
Кодын алдааг хэрхэн олох вэ? "Нугаснаас асуу"

Н.Тэмүүлэн
Багш


Н.Тэмүүлэн
Багш
Программын алдааг англиар bug буюу «шавж» гэдэг. Харин алдааг олж засахыг debug буюу «шавжаас цэвэрлэх» гэнэ.
Энэ нэртэй холбоотой сонирхолтой түүх бий. 1947 онд Харвардын их сургуулийн Mark II компьютер дутуу ажиллаад байв. Инженерүүд шалгаад машины дотор гацаж үхсэн жинхэнэ эрвээхэй олжээ. Тэд эрвээхэйг ажлын тэмдэглэлдээ нааж, доор нь «First actual case of bug being found» буюу «Жинхэнэ шавж олдсон анхны тохиолдол» гэж бичжээ. [1]
Инженерүүд жижиг гэмтлийг bug гэж үүнээс олон жилийн өмнөөс нэрлэдэг байсан. Томас Эдисон ч 1870-аад онд цахилгаан хэлхээний «шавж»-ны тухай бичиж байжээ. Харин энэ тэмдэглэл программист Грейс Хоппер болон түүний багийн ачаар алдаршиж, «bug», «debug» гэсэн үгс компьютерийн ерөнхий нэр томьёо болсон. Тэр тэмдэглэл одоо АНУ-ын Смитсонийн музейд хадгалагдаж байна.
Өнөөдрийн алдаанууд тэр эрвээхэй шиг шууд харагддаггүй. Тэд кодын мөрүүдийн дунд нуугдаж байдаг.
Алдааг олохын тулд эхлээд түүнийг таньж сурах хэрэгтэй. Программын алдаа ерөнхийдөө гурван төрөлд хуваагдана.
1. Syntax алдаа (бичлэгийн алдаа). Кодын дүрэм зөрсөн үед гарна. Хаалт дутуу, хашилт мартсан, үгийг буруу бичсэн зэрэг нь хэл зүйн алдаатай адил. Программ огт ажиллахгүй тул хамгийн амархан олддог.

2. Runtime алдаа (ажиллах үеийн алдаа). Код зөв бичигдсэн ч ажиллаж байх явцдаа боломжгүй үйлдэл таараад зогсоно. Жишээ нь, тэгээр хуваах, байхгүй файл нээх.

3. Logic алдаа (логикийн алдаа). Хамгийн асуудалтай нь энэ. Программ асуудалгүй ажиллаж, ямар ч алдааны мессеж гаргахгүй. Гэвч хариу нь буруу байдаг. Компьютер таны хэлсэн зүйлийг яг хийсэн, харин та буруу зүйл хэлсэн гэсэн үг.


Улаан өнгөөр гарсан алдааны мессежийг хараад сандрах хэрэггүй. Энэ бол компьютер танд алдаа хаана байгааг зааж өгч байгаа эрдэнийн сангийн газрын зураг юм. Дээрх тэгээр хуваасан кодыг ажиллуулахад Python ийм мессеж гаргана:
Traceback (most recent call last):
File "main.py", line 3, in <module>
print(too / huvaagch)
~~~~^~~~~~~~~~
ZeroDivisionError: division by zeroИйм мессежийг доороос нь дээш унших нь зөв:

Хамгийн хачин мөртлөө хамгийн үр дүнтэй аргын нэг бол rubber duck debugging буюу «резинэн нугастай debug хийх» арга.
Энэ арга Эндрю Хант, Дэйвид Томас нарын 1999 онд хэвлүүлсэн «The Pragmatic Programmer» номоор алдаршсан. Номд нэгэн программист ширээн дээрээ резинэн нугас тавьж, кодоо түүнд мөр мөрөөр нь тайлбарладаг тухай гардаг. [2]
Арга нь маш энгийн:
Ширээн дээрээ нугас (эсвэл дурын тоглоом, баримал) тавьна.
Код чинь юу хийх ёстойг нугасанд тайлбарлана.
Дараа нь кодоо мөр бүрээр нь, чанга дуугаар тайлбарлана: «Энэ мөр ийм тоо авна, дараагийн мөр түүнийг нэмнэ…»
Хэлж байгаа зүйл чинь кодоосоо зөрүүтэй байгааг анзаарсан мөчид алдаа олдоно.

Яагаад ажилладаг вэ? Дотроо бодохдоо бид «энэ хэсэг мэдээж зөв дөө» гээд алгасаад байдаг. Харин чанга дуугаар тайлбарлахад алхам бүрийг алгасалгүй дахин бодохоос өөр аргагүй. Нугас хариулт өгөхгүй, харин сонсох түвшинд л оролцоно. Хариултыг та өөрөө олно.
Нугас байхгүй бол санаа зовох хэрэггүй. Ангийн найз, гэрийн муур, бүр цэцэгийн сав ч болно. Гол нь бодлоо чанга дуугаар, алхам алхмаар хэлэх.
Бат дөрвөн шалгалтын дундаж оноогоо бодох программ бичлээ. Оноо нь 80, 95, 70, 100 тул дундаж нь 86.25 байх ёстой.
onoo = [80, 95, 70, 100]
niit = 0
for i in range(1, len(onoo)):
niit = niit + onoo[i]
dundaj = niit / len(onoo)
print("Дундаж:", dundaj)Гэтэл программ Дундаж: 66.25 гэж хэвлэв. Алдааны мессеж гараагүй тул энэ бол logic алдаа.
Алхам 1. Хувьсагчид юу болж байгааг хэвлэж харах. Энэ аргыг print debugging гэдэг. Давталт дотор нэг мөр нэмээд дахин ажиллуулна:
for i in range(1, len(onoo)):
print("i =", i, " onoo[i] =", onoo[i])
niit = niit + onoo[i]Гаралт:
i = 1 onoo[i] = 95
i = 2 onoo[i] = 70
i = 3 onoo[i] = 100
Дундаж: 66.25Алхам 2. Нугаснаас асуух. Бат нугасандаа тайлбарлаж эхэллээ: «Давталт оноо бүрийг нэг нэгээр нь нэмнэ. Эхний оноо бол 80… хүлээгээрэй, дэлгэц дээр 80 гэж нэг ч удаа гараагүй байна!»
Энэ мөчид алдаа илэрлээ. Python-д жагсаалтын дугаарлалт 0-ээс эхэлдэг. Харин range(1, ...) нь 1-ээс эхлэсэн тул эхний оноо алгасагдсан байна.

Алхам 3. Засаад дахин шалгах. range(1, len(onoo))-ийг range(len(onoo)) болгон засахад зөв хариу гарна:
Дундаж: 86.25Алдаа олдсоны дараа туслах зорилгоор нэмсэн print мөрүүдээ устгахаа мартуузай.
Алдаа хайхад таамаглаж энд тэнд засахаас илүү дараалалтай ажиллах нь хамаас хурдан.
Алдааг дахин гарга. Алдаа яг ямар үед, ямар оролтоор гардагийг тодорхойл. Дахин дахин гаргаж чадахгүй алдааг засах хэцүү.
Мессежийг анхааралтай унш. Алдааны төрөл, мөрийн дугаарыг тэмдэглэ.
Хайх хүрээгээ нарийсга. print ашиглан кодын дунд хэсэгт утгуудыг шалга. Зөв байвал алдаа доор хагаст нь, буруу байвал дээр хагаст нь байна. Ингэж хагалсаар байгаад алдаатай мөрөнд хүрнэ.
Нэг удаад нэг л зүйлийг өөрчил. Зэрэг олон зүйл засвал аль нь тусалсныг, аль нь шинэ алдаа үүсгэснийг мэдэхгүй.
Засаад дахин шалга. Зөвхөн тэр алдаа биш, программын бусад хэсэг зөв ажиллаж байгаа эсэхийг шалга.
Нэмэлт зөвлөгөө:
Debugger хэрэгсэл ашигла. VS Code, Thonny зэрэг программ кодыг мөр мөрөөр нь ажиллуулж, хувьсагч бүрийн утгыг харуулдаг. Зогсоох цэгийг breakpoint гэнэ.
Амраарай. 10 минут алхаад ирсний дараа нүдэнд тусаагүй алдаа гэнэт ил харагдах нь олон.
Алдаагаа тэмдэглэ. Нэг удаа олсон алдаа дахин гарахад та шууд танина.
Алдаа гаргах нь та муу программист гэсэн үг биш. Дэлхийн хамгийн шилдэг программистууд ч өдөр бүр bug-тай тулгардаг. Тэдний онцлог нь алдааг айдаггүй, тайван, дараалалтайгаар хайдагт л байдаг.
Алдаа бүр танд шинэ зүйл зааж өгдөг. Дээрх жишээнд Бат Python-д дугаарлалт 0-ээс эхэлдгийг хэзээ ч мартахгүй болсон.
Тиймээс дараагийн удаа код тань ажиллахгүй бол сандрахаа болиод ширээн дээрх нугасандаа хандаарай. Нугас чинь хариултыг мэддэггүй ч та мэднэ.
[1] Smithsonian, National Museum of American History — Log Book With Computer Bug
[2] The GitHub Blog — What’s with all the ducks? (2022)