IlmHamroh
JavaScript Full-stack/9-qism. JavaScript brauzerda va debugging27/29-dars21 daqiqa
Mundarija (29)

Debugging metodologiyasi: xatoni taxmin bilan emas, tizimli topish

Qisqacha: Debugging metodologiyasi — xatoni tasodifiy o'zgartirishlar bilan emas, tergovchi kabi tizimli topish usuli. Avval xatoni ishonchli takrorlaysiz, keyin doirani toraytirasiz, gipoteza qo'yib uni dalil bilan tekshirasiz. Tuzatishda bir vaqtda faqat bitta narsani o'zgartirasiz va takrorlash qadamlarini qayta sinaysiz.

Bu darsda

  • Xatoni ishonchli takrorlash retseptini yoza olasiz: qadamlar, kutilgan va haqiqiy natija.
  • Izolyatsiya va binar qidiruv bilan xato doirasini bir necha qadamda toraytirasiz.
  • Gipoteza qo'yib, uni console.log yoki debugger bilan tekshirasiz va jurnalga yozasiz.
  • Eng oxirgi o'zgarishni git diff bilan tekshirish va bitta o'zgarish qoidasini qo'llaysiz.
  • Rubber duck usulini va qachon yordam so'rash kerakligini bilasiz.

Oldin bilishingiz kerak: DevTools bilan debug qilish, Muammo yechish metodikasi, dataset, addEventListener asoslari, git diff.

1. Nega bu kerak?

09-qismda DOM, hodisalar, formalar va qulaylik bilan ancha kod yozdingiz. Kod ko'paygan sari xatolar ham ko'payadi — endi ularni qanday topishni o'rganamiz.

«Bahor» saytida yangi sahifa bor: mehmon taom tugmalarini bosadi, pastda buyurtma jami hisoblanadi. Ertalab Jasur aka Azizga yozdi: "Savat buzilibdi, ba'zan jami o'rnida qandaydir NaN chiqyapti. Kecha hammasi joyida edi".

Aziz shoshib qoldi. Avval jami ni let dan var ga o'zgartirdi. Keyin skriptni <head> ga ko'chirdi. Keyin brauzer keshini tozaladi. Bir soatdan keyin savat umuman ishlamay qoldi — endi ikkita xato bor, birinchisi qayerdaligi esa hamon noma'lum.

Bu usulning nomi bor — tasodifiy debugging ("balki shudir?" deb hamma narsani urinib ko'rish). Ba'zan omad keladi, lekin ko'pincha vaqt ketadi va yangi xato qo'shiladi.

Shifokorni eslang. Bemor "boshim og'riyapti" desa, u javondagi hamma dorini birma-bir bermaydi. Avval so'raydi: qachondan, qayeri, nima qilganda kuchayadi. Keyin tahlil buyuradi va natijaga qarab bitta davo tanlaydi. DevTools darsida siz "stetoskop"ni — debugger'ni o'rgangansiz. Bugun shifokorning usulini o'rganamiz.

2. Ilmiy usul: kuzat, taxmin qil, tekshir

Debugging metodologiyasi — xatoni topishning takrorlanadigan tartibi. U fandagi ilmiy usulning o'zi:

  1. Kuzatish — xato aniq qachon va qanday chiqadi?
  2. Gipoteza (hypothesis) — sabab haqidagi tekshirsa bo'ladigan taxmin: "ko'k choy tugmasida narx noto'g'ri yozilgan".
  3. Tajriba — taxminni dalil bilan tekshirish: console.log, debugger, Elements paneli.
  4. Xulosa — gipoteza tasdiqlandimi yoki rad etildimi? Rad etilsa — yangi gipoteza.

Diagrammada sikl yopiq: gipoteza rad etilsa, yangi taxmin bilan qaytasiz. Tuzatishga faqat sabab tasdiqlangandan keyin o'tiladi:

flowchart TD
  A["Xatoni takrorlash"] --> B["Doirani toraytirish"]
  B --> C["Gipoteza"]
  C --> D["Tajriba: log, debugger"]
  D --> E{"Tasdiqlandimi?"}
  E -- "yo'q" --> C
  E -- "ha" --> F["Bitta o'zgarish bilan tuzatish"]
  F --> G["Takrorlash qadamlarini qayta sinash"]

Ikki so'zni farqlab oling. Belgi (symptom) — ko'rinadigan narsa: "jami NaN". Sabab (root cause) — uni keltirib chiqargan joy. Belgini yashirish oson (NaN chiqsa 0 ko'rsat), lekin sabab joyida qoladi va boshqa joyda yana chiqadi. Maqsad doim — sabab.

Tekshirib ko'ring: Aziz "jami NaN bo'lsa, 0 deb yoz" degan if qo'shdi. Ekranda NaN yo'qoldi. Xato tuzatildimi?

Javob

Yo'q. U faqat belgini yashirdi. Mehmon endi noto'g'ri jamini — 0 so'mni — ko'radi, bu NaN dan ham yomon: xato borligi ham sezilmay qoladi. Sabab (narx qayerda buzilayotgani) topilmagan.

3. 1-qadam: xatoni takrorlash

Takrorlab bo'lmaydigan xatoni tuzatib bo'lmaydi: tuzatdingizmi-yo'qmi, tekshira olmaysiz. Shuning uchun birinchi ish — takrorlash (reproduce): xatoni har safar chiqaradigan aniq qadamlarni topish.

Mana Jasur aka ko'rgan sahifa. Tugmalarni bosib ko'ring: avval Osh, keyin Lag'mon — jami 63000 bo'ladi. Endi Ko'k choy ni bosing:

html
<h2>Savat</h2>
<button type="button" data-narx="35000">Osh</button>
<button type="button" data-narx="28000">Lag'mon</button>
<button type="button" data-narx="30000">Manti</button>
<button type="button" data-narx="5 000">Ko'k choy</button>
<p>Jami: <output id="jami">0</output> so'm</p>
<script>
  let jami = 0;
  const jamiOyna = document.querySelector("#jami");
  const tugmalar = document.querySelectorAll("[data-narx]");

  for (const tugma of tugmalar) {
    tugma.addEventListener("click", () => {
      const narx = Number(tugma.dataset.narx);
      jami += narx;
      jamiOyna.textContent = jami;
    });
  }
</script>

Jami o'rnida NaN chiqdi. Konsol esa bo'sh — qizil xato yo'q. Bunday xato eng ayyori: dastur yiqilmaydi, faqat noto'g'ri ishlaydi. Endi yana Osh ni bosing — jami baribir NaN qoladi. NaN ga istalgan son qo'shilsa ham NaN chiqadi (Number turi).

Topilganini retsept qilib yozamiz. Bu — takrorlash retsepti:

Band Mazmuni
Qadamlar 1. Savat sahifasini oching. 2. "Ko'k choy" ni bosing.
Kutilgan natija Jami: 5000 so'm
Haqiqiy natija Jami: NaN so'm, keyingi bosishlarda ham NaN
Muhit (qaysi brauzer, qaysi qurilma) Chrome 154, kompyuter; telefonda ham xuddi shunday

E'tibor bering: Jasur aka "ba'zan" degan edi. Endi "ba'zan" ning aniq ma'nosi bor — "ko'k choy tanlangan har safar". Noaniq "ba'zan" ni aniq qadamga aylantirish — takrorlashning asosiy foydasi.

Ba'zi xatolar har safar chiqmaydi: tarmoq sekin bo'lganda, faqat bitta brauzerda yoki tasodifiy vaqtda. Ularni ham avval "qachon chiqadi?" savoli bilan ushlaysiz: qaysi brauzer, qaysi ekran eni, qaysi ma'lumot. Takrorlash qiyin bo'lsa ham, bu qadamni o'tkazib yubormang.

Tekshirib ko'ring: Nega retseptda "Kutilgan natija" ham yoziladi? Haqiqiysi yetmaydimi?

Javob

Xato — kutilgan va haqiqiy natija orasidagi farq. Kutilganini yozmasangiz, boshqa odam (yoki ertangi o'zingiz) nimani xato deb hisoblaganingizni bilmaydi. Tuzatgandan keyin ham aynan shu qatorga qarab tekshirasiz: endi haqiqiy natija kutilganga tengmi?

4. 2-qadam: izolyatsiya — doirani toraytirish

Izolyatsiya (isolation) — xato chiqadigan eng kichik holatni topish: ortiqcha hamma narsani olib tashlab, xatoni faqat bitta joyga "qamab qo'yish".

Savatda to'rtta tugma bor. Har birini alohida sinaymiz: dars sahifasini yangilang (F5) — jonli oyna boshidan ishlaydi — va faqat bitta tugmani bosing.

Tugma Natija
Osh 35000
Lag'mon 28000
Manti 30000
Ko'k choy NaN

Endi doira ancha tor: muammo uchta tugmada yo'q, faqat bittasida bor. Kodning qolgan qismi — sikl, qo'shish, chiqarish — boshqa tugmalarda to'g'ri ishlayapti. Demak, ko'k choyni boshqalardan farq qiladigan narsani qidirish kerak.

Izolyatsiyaning yana bir foydasi — minimal takrorlash (minimal reproducible example). Bu xatoni ko'rsatadigan eng qisqa kod: ortiqcha uslub, boshqa sahifalar va funksiyalarsiz. Uni yordam so'rash da boshqalarga yuborasiz. Ko'pincha shu qisqa misolni tayyorlayotganda xatoni o'zingiz topib olasiz.

Tekshirib ko'ring: Osh → Ko'k choy → Manti tartibida bosilsa, oxirida nima chiqadi? Bu izolyatsiya uchun qanday ma'lumot beradi?

Javob

NaN. Osh'dan keyin 35000 chiqadi, choy uni NaN ga aylantiradi, manti esa NaN ga qo'shilib yana NaN beradi. Bundan xulosa: "keyingi bosishlar ham buzilyapti" — bu alohida xato emas, choy bergan bitta NaN ning oqibati. Shuning uchun har tugmani alohida, toza sahifada sinash muhim.

5. 3-qadam: gipotezalar jurnali

Doira torayganda xayolga bir nechta taxmin keladi. Ularni boshda saqlamang — gipotezalar jurnaliga yozing. Bu oddiy jadval: taxmin, uni qanday tekshirasiz, natija.

# Gipoteza Qanday tekshiraman Natija
1 Choy tugmasi bosilganda hodisa ishlamaydi Bosganda jami o'zgaradimi? Rad etildi: o'zgaradi (NaN ga)
2 Choy narxi songa to'g'ri aylanmayapti narx ni konsolga chiqarish ?
3 Qo'shishda xato jami ni qo'shishdan oldin va keyin chiqarish ?

Birinchi gipotezani kodga tegmasdan rad etdik: jami o'zgaryapti, demak tinglovchi ishlayapti. Jurnal sizni bitta narsani ikki marta tekshirishdan va "nimalarni sinab ko'rgandim?" degan chalkashlikdan saqlaydi.

Yaxshi gipoteza tekshirsa bo'ladigan bo'ladi. "Kod buzilgan" — gipoteza emas, uni tekshirib bo'lmaydi. "Choy narxi Number() dan keyin NaN bo'lyapti" — gipoteza: bitta console.log ha yoki yo'q deydi.

6. 4-qadam: binar qidiruv

6.1 G'oya: o'rtadan kesish

Ma'lumot tugmadan ekranga to'rt bosqichda yetib boradi:

flowchart LR
  A["data-narx atributi"] --> B["Number() bilan son"]
  B --> C["jami ga qo'shish"]
  C --> D["ekranga chiqarish"]

Har bosqichga console.log qo'yib chiqish mumkin. Lekin tezroq yo'l bor: binar qidiruv — tekshiruvni yo'lning o'rtasiga qo'yish. Natija to'g'ri bo'lsa, xato o'rtadan keyin. Noto'g'ri bo'lsa — o'rtadan oldin. Har tekshiruv qolgan yo'lni ikkiga bo'ladi.

O'yinni eslang: "1 dan 100 gacha son o'yladim, toping". Har safar o'rtadagi sonni aytib "ko'pmi, kammi?" deb so'rasangiz, 7 ta savolda albatta topasiz. 1, 2, 3 deb ketma-ket so'rasangiz — 100 ta savol kerak bo'lishi mumkin.

Binar qidiruv: xatoli joy necha tekshiruvda topiladi
  • 8 qator3 ta tekshiruv
  • 100 qator7 ta tekshiruv
  • 1 000 qator10 ta tekshiruv
  • 10 000 qator14 ta tekshiruv

Manba: Hisob: har tekshiruv qolgan qismni ikkiga bo'ladi (2³ = 8, 2⁷ = 128, 2¹⁰ = 1 024, 2¹⁴ = 16 384)

Kod 10 baravar uzaysa, tekshiruvlar soni bor-yo'g'i 3–4 taga oshadi. Katta loyihada aynan shu xususiyat binar qidiruvni eng kuchli usullardan biriga aylantiradi.

6.2 Savatda sinaymiz

Yo'lning o'rtasi — Number() dan keyingi joy. Bitta console.log qo'shamiz:

html
<button type="button" data-narx="35000">Osh</button>
<button type="button" data-narx="5 000">Ko'k choy</button>
<p>Jami: <output id="jami">0</output> so'm</p>
<script>
  let jami = 0;
  const jamiOyna = document.querySelector("#jami");
  const tugmalar = document.querySelectorAll("[data-narx]");

  for (const tugma of tugmalar) {
    tugma.addEventListener("click", () => {
      const narx = Number(tugma.dataset.narx);
      console.log("narx:", narx); // DEBUG — keyin o'chiriladi
      jami += narx;
      jamiOyna.textContent = jami;
    });
  }
</script>

Bu kodni izolyatsiyadan keyingi minimal ko'rinishga keltirdik: ikki tugma yetadi. Osh ni bosing — konsolda narx: 35000. Ko'k choy ni bosing — narx: NaN.

Xato o'rtadan oldin: son yasalayotganda yoki undan ham oldin. Qo'shish va chiqarish (yo'lning ikkinchi yarmi) aybsiz — jurnaldagi 3-gipoteza rad etildi. Qolgan yarmini yana ikkiga bo'lamiz: Number() ga nima kiryapti? Shu qatorning ustiga ikkinchi log qo'ying:

js
console.log("xom:", tugma.dataset.narx);

"Tahrirlab ko'rish" bilan qo'shib, Ko'k choy ni bosing — konsolda xom: 5 000 va narx: NaN chiqadi. Sabab topildi: atributda 5 000 — orasida bo'sh joy bor. Turlarni o'zgartirish darsidan eslaysiz: Number("1 000") — NaN. Ikki tekshiruvda to'rt bosqichli yo'ldan aybdor joy topildi.

Shu yerda bir savol tug'iladi: logni qaysi qatorga qo'yish kerakligini qanday bilasiz? Javob — ma'lumotning yo'lini chizib oling: qayerdan keladi, qayerdan o'tadi, qayerga chiqadi. Keyin shu yo'lning o'rtasini toping.

Maslahat: Debug uchun qo'shilgan console.log yoniga // DEBUG izohini yozing. Ish tugagach, VS Code'da Ctrl + Shift + F bilan "DEBUG" ni qidirib, hammasini bir zumda topasiz va o'chirasiz.

6.3 Binar qidiruv vaqt bo'yicha: git bisect

Xuddi shu g'oya kod tarixida ham ishlaydi. "Bir oy oldin ishlagan, hozir ishlamayapti, orada 200 ta commit bor" — Git ularni yarmidan bo'lib, sizdan "shu holatda xato bormi?" deb so'raydi. Bu buyruq git bisect deb ataladi va aybdor commitni taxminan 8 qadamda topadi. Uni git bisect darsida to'liq o'rganamiz, hozir bilish shart emas — g'oyasi bugungi binar qidiruvning o'zi.

Tekshirib ko'ring: Funksiyada 40 qator bor, oxirida natija noto'g'ri. Birinchi console.log ni qaysi qatorga qo'yasiz va natija to'g'ri chiqsa, keyingisini qayerga?

Javob

Birinchisi — taxminan 20-qator atrofiga, muhim qiymat hisoblangan joyga. U yerda qiymat to'g'ri bo'lsa, xato 20–40 oralig'ida: keyingi log taxminan 30-qatorga. Noto'g'ri bo'lsa — 10-qatorga. Har safar qolgan oraliq ikkiga bo'linadi.

7. Eng oxirgi o'zgarishni tekshiring

Jasur aka yana bir muhim gap aytgan edi: "Kecha hammasi joyida edi". Bu — tayyor maslahat. Kecha ishlagan narsa bugun buzilgan bo'lsa, sabab ko'pincha orada nima o'zgargan bo'lsa, o'sha.

«Bahor» repozitoriysida git log ga qaraymiz:

bash
git log --oneline

Terminalda:

text
3ca27f0 (HEAD -> main) Menyu: ko'k choyni qo'sh
d349326 Savat: jami hisoblagichini qo'sh

Oxirgi commitni bugun ertalab dizayner Nodira qilgan. U nimani o'zgartirganini git diff ko'rsatadi (HEAD~1 — oxirgidan bitta oldingi commit):

bash
git diff HEAD~1

Terminalda:

text
diff --git a/menyu/index.html b/menyu/index.html
index 5048a40..71796b3 100644
--- a/menyu/index.html
+++ b/menyu/index.html
@@ -2,4 +2,5 @@
 <button type="button" data-narx="35000">Osh</button>
 <button type="button" data-narx="28000">Lag'mon</button>
 <button type="button" data-narx="30000">Manti</button>
+<button type="button" data-narx="5 000">Ko'k choy</button>
 <p>Jami: <output id="jami">0</output> so'm</p>

Bitta qo'shilgan qator — va unda aynan topgan sababimiz. Nodira raqamni chiroyli bo'lsin deb, odamlar o'qiydigan shaklda yozgan. Agar Aziz boshidanoq shu savoldan boshlaganida, xato besh daqiqada topilardi.

Bu usul har doim ham sababni bermaydi. Ba'zan xato kodda ancha oldin bo'lgan, yangi ma'lumot uni faqat endi ko'rsatib qo'ygan. Lekin u eng arzon tekshiruv — birinchi navbatda qiling. Bunga brauzer yangilanishi, yangi paket yoki sozlama ham kiradi: "orada nima o'zgardi?" — faqat kod haqida emas.

8. Tuzatish: bir vaqtda faqat bitta o'zgarish

Sabab tasdiqlandi. Endi tuzatamiz — va faqat bitta narsani o'zgartiramiz.

Ikki yo'l bor: HTML'dagi atributni 5000 qilish yoki kodda bo'sh joyni olib tashlash. Qaysi biri to'g'ri?

data-narx — dastur uchun ma'lumot, uni odam o'qimaydi. Mashina o'qiydigan qiymat sof son bo'lishi kerak. Odamga ko'rinadigan "5 000 so'm" tugmaning matnida yoziladi. Shuning uchun HTML'ni tuzatamiz, kodga tegmaymiz.

html
<button type="button" data-narx="35000">Osh</button>
<button type="button" data-narx="28000">Lag'mon</button>
<button type="button" data-narx="30000">Manti</button>
<button type="button" data-narx="5000">Ko'k choy</button>
<p>Jami: <output id="jami">0</output> so'm</p>
<script>
  let jami = 0;
  const jamiOyna = document.querySelector("#jami");
  const tugmalar = document.querySelectorAll("[data-narx]");

  for (const tugma of tugmalar) {
    tugma.addEventListener("click", () => {
      const narx = Number(tugma.dataset.narx);
      jami += narx;
      jamiOyna.textContent = jami;
    });
  }
</script>

Endi takrorlash retseptini qayta bajaring: Ko'k choy — 5000. Keyin qolgan uchtasini bosing — jami 98000 bo'ladi. Debug uchun qo'shgan console.log lar ham olib tashlandi.

Nega bitta o'zgarish? Aziz ertalab uchta narsani birdan o'zgartirgan edi. Agar xato yo'qolganida ham, uchtasidan qaysi biri yordam berganini bilmas edi. Qolgan ikkitasi esa kodda yangi muammo bo'lib qolardi. Qoida: o'zgartir → takrorlash qadamlarini sina → natijaga qarab keyingi qadam.

Tuzatgandan keyin ikki narsani tekshiring:

  • Xato yo'qoldimi? — takrorlash retsepti endi kutilgan natijani beradi.
  • Boshqa narsa buzilmadimi? — qolgan tugmalar ham to'g'ri. Bu tekshiruv regressiya (regression) — "ilgari ishlagan narsa qaytadan buzilmadimi" — deb ataladi.

Keyinroq bunday tekshiruvlarni qo'lda emas, avtomatik testlar bajaradi. Avtomatik test — kodni o'zingiz o'rningizga tekshiradigan kichik dastur. Uni Birinchi avtomatik test darsida yozamiz, hozir bilish shart emas.

Tekshirib ko'ring: Aziz HTML'ni tuzatdi va yana xavfsizlik uchun kodga .replaceAll(" ", "") ham qo'shdi. Bu bitta o'zgarishmi?

Javob

Yo'q, ikkita. Endi u qaysi tuzatish ishlaganini bilmaydi va kodda keraksiz qator paydo bo'ldi. To'g'ri yo'l: avval bitta tuzatish (HTML) va tekshiruv. Kodni himoyalash kerak bo'lsa — bu alohida qaror, alohida commit bilan.

9. Rubber duck: ovoz chiqarib tushuntirish

Muammo yechish darsida kauchuk o'rdak usuli (rubber duck debugging) bilan tanishgansiz: kodni stol ustidagi o'yinchoqqa qatorma-qator, ovoz chiqarib tushuntirasiz. Debuggingda u ayniqsa kuchli, chunki gipoteza tugab qolganda yordam beradi.

Aziz savat kodini o'rdakka tushuntirib ko'rdi: "Tugma bosildi. dataset.narx dan narxni oldim — bu satr, "5 000". Uni Number ga berdim... to'xta, Number bo'sh joyli satrni songa aylantira oladimi?" Ichida o'ylaganda miya bu qadamni "o'z-o'zidan tushunarli" deb sakrab o'tgan edi. Ovoz chiqarib aytganda — sakrab o'tib bo'lmaydi.

Usulning sharti — har qadamni aytish, "bu yerda hammasi oddiy" deb o'tib ketmaslik. O'rdak o'rniga hamkasb ham bo'ladi, faqat u gapingizni bo'lmasligi kerak. Yordam so'rab xabar yozish ham shunday ishlaydi: xabarni aniq yozayotganda javob ko'pincha o'zi chiqadi.

10. console.log yoki debugger?

Ikkalasi ham gipotezani tekshirish asbobi. DevTools darsida debugger'ni batafsil ko'rgansiz, bu yerda faqat tanlov:

Vaziyat Asbob
Bitta qiymat, bir joyda console.log
Qiymat vaqt o'tib qanday o'zgarishi (har bosishda) console.log yoki logpoint
Ko'p o'zgaruvchi, chalkash oqim Breakpoint va qadamma-qadam
Sikl ichida bitta aniq holat Shartli breakpoint
Kodni o'zgartira olmaysiz (begona sayt) Logpoint

Savat misolida console.log yetarli edi: ikki qiymat, bitta joy. Agar narx o'nta funksiyadan o'tganida, breakpoint qo'yib Call Stack bo'ylab yurish tezroq bo'lardi. Asbob emas, usul muhim: ikkalasi ham "gipotezani dalil bilan tekshir" qadamining bir qismi.

11. Tiqilib qolsangiz

Usul bilan ham ba'zan 30 daqiqa siljish bo'lmaydi. Shunda:

  • Tanaffus qiling. 10–15 daqiqa yuring. Charchagan miya bir xil xatoni qayta-qayta o'qib o'tib ketadi.
  • Taxminlaringizni qayta tekshiring. "Bu funksiya albatta chaqiriladi" — haqiqatan ham shundaymi? Eng ishonchli tuyulgan taxmin ko'pincha aybdor bo'ladi.
  • Yordam so'rang. Xabarga takrorlash retsepti, minimal misol va gipotezalar jurnalini qo'shing (yordam so'rash). "Ishlamayapti" degan xabarga hech kim yordam bera olmaydi; "mana qadamlar, mana nimalarni sinadim" degan xabarga — darhol.

GitHub'da xato haqida xabar (issue) ochishda ham aynan shu tuzilma ishlatiladi: qadamlar, kutilgan va haqiqiy natija, muhit. Repo uchun bunday shablon yasashni Issues va shablonlar darsida ko'rgansiz.

12. Ko'p uchraydigan xatolar

12.1 Takrorlamasdan tuzatish

"Jasur aka NaN dedi — demak Number da muammo" deb darhol kodni o'zgartirish. Xatoni o'zingiz ko'rmagansiz, tuzatdingizmi — bilmaysiz.

Avval o'z ko'zingiz bilan takrorlang va retseptni yozing.

12.2 Belgini yashirish

if (Number.isNaN(jami)) { jami = 0; } — ekran "tuzaldi", hisob esa noto'g'ri.

Belgini emas, sababni toping. Belgini yashiradigan kod xatoni faqat chuqurroqqa ko'madi.

12.3 Ko'p o'zgarishni birdan qilish

Uch joyni o'zgartirib, keyin sinash.

Bitta o'zgarish → sinash. Ish tugagach git diff ga qarang: unda faqat tuzatish qolgan bo'lsin, tasodifiy tajribalar emas.

12.4 "Bu yerda xato bo'lishi mumkin emas"

Eng ishonchli tuyulgan joyni tekshirmaslik: "bu qatorni o'zim yozdim, to'g'ri".

Har taxminni dalil bilan tasdiqlang. Savatdagi xato ham "oddiy HTML qatori" ichida edi.

12.5 Debug izlarini unutib qoldirish

console.log("narx:", narx) saytga chiqib ketdi — mehmonning konsoli sizning xabarlaringizga to'ladi.

// DEBUG belgisi va commitdan oldin git diff ni o'qish.

13. Mashqlar

1-mashq (oson): Tizimli yoki tasodifiy?

Stajyor Sardor bron formasidagi xatoni qidiryapti. Har harakatini "tizimli" yoki "tasodifiy" deb belgilang:

  1. Formani uch marta to'ldirib, xato qaysi maydonda chiqishini yozib oldi.
  2. "Balki kesh" deb brauzerni qayta o'rnatdi.
  3. git log bilan kecha kim nimani o'zgartirganini ko'rdi.
  4. Uchta funksiyani birdan qayta yozdi.
  5. Telefon maydoniga qiymat kirgan joyga console.log qo'ydi.
  6. Xato chiqmasligi uchun xabarni CSS bilan yashirdi.
Yechim
# Javob Nega
1 Tizimli Takrorlash va izolyatsiya
2 Tasodifiy Gipotezasiz, dalilsiz urinish
3 Tizimli Eng oxirgi o'zgarishni tekshirish
4 Tasodifiy Ko'p o'zgarish birdan, sabab noma'lum
5 Tizimli Gipotezani dalil bilan tekshirish
6 Tasodifiy Belgini yashirish, sabab joyida qoldi

2-mashq (o'rta): Bron formasidagi odam soni

Bron qoidasi: bir stolga ko'pi bilan 20 kishi. Mehmonlar shikoyat qilyapti: "3 kishi yozsam ham, ko'p deyapti". Formada sonni o'zgartirib, Tekshirish ni bosing. Avval takrorlash jadvalini to'ldiring: 2, 3, 9, 10, 15, 20, 21 qiymatlarida nima chiqadi? Keyin naqshni toping, gipoteza qo'ying va uni console.log bilan tekshiring.

html
<form id="bron" action="https://example.com/bron"
      method="post" novalidate>
  <label for="odam">Necha kishi?</label>
  <input id="odam" name="odam" type="number"
         min="1" max="20" value="3">
  <button>Tekshirish</button>
  <p id="odam-xato" role="status"></p>
</form>
<script>
  const forma = document.querySelector("#bron");
  const odam = document.querySelector("#odam");
  const xabar = document.querySelector("#odam-xato");

  forma.addEventListener("submit", (event) => {
    event.preventDefault();
    if (odam.value > odam.max) {
      xabar.textContent = `Ko'pi bilan ${odam.max} kishi`;
    } else {
      xabar.textContent = "Joy bor!";
    }
  });
</script>

Ishora: input.value va input.max qanday turdagi qiymat qaytaradi (Forma qiymatlarini o'qish)? Ikki satr qanday taqqoslanadi (Taqqoslash operatorlari)?

Yechim

Takrorlash jadvali:

Qiymat Chiqdi To'g'rimi
2 Joy bor! ha
3, 9 Ko'pi bilan 20 kishi yo'q
10, 15, 20 Joy bor! ha
21 Ko'pi bilan 20 kishi ha

Naqsh: 3 dan 9 gacha bo'lgan bir xonali sonlar xato. Gipoteza: "taqqoslash son bilan emas, satr bilan bo'lyapti". Tekshiruv — if dan oldin:

js
console.log(typeof odam.value, typeof odam.max); // DEBUG

Konsolda string string. Ikki satr lug'at tartibida, belgima-belgi solishtiriladi: "3" va "20" da birinchi belgilar 3 va 2, 3 katta — shuning uchun "3" > "20" rost. "2" esa "20" ning boshi bo'lgani uchun kichik chiqadi. Tuzatish — bitta qator:

js
if (Number(odam.value) > Number(odam.max)) {

Keyin jadvaldagi yettala qiymatni qayta sinang (regressiya). Formadagi raqamli maydonni JS'da odam.valueAsNumber bilan ham o'qish mumkin — u darhol son beradi.

3-mashq (qiyin): Menyuda choy yo'q

Jasur aka: "Saytdagi menyuda ko'k choy ko'rinmayapti, lekin ro'yxatga qo'shganman". Quyidagi sahifada uchta gipoteza bilan jurnal tuzing (ma'lumotda yo'q / chizishda tushib qoladi / CSS yashiryapti), har birini tekshiring va sababni toping. Tuzatishdan keyin regressiya tekshiruvini ham yozing.

html
<style>
  .tugadi { display: none; }
</style>
<ul id="menyu"></ul>
<script>
  const taomlar = [
    { nom: "Osh", narx: 35000, tugadi: false },
    { nom: "Lag'mon", narx: 28000, tugadi: false },
    { nom: "Manti", narx: 30000, tugadi: false },
    { nom: "Ko'k choy", narx: 5000, tugadi: false },
  ];
  const royxat = document.querySelector("#menyu");

  function menyuniChiz() {
    royxat.replaceChildren();
    for (let i = 0; i < taomlar.length - 1; i++) {
      const li = document.createElement("li");
      li.textContent = `${taomlar[i].nom} — ${taomlar[i].narx}`;
      if (taomlar[i].tugadi) {
        li.classList.add("tugadi");
      }
      royxat.append(li);
    }
  }

  menyuniChiz();
</script>

Ishora: ma'lumotdagi elementlar sonini va sahifadagi li lar sonini solishtiring — bu yo'lning o'rtasi.

Yechim

Gipotezalar jurnali:

# Gipoteza Tekshiruv Natija
1 Choy ma'lumotda yo'q console.log(taomlar.length) Rad: 4 ta
2 CSS yashiryapti Elements paneli: choy li si bormi? Rad: li umuman yo'q
3 Chizishda tushib qoladi menyuniChiz dan keyin royxat.children.length Tasdiq: 3 ta

Ma'lumotda 4 ta, sahifada 3 ta — yo'qotish chizishda. Siklga qarasak: i < taomlar.length - 1. i 0, 1, 2 bo'ladi, 3-indeksdagi choyga navbat kelmaydi. Bu — DevTools darsidagi kabi "bittaga xato" (off-by-one). Tuzatish:

js
for (let i = 0; i < taomlar.length; i++) {

Tuzatilgan sahifa:

html
<style>
  .tugadi { display: none; }
</style>
<ul id="menyu"></ul>
<script>
  const taomlar = [
    { nom: "Osh", narx: 35000, tugadi: false },
    { nom: "Lag'mon", narx: 28000, tugadi: false },
    { nom: "Manti", narx: 30000, tugadi: false },
    { nom: "Ko'k choy", narx: 5000, tugadi: false },
  ];
  const royxat = document.querySelector("#menyu");

  function menyuniChiz() {
    royxat.replaceChildren();
    for (let i = 0; i < taomlar.length; i++) {
      const li = document.createElement("li");
      li.textContent = `${taomlar[i].nom} — ${taomlar[i].narx}`;
      if (taomlar[i].tugadi) {
        li.classList.add("tugadi");
      }
      royxat.append(li);
    }
  }

  menyuniChiz();
  console.log(royxat.children.length);
</script>

Konsolda:

text
4

Regressiya: bitta taomga tugadi: true qo'yib ko'ring — u yashirinishi, qolganlari ko'rinishi kerak. Ikkinchi gipoteza ham foydali edi: "tugadi" class'i bilan yashirilgan taom ham "yo'qolgandek" ko'rinadi — u boshqa kungi xatoning sababi bo'lishi mumkin. Sikl for...of bilan yozilganda bu xato umuman bo'lmasdi: u indeks chegarasini o'zi hal qiladi.

4-mashq: Portfolio qadami — debug jurnali va tozalash

09-qism davomida asosiy.js ga ko'p kod qo'shildi, ular orasida "ishladimi?" degan vaqtinchalik tekshiruvlar ham bor. Bugun ularni tizimli tozalaysiz va loyihaga debug jurnalini qo'shasiz.

  1. kurs/portfolio/docs/ ichida debug-jurnal.md yarating. Unga shu qism davomida duch kelgan bitta xatoingizni yozing: takrorlash retsepti, gipotezalar jurnali, sabab, tuzatish. Eslay olmasangiz — birinchi darsdagi null holatini yozing.
  2. VS Code'da sayt/ papkasi bo'yicha Ctrl + Shift + F bilan console.log ni qidiring. Har biriga savol bering: bu mehmon uchun kerakmi yoki faqat "ishladimi?" tekshiruvimi? Vaqtinchaliklarini o'chiring. sahifaniTekshir va joriyHavolaniBelgila dagi console.warn lar qoladi — ular sahifa tuzilmasidagi muammoni ogohlantiradi. Faqat konsolga yozadigan funksiya (masalan Elementlarni tanlash dagi menyuniTop) loglarsiz bo'sh qoladi — uni chaqiruvi bilan birga olib tashlang.
  3. Bitta o'zgarish qoidasi: har o'chirishdan keyin bosh sahifani va 404.html ni Live Server'da ochib, konsolda qizil xato yo'qligini va qo'shgan funksiyalaringiz (menyu, tema tugmasi, forma tekshiruvi) ishlashini tekshiring.
  4. git diff ni o'qing: unda faqat o'chirilgan qatorlar bo'lsin. Keyin npm run check va commit: JS: vaqtinchalik console.log larni olib tashla. Jurnal — alohida commit: Docs: debug jurnalini qo'sh.
Yechim

docs/debug-jurnal.md namunasi:

markdown
# Debug jurnali

## 2026-10-04 — sarlavha o'zgarmaydi

**Takrorlash:** index.html ni oching → h1 da "Menyu" qoladi.
**Kutilgan:** "Bugungi menyu". **Haqiqiy:** "Menyu",
konsolda `Cannot set properties of null`.
**Muhit:** Chrome 154, Live Server.

Gipotezalar:
1. Selektor xato → Console'da querySelector("h1")
   sahifa ochilgach elementni topdi. Rad.
2. Skript HTML'dan oldin ishlaydi → readyState
   logi "loading" dedi. Tasdiq.

**Sabab:** skript `<head>` da, `defer` siz.
**Tuzatish:** `defer` qo'shildi (bitta o'zgarish),
sahifa qayta sinaldi.

Qaysi console.log qolishi mumkin? Odatda — hech biri. Foydalanuvchi uchun xabar sahifaning o'zida chiqadi, konsolda emas. Dasturchiga ogohlantirish kerak bo'lsa — console.warn. Jurnalni har jiddiy xatodan keyin to'ldirib boring: bir necha oydan keyin u sizning shaxsiy "xatolar lug'atingiz" bo'ladi.

14. Real ishda

  • Xato hisoboti (bug report). Jamoada xato GitHub Issues yoki Jira kabi tizimda ochiladi va birinchi so'raladigan narsa — takrorlash qadamlari. Qadamlarsiz hisobot ko'pincha "takrorlanmadi" deb yopiladi.
  • "Ishlamayapti" ga javob. Tajribali dasturchi xabar olganda birinchi uchta savolni beradi: qanday qadamlar, nima kutgan edingiz, nima chiqdi.
  • Production xatolari. Saytdagi xatolar maxsus xizmatlarga (masalan Sentry — kursda alohida o'rganamiz) yig'iladi. Ularni tekshirish ham shu usulda: takrorlash, izolyatsiya, gipoteza (Production xatolari).
  • Postmortem. Katta xatodan keyin jamoa "nima bo'ldi, nega, qanday oldini olamiz" hujjatini yozadi (kursda keyinroq: postmortem) — bu gipotezalar jurnalining katta ko'rinishi.
  • Intervyu. "Eng qiyin topgan xatoingiz haqida gapirib bering" — ko'p uchraydigan savol. Kuchli javob — usul haqida: qanday takrorladingiz, qanday toraytirdingiz, qanday tekshirdingiz.

Xulosa

  • Debugging — ilmiy usul: takrorla, toraytir, gipoteza qo'y, dalil bilan tekshir.
  • Takrorlash retsepti: qadamlar, kutilgan va haqiqiy natija, muhit.
  • Binar qidiruv: tekshiruvni yo'lning o'rtasiga qo'ying — har qadam qolgan yo'lni ikkiga bo'ladi.
  • "Kecha ishlagan edi" bo'lsa — avval git log va git diff: orada nima o'zgardi?
  • Bir vaqtda bitta o'zgarish, keyin takrorlash qadamlari va regressiya tekshiruvi.
  • Belgini emas, sababni tuzating; tiqilsangiz — o'rdakka tushuntiring yoki retsept bilan yordam so'rang.

Keyingi dars: Stack trace va JavaScript xato turlari — qizil xato chiqqanda uning har bir qatorini o'qib, aybdor joyga to'g'ri borishni o'rganamiz.

Manbalar

  • Chrome DevTools: "Debug JavaScript" — developer.chrome.com/docs/devtools
  • MDN: "What went wrong? Troubleshooting JavaScript" — developer.mozilla.org
  • Git: "git-bisect" hujjati — git-scm.com/docs/git-bisect
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Debugging metodologiyasi: xatoni taxmin bilan emas, tizimli topish — IlmHamroh