گاونوکد — اصطلاحی غیررسمی برای کد منبع کمکیفیت است: غیرقابل خوانش، ضعیفاً ساختاریافته و دشوار برای حفظنظارت. به گزارش Stripe (2022)، برنامهنویسان تا 40% از زمان کاری خود را صرف خواندن و فهمیدن کد بد نوشتهشده میکنند. در جامعه روسزبان این اصطلاح آنچنان رایج است که سایت تخصصی govnokod.ru وجود دارد که برنامهنویسان نمونههای خصوصاً برجسته را در آن منتشر میکنند.
نکات کلیدی
گاونوکد — یک ویژگی ذهنی اما عموماً پذیرفتهشده برای کدی است که حداقل استانداردهای کیفی را رعایت نمیکند. روبرت مارتین در کتاب «کد پاک» (2008) کد بد را کدی تعریف میکند که «مانع درک اینکه چه میکند میشود». گاونوکد میتواند از نظر نحوی صحیح و حتی کار کند، اما حفظنظارت آن برای تیم به کابوس تبدیل میشود.
اصطلاح گاونوکد در جامعه روسزبان رایج است. در انگلیسی از اصطلاحات رسمیتری مانند spaghetti code، dirty code، technical debt code استفاده میشود. اما رنگ عاطفی «گاونوکد» نگرش برنامهنویسان را نسبت به چنین کدی — ترکیبی از خشم، انزجار و احساس توهین حرفهای — بهتر منتقل میکند.
به گزارش پژوهش McKinsey (2023)، شرکتهایی با بدهی فنی بالا — و گاونوکد عمدهترین جزء آن است — 20–40% بیشتر منابع را برای توسعه ویژگیهای جدید هزینه میکنند. کیفیت کد مستقیماً بر شاخصهای کسبوکار تأثیر میگذارد و این استعاره نیست، بلکه واقعیتی ثابتشده است.
معیارهای عینی وجود ندارد، اما معیارهای عملی وجود دارد: اگر برنامهنویس بیش از 5 دقیقه صرف فهمیدن یک تابع 20 خطی کند — این گاونوکد است. اگر تغییر یک خط سه ماژول غیرمرتبط را مخروب کند — این گاونوکد است. اگر نتوان کد را بدون بازنویسی کامل با آزمایش پوشانید — این گاونوکد است.
کپی-پیست (برنامهنویسی کپی-پیست) — یکی از برجستهترین و آسانترین نشانههای قابل کشف است. وقتی همان بلوک کد در چند مکان با تغییرات کمی تکرار میشود، این نه تنها گاونوکد، بلکه منبعی برای باگهای آینده است. تصلیح در یک جا و عدم تصلیح در دیگری — وضعیتی تیپیکی.
نامهای بیمعنی متغیرها — کلاسیک. متغیرهایی با نامهای `a`، `b`، `x`، `data`، `temp`، `tmp`، `result`، `list`، `obj` هیچ اطلاعاتی درباره کاربرد خود نمیدهند. خواننده کد مجبور است کل تابع را تحلیل کند تا بفهمد چه چیزی در متغیر ذخیره شده است. روبرت مارتین این را «دروغ در نام» مینامد — نام قول اطلاعات میدهد، اما آن را تأمین نمیکند.
تودرون عمیق — وقتی شرایط، حلقهها و مدیریت خطا یک ساختار با 5+ سطح تورفتائه ایجاد میکنند. چنین کدی بدون پیمایش جانبی یا پیگیری ذهنی تمام سطوح قابل خواندن نیست. این راهی مستقیم به خطاهاست: اپراتورهای منطقی به راحتی اشتباه میشوند و اقواس بسته را میتوان نادیده گرفت.
| نشانه | نمونه گاونوکد | کد پاک |
|---|---|---|
| کپی-پیست | یک بلوک 5 بار کپی شده | در یک تابع جایگزین شده |
| نامها | `var a = getData()` | `var userList = getData()` |
| تودرون | 6 سطح if/for | 2–3 سطح با return early |
| توابع | تابع 300 خطی | به 3–5 روش تقسیم شده |
| توزیحات | `i++ // increment i` | کد قابل فهم بدون توزیح |
Dead code — توابع، متغیرها، کلاسهایی که هیچجا استفاده نمیشوند. این حجم کد را افزایش میدهد، برنامهنویس را منحرف میکند و ایده غلطی از قابلیتهای سیستم ایجاد میکند. Magic numbers — اعداد بدون زمینه. God-کلاسها — کلاسهایی که همه چیز را یکجا انجام میدهند و اصل مسئولیت مفرد (SOLID: S) را نقض میکنند.
کمبود زمان — شایعترین دلیل. وقتی موعدهای تحویل نزدیک هستند، برنامهنویسان کیفیت را فدای سرعت میکنند. از نظر تاکتیکی این ممکن است موجه باشد، اما از نظر استراتژیک — این انباشت بدهی فنی است. مشکل اینجاست که به ندرت به گاونوکد «موقت» برای تصلیح بازمیگردند.
عدم وجود بررسی کد — دومین دلیل اهمیت. وقتی کد بدون بررسی همکاران تنها نوشته میشود، الگوهای بد تقویت شده و تکثیر میشوند. بررسی کد نه تنها کنترل کیفیت، بلکه انتقال دانش در تیم نیز هست. پروژههای بدون بررسی به حتم به گاونوکد تبدیل میشوند.
مهارت پایین برنامهنویس یا عدم وجود استاد. جونیورهای بدون نظارت به طور طبیعی گاونوکد مینویسند — این بخشی از فرآیند یادگیری است. مشکل وقتی ایجاد میشود که این کد بدون بررسی و بازپیرایی وارد تولید شود.
در تیمهایی که شعار «کار میکند — کافیست» است، گاونوکد شکوفایی میکند. نبود استانداردهای کدنویسی، نیازمندیهای آزمایش و فرآیندهای بررسی محیطی ایجاد میکند که کیفیت کد برای هیچ کس اهمیت ندارد. چنین پروژههایی سریعاً به «لگاسی» تبدیل میشوند — کدی که از دست زدن به آن میترسند.
اصلی پیامد گاونوکد — کاهش سرعت توسعه است. پارادوکس کد بد ایناست که نسخه اول را سریع مینویسد، اما هر ویرایش بعدی زمان بیشتری میبرد. نمودار وابستگی سرعت توسعه به کیفیت کد نمایی نمایی است — پس از گذشتن از حد مشخصی، افزودن ویژگیهای جدید عملاً غیرممکن میشود.
جابه جایی نیروی کار — پیامدی غیرمستقیم اما جدی. برنامهنویسان، خصوصاً مجربان، نمیخواهند با گاونوکد کار کنند. به گزارش Stack Overflow Developer Survey 2024، 47% برنامهنویسان کیفیت بییس کد را یکی از عوامل کلیدی در انتخاب محل کار عنوان میکنند. پروژههایی با کد بد بهترین کارکنان را از دست میدهند.
امنیت — قربانی دیگر گاونوکد. کد بد نوشته شده حاوی آسیبپذیریهای بیشتری است: استثنای های پردازش نشده، SQL-injection، XSS، نشت حافظه. کد کیفی با آزمایشهای واحد و بررسی کد اکثر این مشکلات را قبل از تولید گیرنداری میکند.
SonarQube و ابزارهای مشابه میتوانند بدهی فنی را به ساعت یا روز تخمین بزنند. به عنوان مثال، 500 اشترار درباره کپی-پیست، 200 درباره اعداد جادویی و 50 درباره تودرون عمیق — 30 روز بدهی فنی را نشان میدهند. این اعداد را میتوان و باید برای تاجیه بازپیرایی به مدیریت نشان داد.
اصل DRY (Don't Repeat Yourself) — اولین چیزی که باید پیاده کنید. هر قسمت منطق باید در یک نسخه وجود داشته باشد. به جای کپی-پیست، کد تکراری را در یک تابع، کلاس یا ماژول جدا کنید. به جای اعداد جادویی — ثابتهای نامگذاری شده. به جای توابع طولانی — چند تابع کوچک.
اصل KISS (Keep It Simple, Stupid) از پیچیدگی زیاد جلوگیری میکند. اگر وظیفه را میتوان در 10 خط حل کرد — 50 خط ننویسید. اگر حلقه از استریم سادهتر است — از حلقه استفاده کنید. اگر تابع ساده از دکوراتور قابل فهمتر است — تابع بنویسید. سادگی ویژگی اصلی کد قابل حفظ است.
اصل Boy Scout Rule — «کد را بهتر از آنچه پیدا کردی ترک کن». حتی بهبودهای کوچک در هر ویرایش به مرور زمان گاونوکد را به کد مناسب تبدیل میکنند. تغییر نام متغیر، تقسیم یک تابع بزرگ، افزودن آزمایش — هر بهبودی اهمیت دارد.
// کد بد — کپی-پیست، اعداد جادویی، نامهای ضعیف
function calc(a, b, c) {
let x = a * 0.85;
if (b > 1000) { x = x * 0.9; }
let y = c * 0.85;
if (b > 1000) { y = y * 0.9; }
return x + y;
}
// کد پاک — نامهای واضح، DRY، ثابتها
const DISCOUNT_RATE = 0.85;
const BULK_THRESHOLD = 1000;
const BULK_DISCOUNT = 0.9;
function applyDiscount(amount, quantity) {
let price = amount * DISCOUNT_RATE;
if (quantity > BULK_THRESHOLD) {
price = price * BULK_DISCOUNT;
}
return price;
}
function calculateTotal(items, quantity) {
return items.reduce((sum, item) => {
return sum + applyDiscount(item, quantity);
}, 0);
}
یک نمونه تیپیک در Python را بررسی کنیم. تابع سفارشات را پردازش میکند، اما بد: 80 خط، تودرون عمیق، اعداد جادویی، تکرار. پس از بازپیرایی، کد خوانا، آزمایشپذیر و قابل حفظ میشود.
# کد بد — یک تابع همه کار را انجام میدهد
def process_order(order):
if order.get("type") == "premium":
if order["amount"] > 100:
discount = 0.8
else:
discount = 0.9
else:
discount = 1.0
total = order["amount"] * discount
return total
# کد پاک — توابع و ثابتهای جداشده
class OrderProcessor:
PREMIUM_DISCOUNT_HIGH = 0.8
PREMIUM_DISCOUNT_LOW = 0.9
PREMIUM_THRESHOLD = 100
def get_discount(self, order):
if order.type == "premium" and order.amount > self.PREMIUM_THRESHOLD:
return self.PREMIUM_DISCOUNT_HIGH
return self.PREMIUM_DISCOUNT_LOW
def calculate_total(self, order):
return order.amount * self.get_discount(order)
تابع خوب یک کار انجام میدهد و آن را خوب انجام میدهد. اگر تابع سه کار مختلف انجام میدهد — آن را تقسیم کنید. اگر تابع بیش از 20 خط دارد — احتمالاً قابل تقسیم است. اگر در تابع بیش از دو سطح تورفتائه وجود داشته باشد — بازپیرایی لازم است.
تحلیلگرهای ایستاتیک کد — خط اول دفاع در برابر گاونوکد. ESLint (JavaScript)، Pylint (Python)، SonarQube (چندزبانه)، Checkstyle (Java) به طور خودکار کپی-پیست، اعداد جادویی، بلوکهای catch خالی، توابع خیلی طولانی و صدها الگوی ضد دیگر را کشف میکنند.
Code style و فرماتکنندهها — سطح دوم حفاظت. Prettier، Black، gofmt کد را به طور خودکار فرمات میکنند و مشکلات فاصله، تورفتائه و پرانتز را برطرف میکنند. سبک واحد در تیم کد را بدون توجه به نویسنده قابل خواندن میکند. بحثهای فرمتبندی باید خودکار شوند.
بررسی کد — سومین و مهمترین سطح. هیچ تحلیلگر جایگزین انسانی نمیشود که متوجه اشتباه بودن معماری راهحل یا انتخاب روش نادرست شود. بررسی مؤثر زمان میخواهد، اما با کاهش چند برابری میزان گاونوکد بازپرداخت میشود.
سوالات متداول
بسیار نادر. در پروتوتیپسازی یا هاکاتونها سرعت از کیفیت مهمتر است، اما چنین کدی باید به عنوان موقت علامتگذاری شود و بدون بازپیرایی وارد تولید نشود. در تولید هیچ تاجیهی برای گاونوکد وجود ندارد — هر صرفهجویی در زمان اکنون به تضریفات چند برابر در آینده تبدیل میشود.
کد تابکار — کدی بیتجربه اما غالباً مخلصانه است که با افزایش مهارت بهبود مییابد. گاونوکد به طور عمدی یا بیاعتنایی به کیفیت است. تابکار میتواند کد غیرامثل اما خوانا بنویسد. گاونوکد اصلاً غیرقابل خواندن است — نویسندهاش اهمیت نمیدهد که آیا دیگران آن را میفهمند یا نه.
بازنویسی — آخرین راهحل است. بازپیرایی تدریجی ایمنتر است: ماژول را جدا کنید، آن را با آزمایش بپوشانید، قسمت به قسمت بازنویسی کنید. بازنویسی کامل پرخطر است — ممکن است منطق کسبوکار انباشته شده در کد قدیمی را از دست بدهید، از جمله پردازش موارد حاشیهای که هیچ کس مستند نکرده است.
از متریکها استفاده کنید: SonarQube بدهی فنی را به ساعت نشان میدهد. نشان دهید چقدر زمان برای باگهای کد قدیمی تلف میشود. سرعت توسعه ویژگیهای جدید را در بخشهای «پاک» و «کثیف» پروژه مقایسه کنید. به زبان کسبوکار ترجمه کنید: زمان پول است، و گاونوکد هزینه دارد.
«کد پاک» روبرت مارتین (2008) — کتاب مرجع برنامهنویسی کیفی است. در آن اصول نامگذاری، فرماتبندی، پردازش خطا و آزمایش توصیف شده است. به علاوه: «کد کامل» از استیو مککانل، «بازپیرایی» از مارتین فاولر، «گروه چهارنفری» درباره الگوهای طراحی. هر برنامهنویسی باید این کتابها را بخواند.
نتیجه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.