Говнокод — е сленгово название на изходен код с ниско качество: нечетен, лошо структуриран и труден за поддръжка. Според доклада на Stripe (2022), програмистите прекарват до 40% от работното си време в четене и разбиране на лошо написан код. В рускоезичната общност терминът е толкова разпространен, че съществува специализиран сайт govnokod.ru, където програмистите публикуват примери на особено ярки случаи.
Основно
Говнокод — е субективна, но широко приета характеристика на код, който не отговаря на минималните стандарти за качество. Роберт Мартин в книгата си „Чист код” (2008) определя лошия код като код, който „пречи да се разбере какво прави”. Говнокодът може да е синтактично правилен и дори да работи, но поддръжката му става кошмар за екипа.
Терминът говнокод е разпространен именно в рускоезичната общност. В английския се използват по-формални термини: spaghetti code, dirty code, technical debt code. Емоционалният обелвка на „говнокод” обаче предава по-точно отношението на програмистите към такъв код — смес от раздражение, отвращение и професионална обида.
Според проучването на McKinsey (2023), компаниите с високо ниво на технически дълг — а говнокодът е неговият основен компонент — харчат 20–40% повече ресурси за разработката на нови функции. Качеството на кода пряко повлиява бизнес показателите и това не е метафора, а потвърден факт.
Обективни метрики не съществуват, но има практически критерии: ако програмист харчи повече от 5 минути за разбирането на функция от 20 реда — това е говнокод. Ако промяната на един ред разваля три несвързани модула — това е говнокод. Ако кодът не може да се покрие с тестове без пълно преписване — това е говнокод.
Копипаста (copy-paste programming) — един от най-ясните и лесно откриваеми признаци. Когато един и същ блок код се повтаря на няколко места с минимални промени, това не е просто говнокод, а и източник на бъдещи грешки. Поправяне на едно място и пропускане на друго — типична ситуация.
Безсмислени имена на променливите — класика. Променливите с имена `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).
Липса на време — най-често срещаната причина. Когато крайните срокове настигат, програмистите жертват качество за сметка на скоростта. Тактически това може да е оправдано, но стратегически — това е натрупване на технически дълг. Проблемът е, че „временният” говнокод рядко се върщат да поправят.
Липсата на код ревю — втората по значение причина. Когато кодът се пише самостоятелно без проверка от колеги, лошите модели се затвърдяват и размножават. Code review е не само контрол на качеството, но и предаване на знания в екипа. Проектите без ревю неизбежно се свиват към говнокод.
Ниска квалификация на програмиста или липса на менторство. Джуниор програмистите, оставени без надзор, естествено пишат говнокод — това е част от процеса на обучение. Проблемът възниква, когато този код попадне в производство без ревю и рефакторинг.
В екипите, където мотото е „работи — и това е достатъчно”, говнокодът цъфти. Липсата на стандарти за кодиране, изисквания за тестване и процеси за ревю създава среда, в която качеството на кода никого не грижи. Такива проекти бързо стават „legacy” — код, от който се страхуват да пипат.
Основната последица на говнокода е забавяне на разработката. Парадоксът на лошия код е, че той позволява бързо написване на първата версия, но всяка последваща промяна отнима все повече време. Графиката на зависимостта на скоростта на разработка от качеството на кода е експоненциална — след определен праг добавянето на нови функции става практически невъзможно.
Текучест на кадри — ниидректна, но сериозна последица. Програмистите, особено опитните, не искат да работят с говнокод. Според Stack Overflow Developer Survey 2024, 47% от програмистите наричат качеството на кодовата база като един от ключовите фактори при избора на работно място. Проектите с лош код губят най-добрите си служители.
Сигурност — още една жертва на говнокода. Лошо написаният код съдържа повече уязвимости: необработени изключения, SQL-инжекции, XSS, изтичане на памет. Качественият код с unit тестове и code review хваща повечето от тези проблеми преди производството.
SonarQube и подобни инструменти могат да оценят техническия дълг в човекочасове или дни. Например, 500 предупреждения за копипаста, 200 за магически числа и 50 за дълбоко нестване дават оценка от 30 дни технически дълг. Тези цифри могат и трябва да се показват на ръководството за обосноваване на рефакторинга.
Принципът DRY (Don't Repeat Yourself) — първият, който трябва да се внедри. Всяка част от логиката трябва да съществува в единствен екземпляр. Вместо копипаста — изнесете повтарящия се код в отделна функция, клас или модул. Вместо магически числа — именувани константи. Вместо дълги функции — няколко малки.
Принципът KISS (Keep It Simple, Stupid) предпазва от прекалена сложност. Ако задачата може да се реши в 10 реда — не пишете 50. Ако цикълът е по-прост от stream — използвайте цикъла. Ако обикновената функция е по-разбираема от декоратор — пишете функция. Простотата е основното качество на лесно поддържаем код.
Принципът 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 автоматично форматират кода, премахвайки проблеми с интервали, отстъпи и скоби. Единнен стил в екипа прави кода четен независимо от това кой го е написал. Споровете за форматиране трябва да се автоматизират.
Code review — третото и най-важното ниво. Никой анализатор не може да замени човек, който забелязва, че архитектурата на решението е грешна или че програмистът е избрал грешен подход. Ефективното ревю изисква време, но се отплаща чрез намаляване на количеството говнокод многократно.
Често задавани въпроси
Изключително рядко. При прототипиране или хакатони скоростта е по-важна от качеството, но такъв код трябва да бъде маркиран като временен и не трябва да попада в производство без рефакторинг. В производството няма оправдание за говнокод — всяко икономия на време сега ще се превръне в многократни загуби в бъдещето.
Кодът на новака е неопитен, но често искрен код, който се подобрява с растежа на уменията. Говнокодът е съзнателно или безразлично пренебрегване на качеството. Новакът може да напише неоптимален, но четен код. Говнокодът обаче е принципно нечетен — неговият автор не дава дали другите ще го разберат или не.
Преписването е крайна мярка. Постепенният рефакторинг е по-безопасен: отделяте модула, покривате го с тестове, преписвате част по част. Пълното преписване е рисковано — може да загубите бизнес логиката, натрупана в стария код, включително обработката на гранични случаи, които никой не е документирал.
Използвайте метрики: SonarQube ще покаже техническия дълг в часове. Покажете колко време се губи за грешки в стария код. Сравнете скоростта на разработка на нови функции в „чистата” и „мръсната” част на проекта. Преведете на езика на бизнеса: времето е пари, а говнокодът струва пари.
„Чист код” от Роберт Мартин (2008) — библията на качественото програмиране. В нея са описани принципите за именуване, форматиране, обработка на грешки и тестиране. Допълнително: „Съвършен код” от Стив МакКонел, „Рефакторинг” от Мартин Фаулър, „Бандата на четирима” за дизайн моделите. Тези книги трябва да прочете всеки програмист.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също