Dasturlashda sehr — bu nima, magic numbers nima uchun xavfli va almashtirish

Muallif: IT Sectr Nashr etilgan: 2026-07-27 O'qish vaqti: 10 daq

Dasturlashda sehr — bu metafora emas, balki maʼnosi kontekstdan aniq boʻlmagan va tushunish uchun tashqi bilim talab qiladigan qiymatlarni (raqamlar, satrlar, bayroqlar) bildiruvchi aniq atamadir. Sehrning eng keng tarqalgan turi — magic numbers: toʻgʻridan-toʻgʻri kodga izohsiz yozilgan raqamli konstantalar. SonarSource Code Quality Report (2025) tadqiqotiga koʻra, statik analizatorlarning barcha ogohlantirishlarining taxminan 8 foizi tushuntirilmagan literallar bilan bogʻliq. Sehrli qiymatlar kodni moʻrt qiladi: oʻzgartirish barcha holatlarni qidirishni talab qiladi va yangi dasturchi raqamga tegish mumkinmi yoki u tizim ishlashi uchun muhimmi, tushunmaydi.

Asosiy

  • Sehr — koddagi maʼnosi oʻquvchidan yashirin boʻlgan yashirin raqamlar, satrlar va bayroqlar.
  • Magic numbers — nomsiz raqamli literallar: 86400, 3.14, 0.85, 1024.
  • Sehrli satrlar — konstantalarga chiqarilmagan yoʻllar, kalitlar, URL-larning qattiq kodlanishi.
  • Qidiruv vositalari: SonarQube (MagicNumber qoidasi), ESLint (no-magic-numbers), Detekt.
  • Yechim: har bir sehrli qiymatni izohli nom bilan nomlangan konstantaga chiqarish.

Dasturlashda sehr nima?

Sehr (magic) — manba kodidagi maʼnosi mavzu sohasi haqida qoʻshimcha bilimsiz aniq boʻlmagan har qanday qiymatdir. Bu atama jamiyatda oʻrnashgan: agar dasturchi raqamga qarab, uning qayerdan kelganini tushunmasa — bu sehr.

Sehr bir necha turda boʻladi: raqamli (magic numbers), satr (magic strings), mantiqiy (magic flags) va konfiguratsion (sozlamalarda boʻlishi kerak boʻlgan qattiq kodlangan parametrlar). Barcha toʻrt turni bitta muammo birlashtiradi: talab oʻzgarganda dasturchi qiymat ishlatilgan barcha joylarni topib, ularni qoʻlda almashtirishi kerak. Hatto bitta holatni oʻtkazib yuborish xatoga olib keladi.

JetBrains Code Quality Survey (2025) hisobotiga koʻra, dasturchilarning 73 foizi magic numbers-ni past sifatli kod koʻrsatkichi deb hisoblaydi, 41 foizi esa vaqti-vaqti bilan ularni oʻzlari ham qoldirishlarini tan oladi. Asosiy sabab — shoshqaloqlik: “Keyinroq constanta qoʻyaman” — ammo keyinroq kelmaydi va bir oydan soʻng 0.85 raqami metod tanasida izohsiz qoladi.

Asosiy qoida: 0, 1, true, false va boʻsh satrdan tashqari har bir literal qiymat nomlangan konstantaga chiqarilishi kerak. Istisnolar: hisoblagichni oshirish (i + 1), matematik nollar (0 ga tekshirish) va akkumulyatorlarning boshlangʻich qiymatlari. Qolgan hamma narsa — nomlash uchun nomzod.

Magic numbers va ularning xavfi

Magic number — kontekstdan qiymati aniq boʻlmagan raqamli literaldir. Klassik misol: timeout uchun masʼul koddagi 86400. Dasturchi raqamni koʻrib, bu bir kundagi soniyalar soni ekanligini taxmin qilishi kerak. Agar xato qilib 84600 qoʻysa — xatoni topish qiyin boʻladi, chunki timeout 18 daqiqa oldin ishga tushadi.

Magic numbers nima uchun xavfli: birinchidan, ular oʻqish qobiliyatini buzadi. 1024 raqami kilobayt hajmi, sahifalash chegarasi yoki elementlarning maksimal sonini anglatishi mumkin. Kontekstsiz — bu shunchaki raqam. Ikkinchidan, ular takrorlanish yaratadi: agar 1024 besh joyda ishlatilsa, chegarani 2048 ga oʻzgartirganda dasturchi barcha beshtasini topib almashtirishi kerak. Agar bir joy oʻtkazib yuborilsa — tizim notoʻgʻri ishlaydi, ammo aniq xato boʻlmaydi.

Magic numbers namunasi: oldin va keyin

kotlin
// oldin — sof holda sehr
fun calculateTimeout(base: Int): Int {
    return base * 3 + 5000
}

// keyin — qiymatlar konstantalar bilan almashtirildi
private const val RETRY_MULTIPLIER = 3
private const val BASE_TIMEOUT_MS = 5000

fun calculateTimeout(base: Int): Int {
    return base * RETRY_MULTIPLIER + BASE_TIMEOUT_MS
}

Uchinchi xavf — test qilishning imkonsizligi. Agar chegara qiymati kodda literal sifatida qattiq kodlangan boʻlsa, test chegara shartlarini tekshirish uchun uni bekor qila olmaydi. Companion object yoki konfiguratsiya fayliga chiqarilgan konstanta kodni test qilinadigan qiladi: test boshqa qiymat qoʻyadi va tizimning chegaradagi xatti-harakatini tekshiradi.

Odat yarating: 0, 1, 100 yoki 2 dan boshqa raqam yozgan har safar toʻxtang va uni konstantaga chiqarishga arziydimi, deb oʻylang. Agar raqam biznes mantiq bilan bogʻliq boʻlsa (chegara, limit, timeout, oʻlcham) — albatta chiqaring. Agar raqam matematik konstanta boʻlsa (pi, e) — standart kutubxonadan foydalaning (Math.PI, Math.E).

Sehrli satrlar va yoʻllar

Magic strings — konstantalar yoki resurslarga chiqarilmasdan kodga kiritilgan satr literallari. Odatiy misollar: endpoint URL-lari, SharedPreferences kalitlari nomlari, Intent Actions, bundle keys, fayl nomlari va SQL soʻrovlari.

Sehrli satrlarning xavfi kompilyatsiya bosqichida tekshiruvning yoʻqligida. “user_prefs” satridagi xato runtime-gacha aniqlanmaydi. Agar satr oʻn joyda ishlatilsa va dasturchi bir joyda “user_pref” (s harfisiz) yozgan boʻlsa — dastur qulab tushmaydi, ammo maʼlumotlar saqlanmaydi. Bunday xato oylab produksiyada yashashi mumkin, chunki crashga sabab boʻlmaydi.

Android loyihalari uchun sehrli satrlar resurslarga (strings.xml, arrays.xml) yoki companion objectdagi konstantalarga chiqarilishi kerak. iOS uchun — matn resurslariga (Localizable.strings) yoki enum konstantalariga. Backend uchun — konfiguratsiya fayllariga (.env, application.properties). Hech bir kalit, URL yoki yoʻl kodda satr literali sifatida boʻlmasligi kerak.

swift
// oldin — sinf boʻylab sehrli satrlar
let prefs = UserDefaults.standard
prefs.set(token, forKey: "auth_token")
prefs.set(userId, forKey: "current_user_id")

// keyin — satrlar enumga chiqarildi
enum PrefKeys: String {
    case authToken = "auth_token"
    case currentUserId = "current_user_id"
}

prefs.set(token, forKey: PrefKeys.authToken.rawValue)
prefs.set(userId, forKey: PrefKeys.currentUserId.rawValue)

Takrorlanadigan satrlarga alohida eʼtibor bering. Agar bir xil “user_settings” kaliti uchta faylda uchrasa — 99 foiz ehtimol bilan ertami-kechmi ulardan birida xato paydo boʻladi. Enum yoki konstantaga chiqarish barcha havolalar bir xil qiymatdan foydalanishini taʼminlaydi.

Magic flags va mantiqiy parametrlar

Magic flags — chaqiruv kontekstidan qiymati aniq boʻlmagan mantiqiy parametrlardir. Klassik anti-namuna: metodga bu bayroq nima yoqishini yoki oʻchirishini tushuntirmasdan true yoki false uzatish.

Misol: userDao.fetch(includeDeleted = false). Dasturchi false ni koʻrib, bu “oʻchirilganlarni kiritma” yoki “faollarni kiritma” ekanligini tushunmaydi. Bir oydan keyin false true ga aylanadi va natijalarda oʻchirilgan yozuvlar paydo boʻla boshlaydi. Xato faqat produksiyada aniqlanadi.

Yechim — mantiqiy bayroqlarni enum yoki sealed class bilan almashtirish. Boolean parametri oʻrniga UserFilter.includeDeleted yoki UserFilter.activeOnly dan foydalaning. Shunday qilib, kod oʻz maqsadini hujjatlashtiradi va IDE avtomatik toʻldirishda mavjud variantlarni taklif qiladi.

Mantiqiy bayroq bir necha qatlam orqali uzatilsa — bu abstraksiya notoʻgʻri ekanligining yana bir signalidir. Bayroqni uch darajali chaqiruv orqali oʻtkazish oʻrniga, filtrlash tanlovi yuqori darajada qabul qilinib, tayyor konfiguratsiya sifatida uzatilishi kerakmi, deb oʻylang. Kodda mantiqiy bayroqlar qancha kam boʻlsa — sehr shuncha kam.

Qoida joriy qiling: hech qanday mantiqiy parametr nomlangan argumentlarsiz metodga uzatilmaydi (agar til named arguments-ni qoʻllab-quvvatlasa). Kotlin va Swiftda bu talab avtomatik bajariladi. Java-da true/false oʻrniga Builder yoki enum konstantalaridan foydalaning.

Sehrni aniqlash vositalari

Sehrli qiymatlarni qidirish kutilmagan joylarda literallarni aniqlash uchun sozlangan statik analizatorlar tomonidan avtomatlashtiriladi. Har bir til sozlanishi mumkin boʻlgan istisnolar bilan oʻz vositalarini taklif qiladi.

VositaTillarQoida
SonarQubeJava, Kotlin, Swift, Python, JSMagicNumber, HardcodedString
ESLintJavaScript, TypeScriptno-magic-numbers, no-hardcoded-strings
DetektKotlinMagicNumber, ComplexCondition
SwiftLintSwiftmagic_number (opt-in qoida)
PMDJava, Apex, PLSQLMagicNumber (ruxsat etilganlar roʻyxati sozlanishi mumkin)
PhpStorm InspectionsPHPNumericLiteralWithContext (ichki tekshiruv)

Istisnolarni sozlash juda muhim — usiz analizator har bir oshirishda (-1, +1) va matematik nolda ogohlantiradi. SonarQube uchun ruxsat etilgan raqamlar roʻyxati: 0, 1, -1, 2 (ikki barobarga oshirish uchun), 100 (foizlar), 60 va 24 (vaqt). Qolgan barcha qiymatlar uchun — public static final (Java) yoki const val (Kotlin) bilan nomlangan konstantani talab qiling.

CI darajasida tahlil uchun sehrni ogohlantirish (warning) sifatida tekshirishni qoʻshing, lekin buildni bloklamasin. Birinchi ishga tushirish legacy-kodda yuzlab ogohlantirishlarni koʻrsatadi. Asta-sekin, ticket-ticket, kodni konstantalarga oʻtkazing va sifat chegarasini oshiring. Magic numbers soni 10 dan kam boʻlganda — qoidani build xatosi sifatida yoqing.

Refaktoring: sehrni konstantalar bilan almashtiramiz

Sehrni refaktoring qilish — eng xavfsiz operatsiyalardan biri: literalni konstantaga almashtirish kod xatti-harakatini oʻzgartirmaydi. Shunga qaramay, yondashuv tizimli boʻlishi kerak, yashirin bogʻliqliklarni qoldirmaslik uchun (masalan, bir xil magic number bogʻliq boʻlmagan kontekstlarda ishlatilsa, lekin tasodifan qiymati bir xil boʻlsa).

Bosqichma-bosqich jarayon: sehrli qiymatning barcha holatlarini toping, har birining kontekstini tushuning, turli konstantalarga ajrating (qiymatlar bir xil boʻlsa ham — kontekstlar farqli va konstantalar farqli nomlanishi kerak), literallarni konstantalar bilan almashtiring, testlar orqali tekshiring. 2-bosqichdagi xato eng keng tarqalgan: ikki xil tushuncha (millisekundlardagi timeout va baytlardagi chegara) son jihatdan bir xil boʻlishi mumkin (masalan 5000), ammo semantik jihatdan bu turli kattaliklar va ularni bitta konstantada birlashtirib boʻlmaydi.

java
// oldin — turli kontekstlarda bir xil raqam
public class Config {
    public void setupCache() {
        cache.setMaxSize(5000); // 5 MB
    }
    public void setupTimeout() {
        client.setReadTimeout(5000); // 5 soniya
    }
}

