Говнокод — је сленг назив за изворни код ниског квалитета: нечитак, лоше структуриран и тежак за одржавање. Према извештају 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-тестовима и код-ревјуом хвата већину ових проблема пре продукције.
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 креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође