WisarWisar
Dasturlash kitobi/15-QISM — Kasbiy konikmalar41 daqiqa

15.1-bob: Toza kod va refactoring

15-QISM — Kasbiy ko'nikmalar · 1-mavzu


1. Kirish va motivatsiya

Siz endi ko'p texnologiyani bilasiz (0-14 QISM) — ishlaydigan ilova qura olasiz. Lekin ishlaydigan kod va yaxshi kod o'rtasida katta farq bor. Real ishda kod bir marta yoziladi, lekin yuzlab marta o'qiladi (siz va boshqalar — keyinroq tuzatish, qo'shish uchun). Toza kod (clean code) — o'qish oson, tushunish oson, o'zgartirish oson kod. Bu professional dasturchini havaskordan ajratadi: havaskor "ishlaydigan" kod yozadi (o'ziga tushunarli), professional "o'qiladigan" kod yozadi (boshqalarga ham tushunarli, oson o'zgartiriladigan).

Nega bu muhim? Chunki real loyiha uzoq yashaydi (yillar — xususiyatlar qo'shiladi, xatolar tuzatiladi, jamoa o'zgaradi). Iflos kod (chalkash, takror, tushunarsiz) — har o'zgartirish azob (qaerda nima — noaniq, bir joyni tuzatsa boshqasi buziladi). Toza kod — har o'zgartirish oson (aniq struktura, kam takror). Tadqiqotlar ko'rsatadi: dasturchi vaqtining ~70% kod o'qishga ketadi (yozishga emas) — shuning uchun o'qiladigan kod = samaradorlik. Refactoring esa — ishlaydigan kodni (xatti-harakatini o'zgartirmasdan) yaxshilash (toza qilish) — bu doimiy jarayon (kod o'sgani sari toza tutib turish).

Bu bob: toza kod nima va nega, nomlash (o'zgaruvchi/funksiya — eng muhim), funksiyalar (kichik, bitta vazifa), izohlar (qachon kerak/kerakmas), kod hidi (code smell — yomon belgilar), refactoring (texnikalar — extract, rename), va SOLID/DRY/KISS (printsiplar). Bu mavzular ketma-ket, misollar bilan to'liq ochib beriladi.

O'xshatish: Toza kod — bu tartibli oshxona. Ikki oshpaz ham mazali taom pishirishi mumkin (ikkalasi ham "ishlaydi"), lekin biri toza, tartibli ishlaydi (har asbob o'z joyida, idishlar yuvilgan, retsept aniq), ikkinchisi tartibsiz (idishlar uyumda, ingredientlar aralash). Birinchi oshxonada boshqa oshpaz ham kelib oson ishlaydi (hamma narsa joyida, tushunarli); ikkinchisida — faqat o'sha oshpaz biladi qaerda nima, boshqa kishi adashadi. Kod ham shunday: toza kod — boshqa dasturchi (yoki 6 oydan keyingi siz) oson tushunadi va davom ettiradi; iflos kod — faqat yozgan odam biladi (va u ham unutadi). Refactoring — bu oshxonani ishlab turiboq tartibga solish (taomni buzmasdan — idishlarni yuvish, asboblarni joyiga qo'yish). Toza kod — bir marta yozish emas, doimiy tartib.

Nega muhim?

  • Kod ko'p o'qiladi — bir marta yoziladi, yuzlab marta o'qiladi (o'qiladigan = samarali).
  • Loyiha uzoq yashaydi — yillar (xususiyat, xato, jamoa) — toza kod o'zgartirishni oson qiladi.
  • Jamoa — boshqalar (va keyingi siz) kodingizni o'qiydi (tushunarli bo'lishi kerak).
  • Professional belgi — ishlaydigan kod (havaskor) vs o'qiladigan kod (professional).

2. Nazariya — chuqur tushuntirish

2.1. Toza kod nima va printsiplar

text
  TOZA KOD — o'qish/tushunish/o'zgartirish OSON kod:

  TOZA KOD BELGILARI:
   O'QILADI (kod o'zini tushuntiradi — izoh kam kerak)
   ODDIY (murakkab emas — eng sodda yechim)
   ANIQ NOM (o'zgaruvchi/funksiya nima qilishini aytadi)
   KICHIK (funksiya bitta vazifa — kalta)
   TAKROR YO'Q (DRY — bir mantiq bir joyda)
   IZCHIL (bir xil uslub butun loyihada)

  ASOSIY PRINTSIPLAR:
   KISS (Keep It Simple) — sodda tut (murakkablik dushman)
   DRY (Don't Repeat Yourself) — takrorlama (bir mantiq bir joy)
   YAGNI (You Aren't Gonna Need It) — kerakmasini yozma (kelajak uchun "ehtimol")
   SOLID (5 printsip — 2.7)

   Toza kod — o'qish/o'zgartirish oson (aniq nom, kichik funksiya, takror yo'q, sodda)
   Printsiplar — KISS (sodda), DRY (takrorlama), YAGNI (kerakmasini yozma), SOLID

Toza kod nima va printsiplar — toza kodning asosiy xususiyatlari. Toza kod — o'qish, tushunish, o'zgartirish oson kod. Belgilari: (1) o'qiladi (kod o'zini tushuntiradi — izoh kam kerak, nom va struktura aniq); (2) oddiy (murakkab emas — eng sodda yechim, ortiqcha murakkablik yo'q); (3) aniq nom (o'zgaruvchi/funksiya nima qilishini nomidan bilish mumkin); (4) kichik (funksiya bitta vazifa — kalta, oson tushuniladi); (5) takror yo'q (DRY — bir mantiq bir joyda — o'zgartirsa bir joyda); (6) izchil (bir xil uslub butun loyihada — o'qish oson). Asosiy printsiplar: (1) KISS (Keep It Simple, Stupid — sodda tut — murakkablik dushman, eng sodda ishlaydigan yechim); (2) DRY (Don't Repeat Yourself — takrorlama — bir mantiq bir joyda — takror = o'zgartirsa hamma joyni topib o'zgartirish, xato); (3) YAGNI (You Aren't Gonna Need It — kerakmasini yozma — "kelajakda kerak bo'lar" deb ortiqcha kod yozma — kerak bo'lganda yozasiz); (4) SOLID (5 printsip — 2.7). Ikki nuqta: (1) toza kod — o'qish/o'zgartirish oson (aniq nom, kichik funksiya, takror yo'q, sodda); (2) printsiplar — KISS (sodda), DRY (takrorlama), YAGNI (kerakmasini yozma), SOLID. Bu printsiplar — toza kodning "qonunlari" (har biri kodni yaxshilaydi). Eng muhim — KISS va DRY (sodda tut, takrorlama — eng keng qo'llaniladi). Toza kod — bir martalik emas (doimiy odat — har funksiya yozganda "bu o'qiladimi? soddami? takror yo'qmi?"). Bu — professional kod yozishning asosi (ishlaydigan emas — yaxshi ishlaydigan).

2.2. Nomlash (eng muhim)

text
  NOMLASH — toza kodning ENG MUHIM qismi (kod o'qilishi nomga bog'liq):

   YOMON NOMLAR:
  const d = 5;                    // d nima? (noaniq)
  const list = getUsers();        // qanday list? (umumiy)
  function process(data) {...}     // nimani process? (noaniq)
  const flag = true;              // qanday flag?

   YAXSHI NOMLAR (niyatni aytadi):
  const daysUntilExpiry = 5;      // aniq — nima ekani
  const activeUsers = getUsers(); // qanday user
  function validateEmail(email) {...}  // nima qiladi
  const isEmailVerified = true;   // qanday holat

  NOMLASH QOIDALARI:
   Niyatni ayt (nima/nega — "daysUntilExpiry" > "d")
   Funksiya — fe'l (getUser, calculateTotal, isValid)
   O'zgaruvchi — ot (user, total, items)
   Boolean — is/has/can (isActive, hasPermission, canEdit)
   Izchil (getUser/getUsers — bir xil naqsh; fetchUser/getUser aralashma)
   Qisqartma yo'q (calc  calculate; usr  user)

   Nomlash — eng muhim (kod o'qilishi nomga bog'liq — yaxshi nom = izohsiz tushunarli)
   Niyat (nima/nega), fe'l (funksiya), is/has (boolean), izchil, qisqartmasiz

Nomlash (eng muhim) — toza kodning eng muhim, eng ko'p ta'sirli qismi. Kod o'qilishi asosan nomga bog'liq (yaxshi nom — izohsiz tushunarli; yomon nom — izoh ham yetmaydi). Yomon nomlar: d (nima? — noaniq), list (qanday list? — umumiy), process(data) (nimani process? — noaniq), flag (qanday flag?). Yaxshi nomlar (niyatni aytadi): daysUntilExpiry (aniq — necha kun qoldi), activeUsers (qanday user — faol), validateEmail(email) (nima qiladi — email tekshiradi), isEmailVerified (qanday holat — email tasdiqlanganmi). Nomlash qoidalari: (1) niyatni ayt (nima/nega — daysUntilExpiry > d — nom o'zini tushuntiradi); (2) funksiya — fe'l (getUser, calculateTotal, isValid — amal); (3) o'zgaruvchi — ot (user, total, items — narsa); (4) boolean — is/has/can (isActive, hasPermission, canEdit — savol/holat); (5) izchil (getUser/getUsers — bir xil naqsh; fetchUser/getUser aralashtirma — chalkash); (6) qisqartma yo'q (calc calculate, usr user — to'liq, aniq — qisqartma noaniq); (7) izlanadigan (searchable — MAX_RETRIES ni butun loyihada qidirib topish mumkin, lekin 5 raqamini yoki e o'zgaruvchisini qidirib bo'lmaydi — bir harfli/sehrli nom qidiruvda yo'qoladi — mazmunli nom = izlanadigan); (8) aldamas (non-misleading — nom haqiqatni aytsin — userList aslida Map bo'lsa aldamchi (accounts de); getUsers() DBga yozsa aldamchi — nom mazmunga mos bo'lsin, aks holda o'quvchini chalg'itadi). Ikki nuqta: (1) nomlash — eng muhim (kod o'qilishi nomga bog'liq — yaxshi nom = izohsiz tushunarli — bu eng katta ta'sir); (2) niyat (nima/nega), fe'l (funksiya), is/has (boolean), izchil, qisqartmasiz. Nomlash — toza kodning eng muhim, lekin ko'pincha e'tiborsiz qoldiriladigan qismi (dasturchi "ishlaydi-ku" deb d, temp, data yozadi). Yaxshi nom — kelajakdagi o'zi va boshqalar uchun sovg'a (kod o'qishda "bu nima?" savoli kamayadi). "Yaxshi nom topish — qiyin, lekin arziydi" (Phil Karlton: "kompyuter fanida ikki qiyin narsa — kesh invalidatsiya va nom qo'yish"). Vaqt sarflab yaxshi nom toping (qisqa, aniq, niyatli).

2.3. Funksiyalar (kichik, bitta vazifa)

text
  FUNKSIYALAR — kichik, BITTA vazifa (Single Responsibility):

   YOMON — katta funksiya, ko'p vazifa:
  function handleUser(user) {
    // validatsiya (50 qator)
    // DB'ga saqlash (30 qator)
    // email yuborish (20 qator)
    // log yozish (10 qator)
  }   // 110 qator, 4 vazifa — tushunish/test/o'zgartirish qiyin

   YAXSHI — kichik, har biri bitta vazifa:
  function registerUser(user) {
    validateUser(user);          // bitta vazifa
    const saved = saveUser(user);
    sendWelcomeEmail(saved);
    return saved;
  }
  // har funksiya — bitta ish (o'qish/test/qayta ishlatish oson)

  FUNKSIYA QOIDALARI:
   BITTA vazifa (Single Responsibility — bir ish qil)
   KICHIK (ideal <20 qator — bir ekranda ko'rinsin)
   KAM parametr (ideal 0-2; 3+ — obyekt yoki bo'lish)
   Abstraksiya darajasi bir xil (yuqori mantiq + past detal aralashmasin)
   Yon ta'sir kam (pure function afzal — 2.8: FP)

   Funksiya — kichik + bitta vazifa (o'qish/test/qayta ishlatish oson)
   Katta funksiya — bir necha kichik funksiyaga bo'l (extract)

Funksiyalar (kichik, bitta vazifa) — toza funksiya yozish. Yomon funksiya — katta, ko'p vazifa: handleUser (validatsiya + DB + email + log — 110 qator, 4 vazifa) — tushunish qiyin (bir vaqtda ko'p narsa), test qiyin (hammasini birga), o'zgartirish xavfli (bir qismni o'zgartirsa boshqasiga ta'sir). Yaxshi funksiya — kichik, har biri bitta vazifa: registerUser faqat muvofiqlashtiradi (validateUser, saveUser, sendWelcomeEmail — har biri alohida funksiya, bitta ish) — har funksiya o'qish/test/qayta ishlatish oson. Funksiya qoidalari: (1) bitta vazifa (Single Responsibility — bir funksiya bir ish qiladi — nomidan bilinadi); (2) kichik (ideal <20 qator — bir ekranda ko'rinsin — uzun funksiya = ko'p vazifa); (3) kam parametr (ideal 0-2; 3+ parametr — obyektga birlashtir yoki funksiyani bo'l — ko'p parametr chalkash); (4) abstraksiya darajasi bir xil (yuqori mantiq — saveUser() — va past detal — db.query("INSERT...") — bir funksiyada aralashmasin — bir daraja); (5) yon ta'sir kam (pure function afzal — kirish chiqish, tashqi holatni o'zgartirmaydi — test/tushunish oson — 2.8 FP, 2.15 functional); (6) komanda-so'rov ajratish (command-query separation — funksiya yo biror narsa qiladi (komanda — holatni o'zgartiradi, hech narsa qaytarmaydi), yo biror narsa qaytaradi (so'rov — savolga javob, yon ta'sirsiz), lekin ikkalasini birga emas — masalan isUserActive(user) faqat boolean qaytarsin, ichida holatni o'zgartirmasin — aralash funksiya (qiymat qaytaradi VA yon ta'sir qiladi) chalkash va xatarli). Ikki nuqta: (1) funksiya — kichik + bitta vazifa (o'qish/test/qayta ishlatish oson — Single Responsibility); (2) katta funksiya — bir necha kichik funksiyaga bo'l (extract — 2.6 refactoring). Kichik funksiyalar — toza kodning asosi (har biri tushunarli, test qilinadigan, qayta ishlatiladigan). Katta funksiya — eng keng code smell (ko'p vazifa — chalkash). "Funksiya bir narsa qilishi kerak. Yaxshi qilishi kerak. Faqat shu narsani qilishi kerak" (Robert Martin — Clean Code). Kichik, fokuslangan funksiyalar — o'qiladigan, ishonchli kod.

2.4. Izohlar (qachon kerak/kerakmas)

text
  IZOHLAR — qachon KERAK, qachon KERAKMAS (yaxshi kod o'zini tushuntiradi):

   YOMON IZOH (kod nima qilishini takrorlaydi — keraksiz):
  // i ni 1 ga oshir
  i++;
  // user ni qaytar
  return user;
   kod o'zini aytadi (izoh shovqin); YOKI yomon nom (izoh o'rniga yaxshi nom)

   YAXSHI IZOH (NEGA — kod aytmaydigan):
  // Stripe webhook 2 marta keladi (idempotency kerak) — shuning uchun tekshir
  if (await isProcessed(event.id)) return;
  //  NEGA shunday (qaror sababi, kontekst, ogohlantirish)

  IZOH QOIDALARI:
   NEGA izohla (nima emas — kod nimani aytadi, nega aytmaydi)
   Yaxshi nom > izoh (izoh o'rniga aniq nom)
   TODO/FIXME (kelajak ish — vaqtincha)
   Murakkab algoritm/qaror (nega bu yondashuv)
   Eskirgan izoh xavfli (kod o'zgardi, izoh eski — chalkash)
   Zombi kod (izohga olingan kod — o'chir, git'da tarix bor)

   Izoh — NEGA (kod NIMA'ni aytadi); yaxshi kod kam izoh kerak (nom o'zini tushuntiradi)
   Yomon izoh — kodni takrorlash, eskirgan, zombi kod (o'chir)

Izohlar (qachon kerak/kerakmas) — izohlarni to'g'ri ishlatish. Yaxshi kod o'zini tushuntiradi (nom, struktura) — shuning uchun izoh kam kerak. Yomon izoh (kod nima qilishini takrorlaydi — keraksiz): // i ni 1 ga oshir + i++ (kod o'zi aytadi — izoh shovqin), // user ni qaytar + return user (keraksiz) — bu izohlar foydasiz (kod o'qiladi — izoh takror); yoki yomon nom belgisi (izoh o'rniga yaxshi nom qo'y — daysUntilExpiry izohni keraksiz qiladi). Yaxshi izoh (nega — kod aytmaydigan): // Stripe webhook 2 marta keladi (idempotency kerak) + tekshiruv — bu izoh nega shunday qilinganini aytadi (kod "tekshir" deydi, lekin nega — webhook takrorlanishi — izoh aytadi). Izoh qoidalari: (1) nega izohla (nima emas — kod "nima"ni aytadi, kod "nega"ni aytmaydi — qaror sababi); (2) yaxshi nom > izoh (izoh o'rniga aniq nom — // faol foydalanuvchilar + list o'rniga activeUsers); (3) TODO/FIXME (kelajak ish — vaqtincha belgi); (4) murakkab algoritm/qaror (nega bu yondashuv — kontekst); (5) eskirgan izoh xavfli (kod o'zgardi, izoh eski — chalkash — izohga ishonmasdan kodni o'qishga majbur); (6) zombi kod (izohga olingan kod — // const old = ... — o'chir — git tarixida bor — keraksiz shovqin). Ikki nuqta: (1) izoh — nega (kod nima'ni aytadi); yaxshi kod kam izoh kerak (nom/struktura o'zini tushuntiradi); (2) yomon izoh — kodni takrorlash, eskirgan izoh, zombi kod (o'chir). Izoh — "kerakli yomonlik" (Robert Martin) — har izoh kod o'zini tushuntira olmagan joy belgisi. Eng yaxshi kod — o'zini tushuntiradigan (izohsiz aniq), izoh faqat nega (kontekst, qaror, ogohlantirish — kod ayta olmaydigan). Ko'p izoh — ko'pincha yomon kod belgisi (toza kod izohga muhtoj emas). To'g'ri: aniq nom + kichik funksiya (o'zini tushuntiradi) + nega-izoh (zarur kontekst).

2.5. Kod hidi (code smell)

text
  KOD HIDI (code smell) — yomon kod BELGILARI (xato emas, lekin yaxshilash kerak):

  KENG KOD HIDLARI:
  1. TAKROR KOD (duplication) — bir mantiq ko'p joyda (DRY buzilgan)
  2. UZUN FUNKSIYA — ko'p vazifa (>50 qator — 2.3)
  3. UZUN PARAMETR RO'YXATI — 4+ parametr (chalkash)
  4. KATTA CLASS/FAYL — ko'p mas'uliyat (God object)
  5. CHUQUR NESTING — ko'p ichma-ich if/for (3+ — o'qish qiyin)
  6. SEHRLI RAQAM/SATR — `if (status === 3)` (3 nima? — const STATUS_ACTIVE)
  7. YOMON NOM — d, temp, data 2.2-bob
  8. O'LIK KOD — ishlatilmaydigan kod (o'chir)
  9. ZICH BOG'LANISH — bir o'zgartirish ko'p joyga ta'sir
  10. FEATURE ENVY — metod boshqa obyekt ma'lumotiga o'ch (u yerga ko'chir)
  11. PRIMITIVE OBSESSION — hamma narsa string/number (Money, Email tipi yo'q)
  12. SHOTGUN SURGERY — bitta o'zgarish ko'p faylni o'zgartirtiradi (tarqoq)

   Kod hidi — yomon kod belgisi (xato emas, lekin yaxshilash kerak — refactoring)
   Keng: takror, uzun funksiya, sehrli raqam, chuqur nesting, yomon nom

Kod hidi (code smell) — yomon kodning belgilari. Kod hidi — kodda "nimadir noto'g'ri" degan belgi (xato emas — kod ishlaydi, lekin yaxshilash kerak — refactoring talab qiladi). Keng kod hidlari: (1) takror kod (duplication — bir mantiq ko'p joyda — DRY buzilgan — o'zgartirsa hamma joyni topish kerak — xato); (2) uzun funksiya (ko'p vazifa — >50 qator — 2.3); (3) uzun parametr ro'yxati (4+ parametr — chalkash — obyektga birlashtir); (4) katta class/fayl (ko'p mas'uliyat — "God object" — hamma narsani qiladi — bo'l); (5) chuqur nesting (ko'p ichma-ich if/for — 3+ daraja — o'qish qiyin — early return yoki extract bilan tekisla); (6) sehrli raqam/satr (magic number — if (status === 3)3 nima? — const STATUS_ACTIVE = 3 — nomlangan const); (7) yomon nom (d, temp, data — 2.2); (8) o'lik kod (dead code — ishlatilmaydigan funksiya/o'zgaruvchi — o'chir — shovqin); (9) zich bog'lanish (tight coupling — bir o'zgartirish ko'p joyga ta'sir — modullar bir-biriga juda bog'liq); (10) feature envy (havas — metod o'z klassidan ko'ra boshqa obyektning ma'lumotini ko'proq ishlatadi — masalan Order metodi doim customer.getX(), customer.getY() chaqiradi — mantiq aslida Customerga tegishli — o'sha yerga ko'chirish kerak); (11) primitive obsession (ibtidoiy tiplarga yopishish — hamma narsa string/number — pul number, email string, telefon string — alohida Money, Email tipi yo'q — bu tekshiruv/mantiqni tarqatadi, xato tug'diradi — kichik qiymat-obyekt (value object) yechadi); (12) shotgun surgery (o'q otishday jarrohlik — bitta mantiqiy o'zgarish ko'p faylni birdan o'zgartirtiradi — masalan yangi maydon qo'shsangiz 8 ta joyni yangilash kerak — mantiq tarqoq — bir joyga jamlash kerak — bu takror/zich bog'lanishning natijasi). Ikki nuqta: (1) kod hidi — yomon kod belgisi (xato emas — ishlaydi, lekin yaxshilash kerak — refactoring); (2) keng — takror, uzun funksiya, sehrli raqam, chuqur nesting, yomon nom. Kod hidlarini tanish — refactoring qachon kerakligini bilish (hid sezilsa — yaxshilash vaqti). Bu hidlar zararni darrov keltirmaydi (kod ishlaydi), lekin to'planadi (texnik qarz — technical debt — vaqt o'tgani sari kod chalkashadi, o'zgartirish qiyinlashadi). Kod hidlarini payqash va tuzatish (refactoring — 2.6) — kodni sog'lom tutadi (qarz to'planmasin). Professional dasturchi kod hidlarni sezadi ("bu takror — DRY buzilgan", "bu funksiya juda katta") va tuzatadi (refactoring). Kod hidi — refactoring'ning "signali".

2.6. Refactoring (texnikalar)

text
  REFACTORING — kodni XATTI-HARAKATINI O'ZGARTIRMASDAN yaxshilash:

  TA'RIF: kod ISHLASHINI saqlab (test bilan), STRUKTURASINI yaxshilash
   "ishlaydigan kod"ni "yaxshi ishlaydigan kod"ga (toza)

  KENG REFACTORING TEXNIKALARI:
  1. EXTRACT FUNCTION — katta funksiyadan kichik ajratish 2.3-bob
  2. RENAME — yaxshi nom (d  daysUntilExpiry — 2.2)
  3. EXTRACT VARIABLE — murakkab ifodani nomli o'zgaruvchiga
     if (user.age > 18 && user.verified)  const canAccess = ...; if (canAccess)
  4. REPLACE MAGIC NUMBER — sehrli raqamni const (status === 3  STATUS_ACTIVE)
  5. GUARD CLAUSE / EARLY RETURN — chuqur nestingni tekislash:
     if (x) { if (y) {...} }  if (!x) return; if (!y) return; ...
  6. EXTRACT CLASS/MODULE — katta classni bo'lish
  7. INLINE — keraksiz oraliqni yo'qotish (extract'ning teskarisi):
     const x = getPrice(); return x;    return getPrice();
  8. INTRODUCE PARAMETER OBJECT — ko'p parametrni obyektga:
     f(name, email, age, city)    f(user: UserData)
  9. REPLACE CONDITIONAL WITH POLYMORPHISM — katta switch/if'ni polimorfizm:
     switch(type){case A:..case B:..}    har tip alohida class + umumiy metod

  XAVFSIZ REFACTORING:
   TEST bilan (refactoring xatti-harakatni o'zgartirmaydi — test buni kafolatlaydi)
   Kichik qadamlar (bir o'zgartirish  test  keyingi)
   Versiya nazorati (git — orqaga qaytarish mumkin)

   Refactoring — xatti-harakatni saqlab (test) strukturani yaxshilash (toza)
   Texnikalar — extract function/variable, rename, magic number, guard clause

Refactoring (texnikalar) — ishlaydigan kodni yaxshilash. Refactoring — kodning xatti-harakatini o'zgartirmasdan (test bilan kafolatlangan) strukturasini yaxshilash (toza qilish) — "ishlaydigan kod"ni "yaxshi ishlaydigan kod"ga. Keng texnikalar: (1) Extract Function (katta funksiyadan kichik ajratish — 2.3 — bir bo'lakni alohida funksiyaga); (2) Rename (yaxshi nom — d daysUntilExpiry — 2.2); (3) Extract Variable (murakkab ifodani nomli o'zgaruvchiga — if (user.age > 18 && user.verified) const canAccess = user.age > 18 && user.verified; if (canAccess) — o'qish oson, niyat aniq); (4) Replace Magic Number (sehrli raqamn const — status === 3 STATUS_ACTIVE — 2.5); (5) Guard Clause / Early Return (chuqur nestingni tekislash — if (x) { if (y) {...} } if (!x) return; if (!y) return; ... — ichma-ich kamayadi, o'qish oson); (6) Extract Class/Module (katta classni bo'lish — bir necha kichik); (7) Inline (Extract'ning teskarisi — keraksiz oraliq o'zgaruvchi yoki funksiyani yo'qotish — const x = getPrice(); return x; return getPrice(); — agar oraliq nom hech narsa qo'shmasa, olib tashlash kodni soddalashtiradi); (8) Introduce Parameter Object (uzun parametr ro'yxatini bitta obyektga birlashtirish — createUser(name, email, age, city) createUser(data: UserData) — kam parametr, o'qish oson, kelajakda yangi maydon qo'shish oson — 2.3 uzun parametr smell'ini yechadi); (9) Replace Conditional with Polymorphism (katta switch/if-else zanjirini polimorfizm bilan almashtirish — switch(shape.type){ case "circle":.. case "square":.. } o'rniga har tip alohida class va umumiy area() metodi — yangi tip qo'shganda switchni topib o'zgartirish emas, yangi class qo'shish — 2.7 Open/Closed bilan bog'liq). Xavfsiz refactoring: (1) test bilan (refactoring xatti-harakatni o'zgartirmaydi — test buni kafolatlaydi — refactoring oldidan/keyin test o'tsa — ishlash saqlangan — 11.17 test); (2) kichik qadamlar (bir o'zgartirish test keyingi — katta o'zgartirish xavfli); (3) versiya nazorati (git — orqaga qaytarish mumkin — 4-QISM). Ikki nuqta: (1) refactoring — xatti-harakatni saqlab (test) strukturani yaxshilash (toza — funksionallik o'zgarmaydi, kod yaxshilanadi); (2) texnikalar — extract function/variable, rename, magic number, guard clause, extract class. Refactoring — doimiy jarayon (bir martalik "katta tozalash" emas — har kod o'zgartirishda biroz yaxshilash — "boy scout rule": "joyni o'zingiz topganingdan tozaroq qoldir"). Test bilan refactoring — xavfsiz (test ishlashni kafolatlaydi — refactoring buzmaydi). Test'siz refactoring — xavfli (yaxshilash o'rniga buzish mumkin — bilmay). Refactoring — toza kodni saqlash usuli (kod o'sgani sari toza tutib turish — qarz to'planmasin). IDE'lar (VS Code) refactoring'ni avtomatlashtiradi (Rename — F2, Extract Function — avtomatik). Bu — kod sifatini doimiy yaxshilashning asosi.

2.7. SOLID printsiplari

text
  SOLID — obyekt-yo'naltirilgan dizayn 5 printsipi (toza arxitektura):

  S — SINGLE RESPONSIBILITY (bitta mas'uliyat):
   class/funksiya BITTA sabab uchun o'zgarsin (bitta vazifa — 2.3)

  O — OPEN/CLOSED (ochiq/yopiq):
   kengaytirishga OCHIQ, o'zgartirishga YOPIQ (yangi xususiyat — yangi kod,
     mavjudni o'zgartirmasdan)

  L — LISKOV SUBSTITUTION (Liskov almashtirish):
   ota class o'rniga bola class ishlatsa — buzilmasin (to'g'ri meros)

  I — INTERFACE SEGREGATION (interfeys ajratish):
   kichik, maxsus interfeys (katta "hamma narsa" interfeys emas)

  D — DEPENDENCY INVERSION (bog'liqlik teskari):
   abstraksiyaga bog'lan (konkret emas) — 8-QISM DI

   SOLID — toza OOP dizayn 5 printsipi (Single Responsibility eng keng)
   Maqsad — o'zgartirish oson, kengaytiriladigan, kam bog'liq kod

SOLID printsiplari — toza obyekt-yo'naltirilgan dizayn (9-QISM bilan ko'prik). SOLID — besh printsip (har harf bir printsip): (1) S — Single Responsibility (bitta mas'uliyat): class/funksiya bitta sabab uchun o'zgarsin (bitta vazifa — 2.3 — masalan User class ham foydalanuvchi ma'lumotini, ham email yuborishni qilmasin — alohida); (2) O — Open/Closed (ochiq/yopiq): kod kengaytirishga ochiq, o'zgartirishga yopiq (yangi xususiyat qo'shganda — yangi kod yoz, mavjud kodni o'zgartirma — masalan yangi to'lov usuli — yangi class, eski o'zgarmasin); (3) L — Liskov Substitution: ota class o'rniga bola class ishlatsa — kod buzilmasin (to'g'ri meros — bola ota'ning shartnomasiga rioya qilsin — masalan Bird fly() bo'lsa, Penguin extends Bird muammo — uchmaydi); (4) I — Interface Segregation: kichik, maxsus interfeys (katta "hamma narsa" interfeys o'rniga — mijoz faqat kerakli metodlarga bog'liq bo'lsin); (5) D — Dependency Inversion: abstraksiyaga bog'lan (konkret implementatsiyaga emas — 8-QISM Dependency Injection — masalan EmailService interface'ga bog'lan, konkret GmailServicega emas — almashtirish oson). Ikki nuqta: (1) SOLID — toza OOP dizayn 5 printsipi (Single Responsibility eng keng, eng muhim); (2) maqsad — o'zgartirish oson, kengaytiriladigan, kam bog'liq kod. SOLID — katta loyiha arxitekturasi uchun (9-QISM — Clean Architecture, design patterns bilan chuqur). Boshlang'ich uchun — Single Responsibility eng muhim (har class/funksiya bitta ish — toza, tushunarli). Qolganlari (Open/Closed, DI) — katta, o'sayotgan loyiha uchun (moslashuvchanlik). SOLID — qattiq qoidalar emas (har joyda majburiy emas — over-engineering xavfi — YAGNI — 2.1), balki yo'naltiruvchi printsiplar (kod o'zgartirish oson, kengaytiriladigan bo'lsin). 9-QISM (Arxitektura)da chuqur — bu yerda toza kod kontekstida (har funksiya/class bitta vazifa — eng amaliy). SOLID — professional dasturchi bilishi kerak (ish suhbatida ham so'rashadi).

2.8. Toza kod amalda va best practices

text
  TOZA KOD AMALDA — qachon, qancha (balans):

  BALANS (over-engineering xavfi):
   Toza kod MUHIM, lekin OVER-ENGINEERING (ortiqcha murakkablik) — yomon
   YAGNI — kerakmasini abstraksiya qilma (2 marta takror — OK; 3+ — DRY)
   Pragmatik — toza, lekin amaliy (mukammallik dushman — "yetarli toza")

  QACHON REFACTORING:
   Kod hidi sezilsa (takror, uzun funksiya — 2.5)
   Xususiyat qo'shishdan oldin (toza qil, keyin qo'sh)
   Boy scout rule (har joyda biroz tozaroq qoldir)
   Ishlab turgan, tegilmaydigan kodni "shunchaki" refactoring qilma

  BEST PRACTICES:
   Aniq nom (eng muhim — 2.2)
   Kichik funksiya, bitta vazifa 2.3-bob
   Nega-izoh (kod nima'ni aytadi — 2.4)
   DRY, KISS, YAGNI 2.1-bob
   Test bilan refactoring (xavfsiz — 2.6)
   Izchil uslub (linter — 15.3)

   Toza kod — balans (toza, lekin over-engineering emas — pragmatik, "yetarli toza")
   Refactoring — kod hidi/xususiyatdan oldin (ishlab turganni "shunchaki" emas)

Toza kod amalda va best practices — toza kodni pragmatik qo'llash. Balans (over-engineering xavfi): toza kod muhim, lekin over-engineering (ortiqcha murakkablik — har narsani abstraksiya qilish, kerakmas naqshlar) ham yomon. YAGNI 2.1-bob — kerakmasini abstraksiya qilma (masalan 2 marta takror — OK (hali DRY shart emas); 3+ marta — DRY qil — "rule of three"). Pragmatik — toza, lekin amaliy (mukammallik dushman — "yetarli toza" — cheksiz refactoring emas — ish bajarilsin). Qachon refactoring: (1) kod hidi sezilsa (takror, uzun funksiya — 2.5); (2) xususiyat qo'shishdan oldin (toza qil, keyin yangi qo'sh — toza asosga qo'shish oson); (3) "boy scout rule" (har joyda — kod ustida ishlaganda — biroz tozaroq qoldir); (4) ishlab turgan, tegilmaydigan kodni "shunchaki" refactoring qilma (xavf — ishlayotgan kodni buzish — sabab bo'lmasa tegma). Best practices (butun bobni umumlashtiradi): aniq nom (eng muhim — 2.2), kichik funksiya/bitta vazifa 2.3-bob, nega-izoh 2.4-bob, DRY/KISS/YAGNI 2.1-bob, test bilan refactoring 2.6-bob, izchil uslub (linter — 15.3). Ikki nuqta: (1) toza kod — balans (toza, lekin over-engineering emas — pragmatik, "yetarli toza" — mukammallik emas); (2) refactoring — kod hidi/xususiyat qo'shishdan oldin (ishlab turganni "shunchaki" emas — xavf). Toza kod — odat (har funksiya yozganda biroz e'tibor — nom, hajm, takror), bir martalik "katta tozalash" emas. Va balans muhim (juda iflos — qarz; juda mukammal — vaqt isrofi, over-engineering). Pragmatik dasturchi "yetarli toza" yozadi (o'qiladigan, o'zgartiriladigan — lekin cheksiz mukammallik emas). Bu — professional kod yozishning yetuk darajasi (toza, lekin amaliy — ish bajariladigan, sifatli). Linter (15.3 — keyingi bob) izchillikni avtomatlashtiradi (uslub — qo'lda emas). Toza kod — texnik mahorat + tajriba + balans (vaqt bilan rivojlanadi).

2.9. Formatlash (vertikal va gorizontal)

text
  FORMATLASH — kodning KO'RINISHI (o'qish oson bo'lsin):

  VERTIKAL (yuqoridan pastga):
   Bog'liq qatorlar yaqin (bo'sh qatorsiz guruh)
   Turli tushunchalar orasida bo'sh qator (mantiqiy blok ajratish)
   O'zgaruvchi ishlatiladigan joyga yaqin e'lon qilinsin
   Bog'liq funksiyalar yaqin (chaqiruvchi — chaqiriluvchidan yuqorida)

  GORIZONTAL (chapdan o'ngga):
   Qator qisqa (~80-120 belgi — ekranga sig'sin, gorizontal skroll yo'q)
   Indentatsiya izchil (2 yoki 4 probel — struktura ko'rinsin)
   Operator atrofida probel (a + b, a === b — o'qish oson)

   Formatlash — kod ko'rinishi (vertikal guruh + gorizontal qisqa qator)
   Izchillik — MUHIM (linter/Prettier avtomatlashtiradi — 15.3)

Formatlash (vertikal va gorizontal) — kodning ko'rinishi (tuzilishi ko'zga ko'rinsin, o'qish oson bo'lsin). Formatlash funksionallikka ta'sir qilmaydi, lekin o'qiluvchanlikka kuchli ta'sir qiladi (chalkash format = qiyin o'qish). Vertikal formatlash (yuqoridan pastga): (1) bog'liq qatorlar yaqin (bir mantiqni bajaradigan qatorlar — bo'sh qatorsiz, bir guruh); (2) turli tushunchalar orasida bo'sh qator (mantiqiy bloklarni bo'sh qator bilan ajratish — "abzas" kabi — nafas oladigan joy); (3) o'zgaruvchi ishlatiladigan joyga yaqin e'lon (funksiya boshida hammasini emas — ishlatiladigan joyga yaqin — ko'z uzoqqa yugurmaydi); (4) bog'liq funksiyalar yaqin (chaqiruvchi funksiya — chaqiriluvchidan yuqorida — o'qish yuqoridan pastga oqadi — "gazeta metaforasi": muhim yuqorida, detal pastda). Gorizontal formatlash (chapdan o'ngga): (1) qator qisqa (~80-120 belgi — ekranga sig'sin — uzun qator gorizontal skroll talab qiladi, o'qish qiyin); (2) indentatsiya izchil (2 yoki 4 probel — bir xil — struktura (nesting darajasi) ko'zga ko'rinsin); (3) operator atrofida probel (a + b, a === ba+b emas — o'qish oson). Ikki nuqta: (1) formatlash — kod ko'rinishi (vertikal guruh/ajratish + gorizontal qisqa qator/izchil indentatsiya); (2) izchillik — muhim (butun loyihada bir xil — linter/Prettier avtomatlashtiradi — 15.3 — qo'lda emas). Formatlash — o'qiluvchanlikning "tashqi ko'rinishi" (nom/struktura — mazmun, format — shakl). Yaxshi format — kod bir qarashda "hazm bo'ladi" (mantiqiy bloklar ko'rinadi, indentatsiya strukturani ko'rsatadi). Amalda formatni avtomatlashtirish eng to'g'ri (Prettier — 15.3): qo'lda formatlashga vaqt sarflamang, asbob bir xil uslubga keltirsin (jamoada bahs yo'q — asbob qaror qiladi). Muhimi — izchillik (butun loyiha bir xil ko'rinsin — turli uslub aralashmasi chalkash).

2.10. Texnik qarz (technical debt)

text
  TEXNIK QARZ (technical debt) — "tez" yechim uchun kelajakda to'lanadigan narx:

  NIMA: bugun tez/iflos yechim (deadline)  keyin "foiz" (o'zgartirish qiyinlashadi)
   moliyaviy qarz kabi: qarz olish tez, lekin foiz to'lanadi (to'lanmasa — o'sadi)

  QARZ TURLARI:
   ATAYLAB (bilib) — "hozir tez chiqaraylik, keyin tozalaymiz" (reja bilan)
   BEIXTIYOR (bilmasdan) — tajribasizlik, shoshilinch (keyin bilib qolinadi)

  BOSHQARISH:
   Ko'rinadigan qilish (TODO, backlog — qarzni yozib qo'yish)
   Muntazam to'lash (har sprint biroz refactoring — boy scout rule)
   "Foiz"ni kuzatish (qaysi qarz eng ko'p sekinlashtiradi — o'shani birinchi)
   Cheksiz jamg'arish (to'lanmagan qarz — kod "botqoq", har o'zgarish azob)

   Texnik qarz — tez/iflos yechim narxi (kelajakda o'zgartirish qiyinlashadi)
   Boshqarish — ko'rinadigan qilish + muntazam to'lash (jamg'armaslik)

Texnik qarz (technical debt) — bugungi "tez, lekin iflos" yechim uchun kelajakda to'lanadigan narx. Nima: deadline yoki shoshilinch tufayli tez, sifatsiz kod yoziladi (ishlaydi, lekin iflos) — bu bugun vaqt tejaydi, lekin kelajakda "foiz" to'lanadi (kod chalkash — har o'zgartirish sekin, xatarli). Bu — moliyaviy qarzga o'xshaydi: qarz olish tez (bugun pul bor), lekin foiz to'lanadi (to'lanmasa — o'sadi, ko'payadi). Qarz turlari: (1) ataylab (deliberate — bilib olingan qarz — "hozir tez versiya chiqaraylik, keyin tozalaymiz" — reja bilan, ongli qaror — maqbul, agar to'lansa); (2) beixtiyor (inadvertent — bilmasdan olingan — tajribasizlik yoki shoshilinch tufayli — keyin "buni yaxshiroq qilsa bo'lardi" deb bilib qolinadi). Boshqarish: (1) ko'rinadigan qilish (qarzni yashirmang — TODO, backlog, hujjatda yozib qo'ying — ko'rinmaydigan qarz eng xatarli); (2) muntazam to'lash (har sprint/har xususiyat qo'shganda biroz refactoring — "boy scout rule" — 2.8 — qarz kichik bo'lakda to'lanadi, birdan katta "tozalash" emas); (3) "foiz"ni kuzatish (qaysi qarz eng ko'p sekinlashtiradi — o'sha joyni birinchi tozalash — hamma qarz teng emas); (4) cheksiz jamg'arish (to'lanmagan qarz — kod "botqoq" (legacy) — har o'zgartirish azob, yangi dasturchi qo'rqadi tegishga — loyiha sekinlashadi, oxiri qayta yozish). Ikki nuqta: (1) texnik qarz — tez/iflos yechim narxi (kelajakda o'zgartirish qiyinlashadi — "foiz"); (2) boshqarish — ko'rinadigan qilish (TODO/backlog) + muntazam to'lash (boy scout rule — jamg'armaslik). Texnik qarz — muqarrar (har loyihada bo'ladi — deadline, o'rganish jarayoni), muhimi uni boshqarish (ko'rinadigan, nazoratdagi qarz — foydali; yashirin, jamg'arilgan qarz — halokatli). Toza kod va refactoring — texnik qarzni kam tutish vositasi (qarz to'planmasin, foiz o'smasin). Balans 2.8-bob yana muhim: nol qarz — mumkin emas va shart emas (over-engineering); boshqarilgan qarz — sog'lom loyiha belgisi.


3. Sintaksis — printsiplar ma'lumotnomasi

text
NOMLASH 2.2-bob:     niyat (daysUntilExpiry), fe'l (getUser), is/has (isActive)
FUNKSIYA 2.3-bob:    kichik (<20 qator), bitta vazifa, kam parametr (0-2)
IZOH 2.4-bob:        NEGA (kod NIMA'ni); yaxshi nom > izoh
KOD HIDI 2.5-bob:    takror, uzun funksiya, sehrli raqam, chuqur nesting
REFACTORING 2.6-bob: extract function/variable, rename, guard clause (test bilan)
PRINTSIP 2.1-bob:    DRY (takrorlama), KISS (sodda), YAGNI (kerakmasini yozma)
SOLID 2.7-bob:       Single Responsibility (bitta mas'uliyat — eng muhim)
FORMAT 2.9-bob:      vertikal (guruh/bo'sh qator), gorizontal (qisqa qator, indent)
TEXNIK QARZ 2.10-bob:tez/iflos narxi — ko'rinadigan qil + muntazam to'la

4. Batafsil misollar

Har misol: Maqsad + oldin/keyin kod + "Bu nima yaxshilandi".

Misol 1 — Nomlash refactoringi (2.2)

Maqsad: Yomon nomlarni aniq nomlarga o'zgartirib, izohsiz tushunarli kod yaratish. Bu toza kodning eng katta, eng oson yaxshilanishi.

tsx
//  OLDIN — yomon nomlar (izohsiz tushunarsiz):
function calc(a: number, b: number, c: number): number {
  const r = a * b;
  const t = r * (c / 100);
  return r + t;
}
// calc nima? a, b, c nima? — har safar o'qib tushunish kerak

//  KEYIN — aniq nomlar (o'zini tushuntiradi):
function calculateTotalWithTax(price: number, quantity: number, taxPercent: number): number {
  const subtotal = price * quantity;
  const tax = subtotal * (taxPercent / 100);
  return subtotal + tax;
}
// nom o'zini aytadi — izoh kerak emas (price, quantity, taxPercent, subtotal, tax)

Bu nima yaxshilandi: Bu — nomlash refactoringi (eng katta, eng oson toza kod yaxshilanishi — 2.2). Oldin: calc(a, b, c) — funksiya nomi (calc) noaniq (nimani hisoblaydi?), parametrlar (a, b, c) ma'nosiz, ichki o'zgaruvchilar (r, t) tushunarsiz — kodni o'qigan odam har safar mantiqni qayta tiklab tushunishi kerak ("a*b nima? c/100 — foizmi?"). Keyin: calculateTotalWithTax(price, quantity, taxPercent) — nom funksiya nima qilishini aytadi (soliq bilan jami), parametrlar aniq (price — narx, quantity — soni, taxPercent — soliq foizi), ichki o'zgaruvchilar tushunarli (subtotal — oraliq summa, tax — soliq) — kod o'zini tushuntiradi (izoh kerak emas — nom hammasini aytadi). Nima o'zgardi: mantiq bir xil (xatti-harakat o'zgarmadi — refactoring — 2.6), lekin kod o'qiladigan bo'ldi (oldin — jumboq, keyin — aniq). Endi 6 oydan keyin (yoki boshqa dasturchi) bu kodni ko'rsa — darrov tushunadi (calculateTotalWithTax — aniq). Nega bu eng katta yaxshilanish: kod o'qilishi asosan nomga bog'liq 2.2-bob — yaxshi nom = izohsiz tushunarli kod. Bu eng oson (faqat nom o'zgartirish — IDE'da Rename — F2), lekin eng katta ta'sir (o'qiladiganlik). Yomon nom (calc, a, r) — eng keng toza kod xatosi (dasturchi "ishlaydi-ku" deb e'tibor bermaydi), lekin eng ko'p o'qish azobi (har safar tushunish). Aniq nom — kelajakdagi o'qish uchun sovg'a. Nomlash — toza kodning birinchi, eng muhim qadami.

Misol 2 — Funksiyani bo'lish (extract function — 2.3, 2.6)

Maqsad: Katta, ko'p vazifali funksiyani kichik, bitta-vazifali funksiyalarga bo'lish. Bu o'qish, test, qayta ishlatishni osonlashtiradi.

tsx
//  OLDIN — katta funksiya (ko'p vazifa):
async function registerUser(data: RegisterData) {
  // validatsiya
  if (!data.email.includes("@")) throw new Error("Email noto'g'ri");
  if (data.password.length < 8) throw new Error("Parol qisqa");
  // parol hash
  const salt = await bcrypt.genSalt(12);
  const hash = await bcrypt.hash(data.password, salt);
  // DB'ga saqlash
  const user = await db.user.create({ data: { email: data.email, passwordHash: hash } });
  // email yuborish
  await transporter.sendMail({ to: data.email, subject: "Xush kelibsiz", html: "..." });
  return user;
}

//  KEYIN — kichik funksiyalar (har biri bitta vazifa):
async function registerUser(data: RegisterData) {
  validateRegistration(data);                      // bitta vazifa
  const passwordHash = await hashPassword(data.password);
  const user = await createUser(data.email, passwordHash);
  await sendWelcomeEmail(user.email);
  return user;
}
function validateRegistration(data: RegisterData) {
  if (!data.email.includes("@")) throw new Error("Email noto'g'ri");
  if (data.password.length < 8) throw new Error("Parol qisqa");
}
async function hashPassword(password: string) { /* ... */ }
async function createUser(email: string, hash: string) { /* ... */ }
async function sendWelcomeEmail(email: string) { /* ... */ }

Bu nima yaxshilandi: Bu — funksiyani bo'lish (extract function — 2.3, 2.6). Oldin: registerUser to'rt vazifani bajaradi (validatsiya, parol hash, DB saqlash, email) — bir funksiyada 20+ qator, aralash mantiq (yuqori daraja — "ro'yxatdan o'tkazish" — va past detal — bcrypt.genSalt(12) — aralash). Bu kod hidi (uzun funksiya, ko'p vazifa — 2.5): tushunish qiyin (bir vaqtda ko'p narsa), test qiyin (hammasini birga sinash), o'zgartirish xavfli (email mantiqini o'zgartirsa — butun funksiyaga tegish). Keyin: registerUser faqat muvofiqlashtiradi (4 ta funksiyani chaqiradi — yuqori daraja, "nima qilinadi" — aniq), har vazifa alohida funksiya (validateRegistration, hashPassword, createUser, sendWelcomeEmail — har biri bitta ish). Nima yaxshilandi: (1) o'qiladiganregisterUser o'qisa, jarayon aniq (validatsiya hash saqlash email — yuqori daraja, detalsiz); (2) test oson — har funksiyani alohida test (validateRegistrationni alohida sinash — 11.17); (3) qayta ishlatiladigansendWelcomeEmailni boshqa joyda ham ishlatish mumkin; (4) o'zgartirish xavfsiz — email mantiqini o'zgartirsa faqat sendWelcomeEmail (boshqasiga ta'sir yo'q); (5) abstraksiya darajasiregisterUser yuqori (nima), kichik funksiyalar past (qanday) — aralashmaydi 2.3-bob. Mantiq bir xil (refactoring — xatti-harakat o'zgarmadi), lekin struktura toza (har funksiya bitta vazifa — Single Responsibility — 2.7). Bu — eng keng refactoring (katta funksiyani kichiklarga bo'lish — extract function). IDE buni avtomatlashtiradi (kod tanlab "Extract Function"). Kichik funksiyalar — toza kodning asosi (o'qiladigan, test qilinadigan, qayta ishlatiladigan).

Misol 3 — Guard clause (chuqur nestingni tekislash — 2.6)

Maqsad: Chuqur ichma-ich iflarni early return bilan tekislab, o'qishni osonlashtirish. Bu eng keng o'qiluvchanlik yaxshilanishi.

tsx
//  OLDIN — chuqur nesting (ko'p ichma-ich if — o'qish qiyin):
function processOrder(order: Order) {
  if (order) {
    if (order.items.length > 0) {
      if (order.user.isVerified) {
        if (order.payment.isValid) {
          // asosiy mantiq (4 daraja chuqur — o'qish qiyin)
          return chargeAndShip(order);
        } else {
          throw new Error("To'lov noto'g'ri");
        }
      } else {
        throw new Error("Foydalanuvchi tasdiqlanmagan");
      }
    } else {
      throw new Error("Buyurtma bo'sh");
    }
  } else {
    throw new Error("Buyurtma yo'q");
  }
}

//  KEYIN — guard clause (early return — tekis, o'qish oson):
function processOrder(order: Order) {
  if (!order) throw new Error("Buyurtma yo'q");
  if (order.items.length === 0) throw new Error("Buyurtma bo'sh");
  if (!order.user.isVerified) throw new Error("Foydalanuvchi tasdiqlanmagan");
  if (!order.payment.isValid) throw new Error("To'lov noto'g'ri");

  // asosiy mantiq (0 daraja chuqur — aniq, oxirida)
  return chargeAndShip(order);
}

Bu nima yaxshilandi: Bu — guard clause / early return (chuqur nestingni tekislash — 2.6). Oldin: processOrder to'rt daraja ichma-ich if/else (if (order) { if (items) { if (verified) { if (payment) {...} else {...} } else {...} } else {...} }) — bu chuqur nesting kod hidi 2.5-bob: (1) asosiy mantiq (chargeAndShip) 4 daraja chuqurda (ko'p o'ngga surilgan — o'qish qiyin); (2) xato holatlari (else) asosiy mantiqdan uzoqda (qaysi else qaysi ifga — kuzatish qiyin); (3) "o'q" (arrow) shakli (kod o'ngga kengayadi — chap chetga qaytadi — chalkash). Keyin: guard clause (early return — himoya shartlari) — har xato holati boshida tekshiriladi va darrov return/throw (if (!order) throw...) — agar shart bajarilmasa, funksiya darrov chiqadi. Natijada: (1) asosiy mantiq (chargeAndShip) oxirida, 0 daraja chuqurda (aniq — barcha tekshiruvdan o'tgach — "happy path"); (2) xato holatlari boshida, tekis (har biri bir qator — aniq); (3) tekis struktura (o'ngga surilmaydi — o'qish oson). Mantiq bir xil (xatti-harakat o'zgarmadi — refactoring), lekin ancha o'qiladigan (chuqur nesting tekis). Nega bu muhim: chuqur nesting — eng keng o'qiluvchanlik muammosi (inson 2-3 darajadan chuqurni qiyin kuzatadi); guard clause (early return) — eng keng yechim (xato holatlarini boshida tekshir, asosiy mantiqni tekis qoldir). "Happy path" (asosiy to'g'ri yo'l) tekis, alohida — xato holatlari boshida (guard) — bu kodni o'qishni osonlashtiradi (avval "nima noto'g'ri bo'lishi mumkin" — guard, keyin "asosiy ish" — tekis). Bu refactoring — har chuqur if/else ko'rsa qo'llaniladi (early return bilan tekislash). Toza kodning eng amaliy texnikalaridan biri.

Misol 4 — DRY (takrorni yo'qotish — 2.1)

Maqsad: Takror kodni bir joyga birlashtirib, DRY printsipini qo'llash. Bu o'zgartirishni bir joyda qiladi (xato kamayadi).

tsx
//  OLDIN — takror kod (bir mantiq 3 joyda):
function getAdminUsers() {
  return db.users.filter(u => u.active && !u.deleted && u.role === "admin");
}
function getActiveModerators() {
  return db.users.filter(u => u.active && !u.deleted && u.role === "moderator");
}
function getActiveCustomers() {
  return db.users.filter(u => u.active && !u.deleted && u.role === "customer");
}
// "u.active && !u.deleted" 3 marta takror — o'zgartirsa (masalan banned qo'shish)
// 3 joyni topib o'zgartirish kerak (bittasini unutsa — xato)

//  KEYIN — takror bir joyda (DRY):
function getActiveUsers() {
  return db.users.filter(u => u.active && !u.deleted);   // umumiy mantiq bir joyda
}
function getUsersByRole(role: string) {
  return getActiveUsers().filter(u => u.role === role);
}
// Ishlatish: getUsersByRole("admin"), getUsersByRole("moderator")
// "active && !deleted" mantiqi BIR joyda — o'zgartirsa bir joy (xato yo'q)

Bu nima yaxshilandi: Bu — DRY (takrorni yo'qotish — 2.1). Oldin: uch funksiya (getAdminUsers, getActiveModerators, getActiveCustomers) bir xil mantiqni (u.active && !u.deleted — faol va o'chirilmagan) takrorlaydi (3 joyda bir xil shart). Bu takror kod kod hidi 2.5-bob: agar "faol foydalanuvchi" ta'rifi o'zgarsa (masalan !u.banned qo'shish kerak) — 3 joyni topib o'zgartirish kerak (va bittasini unutsa — nomutanosiblik, xato — masalan admin'da banned tekshiriladi, customer'da yo'q). Keyin: umumiy mantiq (active && !deleted) bir joyda (getActiveUsers), va rol bo'yicha filtrlash alohida (getUsersByRolegetActiveUsersni ishlatadi). Endi "faol foydalanuvchi" ta'rifi bir joyda (getActiveUsers) — o'zgartirsa (banned qo'shish) bir joyni o'zgartirish (barcha funksiya avtomatik to'g'ri). Nima yaxshilandi: (1) takror yo'q (DRY — bir mantiq bir joyda); (2) o'zgartirish oson (bir joy — xato kamayadi — unutish yo'q); (3) kam kod (uch deyarli bir xil funksiya ikki aniq funksiya); (4) moslashuvchan (getUsersByRole(anyRole) — yangi rol uchun yangi funksiya kerak emas). Nega DRY muhim: takror kod — eng keng kod hidi 2.5-bob, va u xato manbai (bir joyni o'zgartirib, boshqasini unutish — nomutanosiblik). DRY — mantiqni bir joyda saqlash (o'zgartirsa bir joy — izchil). Lekin balans 2.8-bob — har takror darrov DRY qilma ("rule of three" — 2 marta OK, 3+ — DRY; va tasodifan o'xshash kod — DRY qilma — ular alohida o'zgarishi mumkin). To'g'ri DRY — bir xil mantiqni birlashtirish (tasodifan o'xshashni emas). Bu — takror kodni kamaytirishning asosi (kod kam, o'zgartirish oson, xato kam).

Misol 5 — Sehrli raqam va extract variable (2.5, 2.6)

Maqsad: Sehrli raqamlarni nomli konstantaga, murakkab ifodalarni nomli o'zgaruvchiga ajratib, niyatni aniqlash. Bu kodni o'z-o'zini hujjatlaydigan qiladi.

tsx
//  OLDIN — sehrli raqam + murakkab ifoda (niyat noaniq):
function canUserAccess(user: User): boolean {
  if (user.age >= 18 && user.subscriptionDays > 0 && user.failedLogins < 5) {
    return true;
  }
  return false;
}
// 18 nima? 5 nima? murakkab shart — niyat noaniq

//  KEYIN — nomli const + extract variable (niyat aniq):
const MINIMUM_AGE = 18;
const MAX_FAILED_LOGINS = 5;

function canUserAccess(user: User): boolean {
  const isAdult = user.age >= MINIMUM_AGE;
  const hasActiveSubscription = user.subscriptionDays > 0;
  const isNotLocked = user.failedLogins < MAX_FAILED_LOGINS;

  return isAdult && hasActiveSubscription && isNotLocked;
}
// har shart NOMLI (niyat aniq — kod o'zini tushuntiradi)

Bu nima yaxshilandi: Bu — sehrli raqam (magic number) va extract variable (2.5, 2.6). Oldin: if (user.age >= 18 && user.subscriptionDays > 0 && user.failedLogins < 5) — ikki muammo: (1) sehrli raqamlar (18, 5 — nima ular? 18 — voyaga yetgan yosh? 5 — nima limiti? — kod o'qigan odam taxmin qilishi kerak); (2) murakkab shart (uch shart bir qatorda — niyat noaniq — "bu shart nima tekshiradi?"). Keyin: (1) nomli const (MINIMUM_AGE = 18, MAX_FAILED_LOGINS = 5 — raqam nima ekani aniq — 18 o'rniga MINIMUM_AGE — niyat aniq, va o'zgartirsa bir joyda — DRY); (2) extract variable (har shartni nomli o'zgaruvchiga — isAdult, hasActiveSubscription, isNotLocked — har shart nima tekshirishini aytadi). Natija: return isAdult && hasActiveSubscription && isNotLocked — bu o'qiladi (voyaga yetgan VA obunasi faol VA bloklanmagan — niyat aniq — kod o'zini tushuntiradi). Nima yaxshilandi: (1) sehrli raqam yo'q (18, 5 — nomli const — niyat aniq, o'zgartirsa bir joy); (2) niyat aniq (isAdultage >= 18ning ma'nosi); (3) o'qiladigan (yakuniy shart — nomli o'zgaruvchilar — izohsiz tushunarli); (4) debug oson (har shartni alohida tekshirish mumkin — qaysi shart false). Mantiq bir xil (refactoring), lekin niyat aniq (kod o'zini hujjatlaydi — self-documenting). Sehrli raqam — eng keng kod hidi (raqam kontekstsiz — 3, 100, 86400 — nima?) — nomli const yechadi (STATUS_ACTIVE, MAX_RETRIES, SECONDS_PER_DAY). Extract variable — murakkab ifodani nomli o'zgaruvchiga (niyat aniqlash). Ikkalasi — kodni o'z-o'zini hujjatlaydigan qiladi (nom = hujjat — izoh kerak emas — 2.4). Bu — toza kodning amaliy texnikalari (har sehrli raqam const, har murakkab ifoda nomli o'zgaruvchi).

Misol 6 — Shartni polimorfizm bilan almashtirish (2.6, 2.7)

Maqsad: Tipga qarab tarmoqlanuvchi katta switch/if zanjirini polimorfizm bilan almashtirish. Bu yangi tip qo'shishni oson va xavfsiz qiladi (Open/Closed — 2.7).

tsx
//  OLDIN — tipga qarab switch (har joyda takrorlanadi):
function getArea(shape: Shape): number {
  switch (shape.type) {
    case "circle": return Math.PI * shape.radius ** 2;
    case "square": return shape.side ** 2;
    case "rectangle": return shape.width * shape.height;
    default: throw new Error("Noma'lum shakl");
  }
}
// Yangi shakl (masalan triangle) qo'shsa — bu switch'ni VA getPerimeter,
// getName kabi boshqa switch'larni ham topib o'zgartirish kerak (shotgun surgery — 2.5)

//  KEYIN — polimorfizm (har shakl o'z mantiqini biladi):
interface Shape {
  area(): number;
}
class Circle implements Shape {
  constructor(private radius: number) {}
  area() { return Math.PI * this.radius ** 2; }
}
class Square implements Shape {
  constructor(private side: number) {}
  area() { return this.side ** 2; }
}
class Rectangle implements Shape {
  constructor(private width: number, private height: number) {}
  area() { return this.width * this.height; }
}
// Ishlatish: shape.area() — qaysi shakl ekani ahamiyatsiz (har biri o'zini biladi)
// Yangi shakl (Triangle) — YANGI class qo'shiladi, mavjud kod O'ZGARMAYDI (Open/Closed)

Bu nima yaxshilandi: Bu — Replace Conditional with Polymorphism (shartni polimorfizm bilan almashtirish — 2.6, 2.7). Oldin: getArea shakl tipiga qarab switch bilan tarmoqlanadi. Muammo — bu bitta joy emas: getPerimeter, getName, draw kabi har funksiya shu xil switchni takrorlaydi (tip bo'yicha tarmoqlanish tarqoq — takror + shotgun surgery — 2.5). Yangi shakl (Triangle) qo'shilsa — hamma switchni topib case "triangle" qo'shish kerak (bittasini unutsa — default: throw bilan xato yoki noto'g'ri natija). Keyin: har shakl o'z klassi (Circle, Square, Rectangle) va umumiy Shape interfeysining area() metodini o'zi amalga oshiradi. Chaqirilganda shape.area() — qaysi konkret shakl ekani ahamiyatsiz (polimorfizm — har obyekt o'z hisobini biladi). Nima yaxshilandi: (1) switch yo'q (tarmoqlanish o'rniga polimorfizm — o'qish oson); (2) Open/Closed (2.7 — yangi shakl = yangi class; mavjud kod o'zgarmaydi — kengaytirishga ochiq, o'zgartirishga yopiq); (3) shotgun surgery yo'q (2.5 — har shaklning mantiqi bir joyda — uning klassida — tarqoq emas); (4) birlashgan (bir shaklga tegishli hamma narsa — area, perimeter, name — bir klassda — yuqori kohesiya). Mantiq bir xil (refactoring), lekin struktura kengaytiriladigan bo'ldi. Muhim balans 2.8-bob: bu texnika ko'p tip + ko'p operatsiya bo'lganda arziydi (har ikkisi o'sadi). Agar bitta joyda kichik switch bo'lsa — polimorfizm over-engineering (YAGNI — 2.1 — oddiy switch yetarli). Polimorfizmga o'tish — takror switchlar payqalganda (bir tip bo'yicha ko'p joyda tarmoqlanish — o'shanda arziydi).


5. To'g'ri va noto'g'ri holatlar

1) Nomlash

text
 d, temp, data, calc (noaniq — 2.2)
 daysUntilExpiry, calculateTotal (niyatli — Misol 1)

2) Funksiya

text
 katta, ko'p vazifa (110 qator — 2.3)
 kichik, bitta vazifa (extract — Misol 2)

3) Nesting

text
 chuqur ichma-ich if (4 daraja — 2.5)
 guard clause / early return (Misol 3)

4) Takror

text
 bir mantiq 3 joyda (DRY buzilgan)
 bir joyda (DRY — Misol 4)

5) Sehrli raqam

text
 if (status === 3) (3 nima? — 2.5)
 const STATUS_ACTIVE (Misol 5)

6) Izoh

text
 kod takror izoh (// i++ — i ni oshir)
 nega-izoh (qaror sababi — 2.4)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Yomon nomlar

Sababi: "ishlaydi-ku" (d, temp — 2.2). Yechimi: niyatli nom (Misol 1).

Xato 2 — Katta funksiya

Sababi: ko'p vazifa bir joyda 2.3-bob. Yechimi: extract function (Misol 2).

Xato 3 — Chuqur nesting

Sababi: ichma-ich if 2.5-bob. Yechimi: guard clause (Misol 3).

Xato 4 — Takror kod

Sababi: copy-paste (DRY buzilgan). Yechimi: bir joyga birlashtirish (Misol 4).

Xato 5 — Over-engineering

Sababi: ortiqcha abstraksiya (YAGNI buzilgan — 2.8). Yechimi: pragmatik (yetarli toza — 2.8).

Xato 6 — Test'siz refactoring

Sababi: ishlashni kafolatlamaslik 2.6-bob. Yechimi: test bilan (xavfsiz — 2.6).


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Barcha kod (0-14 QISM): toza kod har joyda (har funksiya/o'zgaruvchi).
  • Linter 15.3-bob: ESLint/Prettier — toza kodni avtomatlashtirish.
  • Code review 15.2-bob: toza kod review'da tekshiriladi.
  • Test 11.17-bob: refactoring test bilan (xavfsiz).
  • Arxitektura (9-QISM): SOLID, design patterns (katta toza).
  • TypeScript (7-QISM): tip — toza kod (xato kamaytirish).
  • FP 2.15-bob: pure function — toza (yon ta'sirsiz).

8. Eng yaxshi amaliyotlar (best practices)

  • Aniq nom (eng muhim — niyatli — 2.2, Misol 1).
  • Kichik funksiya, bitta vazifa (extract — 2.3, Misol 2).
  • Guard clause (chuqur nesting tekislash — Misol 3).
  • DRY (takrorlama — bir joyda — Misol 4).
  • Sehrli raqam const (niyat — Misol 5).
  • Nega-izoh (kod nima'ni aytadi — 2.4).
  • KISS, YAGNI (sodda, kerakmasini yozma — 2.1).
  • Test bilan refactoring (xavfsiz — 2.6).
  • Balans (toza, lekin over-engineering emas — 2.8).
  • Boy scout rule (har joyda tozaroq qoldir — 2.8).
  • Izchil formatlash (vertikal guruh, qisqa qator — Prettier — 2.9).
  • Texnik qarzni boshqarish (ko'rinadigan qil, muntazam to'la — 2.10).
  • Komanda-so'rov ajratish (funksiya yo qiladi, yo qaytaradi — 2.3).

9. Amaliy loyiha: "Kodni Refactoring"

Iflos kodni toza kodga aylantirishni mustahkamlash.

Maqsad

Mavjud iflos kodni (o'z eski loyihangiz yoki berilgan) refactoring qilish — nom, funksiya, nesting, takror, sehrli raqam.

Talablar (requirements)

  1. Nomlash: yomon nomlarni aniqlash (Misol 1).
  2. Funksiya: katta funksiyalarni bo'lish (Misol 2).
  3. Nesting: guard clause (Misol 3).
  4. DRY: takrorni birlashtirish (Misol 4).
  5. Sehrli raqam: const (Misol 5).
  6. Izoh: keraksizni olib tashlash, nega-izoh qo'shish 2.4-bob.
  7. Test: refactoring oldidan/keyin test (xavfsiz — 2.6).
  8. Kod hidi: har hidni aniqlash va tuzatish 2.5-bob.
  9. Balans: over-engineering emas 2.8-bob.
  10. Taqqoslash: oldin/keyin (qancha o'qiladigan bo'ldi).

Maslahatlar (hint)

  • Nom — eng katta ta'sir (Misol 1).
  • Kichik funksiya (Xato 2).
  • Early return (Xato 3).
  • Test bilan (Xato 6).
  • Balans (Xato 5).

"Tayyor" mezonlari (acceptance criteria)

  • Aniq nomlar.
  • Kichik funksiyalar (bitta vazifa).
  • Tekis (guard clause).
  • Takror yo'q (DRY).
  • Sehrli raqam yo'q.
  • Test o'tadi (xatti-harakat saqlangan).

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda toza kod va refactoringni chuqur o'rgandik:

Endi siz toza, o'qiladigan kod yoza olasiz: aniq nom, kichik funksiya, tekis struktura, takror yo'q. Va iflos kodni refactoring qila olasiz (xavfsiz — test bilan). Bu — professional dasturchining belgisi (ishlaydigan emas — yaxshi ishlaydigan kod).

Keyingi bob — 15.2-bob: Code review madaniyati. Toza kod yozishni bildik; endi jamoada kod sifatini ta'minlashni ko'ramiz: code review (kod o'zgarishini boshqalar tekshirishi — sifat, bilim almashish), review berish (qanday konstruktiv fikr), review olish (qanday qabul qilish), PR yaxshi yozish, va review madaniyati. Bu — jamoada professional ishlash ko'nikmasi.


Foydalanilgan rasmiy/ishonchli manbalar

  • "Clean Code" (Robert C. Martin) — nomlash, funksiyalar, izohlar, formatlash, kod hidi
  • "Refactoring: Improving the Design of Existing Code" (Martin Fowler) — refactoring texnikalari katalogi (Extract/Inline, Replace Conditional with Polymorphism), kod hidi katalogi
  • "The Pragmatic Programmer" (Hunt & Thomas) — DRY, KISS, pragmatik yondashuv, boy scout rule
  • "Agile Software Development" (Robert C. Martin) — SOLID printsiplari
  • refactoring.guru — kod hidlari va refactoring texnikalari (vizual katalog)
  • Ward Cunningham — texnik qarz (technical debt) metaforasi

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
15.1-bob: Toza kod va refactoring — Wisar