// keyin — turli kontekstlar uchun turli konstantalar
public class Config {
    private static final int CACHE_MAX_SIZE_MB = 5;
    private static final int READ_TIMEOUT_SECONDS = 5;

    public void setupCache() {
        cache.setMaxSize(CACHE_MAX_SIZE_MB * 1024 * 1024);
    }
    public void setupTimeout() {
        client.setReadTimeout(
            READ_TIMEOUT_SECONDS * 1000
        );
    }
}

Yangi kod uchun qoida oddiy: 0, 1, -1, true, false, null va boʻsh satrdan tashqari har bir literal konstantaga chiqariladi. Istisnolar: matematik konstantalar (har doim standart kutubxona orqali), test maʼlumotlari (testda literal qoldirish mumkin, ammo izohli oʻzgaruvchi nomi bilan) va oshirish uchun chegara qiymatlari (siklda i + 1 — normal).

Tez-tez beriladigan savollar

100 magic number hisoblanadimi, agar bu 100 foiz boʻlsa?

Ha, 100 ham magic number, agar kontekstsiz ishlatilsa. 100 oʻrniga MAX_PERCENT yoki PROBABILITY_SCALE yozing. Istisno: 100 kontekstda aniq foiz boʻlganda (masalan, foiz hisoblash formulasida), lekin bu holatda ham konstanta oʻqish qobiliyatini yaxshilaydi.

Testlarda raqamlar bilan qanday boʻlish kerak?

Testlarda ham nomlangan oʻzgaruvchilardan foydalanish yaxshiroq. assertEquals(42, result) oʻrniga val expected = 42; assertEquals(expected, result) yozing. Istisno: chegara qiymatlari uchun testlar (0, null, boʻsh satr) — ularni literal sifatida qoldirish mumkin, chunki test kontekstida oʻqiladi.

Raqamlarni Android resurslariga chiqarishga arziydimi?

Ha, UI bilan bogʻliq raqamlar (oʻlchamlar, boʻshliqlar, animatsiya davomiyligi) resurslarda boʻlishi kerak (dimens.xml, integers.xml). Biznes konstantalari (timeoutlar, limitlar) — companion object yoki konfiguratsiya faylida. Asosiy mezon: agar raqam mantiqni oʻzgartirmasdan oʻzgarishi mumkin boʻlsa — bu resurs.

Legacy loyihada magic numbersni qanday topish mumkin?

SonarQube-ni MagicNumber qoidasi bilan yoki ESLint-ni no-magic-numbers bilan ishga tushiring. Hisobot oling, foydalanish chastotasi boʻyicha saralang va uch yoki undan koʻp joyda uchraydigan raqamlardan boshlang. Ular eng katta ehtimol bilan konstantaga chiqarish uchun nomzodlardir.

Koddagi har bir raqamni konstantaga chiqarish kerakmi?

Yoʻq. Ruxsat etilgan literallar: 0, 1, -1 (oshirish/kamaytirish, boʻshlikni tekshirish), true, false, null, boʻsh satr. Qolganlarning hammasi nomlashni talab qiladi. Agar 0 raqami boʻshlikni tekshirish sifatida emas (masalan, 0 — ildiz kategoriya IDsi) ishlatilsa, unda 0 ham konstanta boʻlishi kerak: ROOT_CATEGORY_ID = 0.

Xulosa

  • Sehr — izohsiz literallar: raqamlar, satrlar, bayroqlar, maʼnosi kod oʻquvchidan yashirin.
  • Magic numbers — nomsiz raqamli konstantalar (86400, 1024, 0.85, 5000), tushunish uchun soha bilimi talab qiladi.
  • Magic strings — kompilyatorga koʻrinmaydigan va runtime xatolariga olib keladigan qattiq kodlangan kalitlar, URL va yoʻllar.
  • Magic flags — qiymati aniq boʻlmagan mantiqiy parametrlar (metod chaqiruvida true/false).
  • Vositalar: SonarQube, ESLint, Detekt, SwiftLint, PMD — hammasi MagicNumber qoidasini qoʻllab-quvvatlaydi.
  • Yechim: har bir literal (0, ±1, true, false, null, "" dan tashqari) izohli nom bilan nomlangan konstantaga chiqariladi.
  • Turli kontekstlar — turli konstantalar: timeout sifatida 5000 va kesh hajmi sifatida 5000 — turli mavjudotlardir.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing