Kako softverski projekti propadaju: obrasci koji se ponavljaju

Kroz godine rada i komunikacije s drugim developerima susreo sam veliki broj softverskih projekata razvijenih u različitim tehnologijama. Neki su započeli s jasnom vizijom, definiranim pravilima i velikim entuzijazmom. Drugi nisu imali ni osnovne temelje.

Unatoč tim razlikama kod mnogih sam primijetio gotovo identičan obrazac propadanja.

Ne govorim o komercijalnom neuspjehu, nedostatku korisnika ili lošem marketingu. Govorim o tehničkom propadanju softvera koji možda i dalje radi, ima korisnike i redovito dobiva nove funkcionalnosti, ali ga je svakim danom sve teže održavati.

Takvi projekti rijetko propadaju preko noći. Propadaju polako, gotovo neprimjetno.

Često to počinje jednim kompromisom kojeg nitko u tom trenutku ne smatra važnim.

Propadanje ne počinje velikom greškom

Projekt može biti aktivan, imati koliko toliko stabilnu bazu korisnika što može zavarati da je sve u redu. I najčešće neće propasti jednom lošom odlukom.

No kada dođe do “privremenih” kompromisa da će se nešto napraviti kako treba kada bude više vremena, da automatski testovi sada nisu potrebni i nemamo vremena za refaktoring počinje proces polaganog raspadanja.

Privremeni kompromisi jako često nisu privremeni nego postanu način rada. A linijom manjeg otpora bitno je samo isporučiti nije bitno što. Sve do jednom.

Kada se zahtjevi mijenjaju brže od koda

Nije problem kada se zahtjevi mijenjaju. Razvoj softvera nije statičan proces i promjene su očekivane. Problem nastaje kada se mijenjaju bez razumijevanja njihovih posljedica.

Funkcionalnost koja je jučer bila završena danas više ne odgovara novim zahtjevima. Dodaje se još jedan uvjet, još jedna iznimka, još jedno polje. Rok ostaje isti jer se radi o “samo maloj izmjeni”.

No ono što se korisniku čini kao mala promjena može zahtijevati izmjene baze podataka, poslovne logike, korisničkog sučelja i postojećih integracija.

Ako se takve promjene stalno dodaju bez ponovne procjene vremena i resursa, projekt s vremenom postaje skup međusobno povezanih kompromisa.

Na kraju nitko više nije siguran što je bio izvorni zahtjev, što je naknadno dodano i zašto je nešto implementirano baš tako. A dokumentacija, ako postoji, najčešće je ostala negdje na početku.

Kada rokovi određuju kvalitetu

Nerealni rokovi i procjene često su početak problema. Nekada se rok isporuke odredi prije nego što se uopće zna što treba napraviti, a procjena developera postane samo formalnost.

Ako je potrebno deset dana, a na raspolaganju je pet, posao neće čarobno postati dvostruko jednostavniji. Nešto se mora izbaciti.

Najčešće to budu stvari koje korisnik ne vidi. Testovi, dokumentacija, refaktoring, provjera kvalitete i sve ono što nije nužno da bi funkcionalnost na prvi pogled radila.

Projekt je isporučen na vrijeme, svi su zadovoljni, a tehnički dug ostaje developerima koji će ga održavati.

Problem nastaje kada takav način rada postane pravilo. Svaka sljedeća isporuka sve je zahtjevnija jer se uz nove funkcionalnosti mora nositi i teret prethodnih kompromisa.

Na kraju se postavlja pitanje zašto razvoj traje toliko dugo, iako je upravo stalno forsiranje brzine jedan od razloga.

Pravila postoje, ali samo na papiru

U zdravom projektu, pogotovo kada na njemu radi više osoba, treba imati i zadovoljiti neke standarde. Naming konvencije, struktura projekta, code review proces, CI/CD i sl. ne bi trebali biti opcionalni nego obavezni.

U projektu koji propada ta i druga pravila su nešto što se zaobilazi. Bez dosljedne primjene standarda developeri s vremenom počinju razvijati vlastite načine rada. To kratkoročno daje osjećaj brzine, a dugoročno ubija projekt.

Tehnički dug postaje norma

Tehnički se dug ne može uvijek izbjeći, ali kao i svaki dug ako se gomila jednom će puknuti. Sve ono što će se “riješiti kasnije” postaje problem ako to kasnije nema jasan rok ni plan.

Kada kod prestane biti razumljiv, a postane nešto što se izbjegava jer će se nešto drugo pokidati već je kasno. To se najlakše može vidjeti u situacijama kada ispravljanje grešaka traje duže nego implementacija nove funkcionalnosti, a svaka isporuka je stres.

Kada taj stres postane norma lako je djelovati zaposleno i prihvatiti da je to način rada, čak se osjetiti važno spašavajući nešto do čega nije trebalo niti doći.

Gubitak vlasništva nad kodom

Kao i u svemu, mora postojati odgovorna osoba jer “puno baba kilavo dijete”. Možda je projekt u početku imao odgovornu osobu, onda se ona promijenila ili je došlo više developera od kojih je svaki radio po svome.

Tko je kasnije odgovoran za nered? Na čiji način se radi? Tko će popravljati za kime? Puno pitanja, a nitko spreman odgovoriti. Lakše je prešutjeti problem nego riskirati sukob upozoravanjem na njega.

Ljudi mogu otići, ali znanje ne bi trebalo otići za njima. No ako je svatko radio po svome to se najčešće dogodi jer “šta ja znam što je on radio”. Novi developer može krpati projekt no ako je to bez razumijevanja i nema dokumentacije, tehnički dug će samo rasti.

Kolektivno vlasništvo nad kodom nije samo po sebi problem. Problem je kada svi imaju pravo mijenjati kod, ali nitko ne preuzima odgovornost za njegovu kvalitetu i održivost.

Tehnologija napreduje, projekt stoji

Jedan od najvidljivijih znakova zanemarivanja projekta su zastarjele tehnologije.

Projekt je možda započeo na tada aktualnoj verziji Angulara ili neke druge tehnologije. No kako godine prolaze projekt stoji dok nove verzije redovno izlaze.

Još je pogubnije kada se već zastarjele tehnologije kopiraju za nove projekte i tako prenose postojeći tehnički dug. Pa tako novi projekt starta sa deset i više godina starim ovisnostima koje imaju toliko ranjivosti da ih nitko više neće moći ispraviti čak i da želi. Pogotovo u produkciji.

Razlozi su uvijek slični. Nema se vremena, zašto dirati ako radi ili ažurirat ćemo kada bude potrebno. Kada je brzina isporuke jedini prioritet, ažuriranje nikada ne dolazi na red.

Problem je što održavanje projekta ne znači samo dodavanje novih funkcionalnosti ili ispravljanje funkcionalnih grešaka.

Ako nema održavanja i praćenja razvoja tehnologije na kojoj se projekt temelji dugoročna održivost je upitna. Što se nadogradnje dulje odgađaju to postaje složenije, skuplje i rizičnije.

U jednom trenutku ono što je moglo biti redovno održavanje postaje zaseban projekt.

Dokumentacija? Postoji. Negdje.

Na prste jedne ruke mogu nabrojati potpunu i ažurnu dokumentaciju koja je pratila stvarno stanje softvera. Nikome se ne da ili će to kasnije.

Najčešće su to tri faze:

  • dokumentacija ne postoji
  • dokumentacija postoji, ali je vidljivo zastarjela
  • dokumentacija postoji i aktivno smeta jer sadržava netočne informacije

Sve to pomaže da nitko ne zna što i zašto radi. “Ma samo nešto napravi da radi i baš te briga.”

Tu je lako srušiti Chestertonovu ogradu jer se ne zna što stoji iza neke linije koda koja se može činiti skroz nelogičnom. Bez dokumentacije i pravila puno takvih ograda se može nalaziti u projektu.

Chestertonova ograda opisuje jednostavno načelo: prije nego što nešto uklonimo ili promijenimo, trebamo razumjeti zašto je uopće postavljeno.

Komunikacija postaje rizik

U početku se projekt, ako ima vremena, razrađuje. Daju se ideje, planiraju se razvojne faze, zna se rok za isporuku.

Onda krene “fušarenje” jer ako se moglo na drugom projektu, a bio je brz zašto se ne bi moglo i sada. “Samo da završimo” postaje moto, a nove ideje smetnja. Problemi se guraju pod tepih.

Onaj tko digne tepih dobiva “metlu” da to pomete. I što se dogodi? Više nitko ne diže tepih iako je već na oko vidljivo da se ispod nalazi “tona prašine”.

Upozoravanjem na problem postaješ veći problem od pravog problema.

Projekt preživljava

Projekt nije mrtav, ali više ne napreduje. Bez razbijanja i preslagivanja svega rast postaje nemoguć. Projekt nije održiv. Svaki korak naprijed postaje dva koraka unazad.

Svaka nova funkcionalnost traje predugo, unosi sve više grešaka i povećava kompleksnost. Ako je projekt sam sebi svrha to možda nije problem, ali ako treba riješiti neki poslovni problem onda otežava to rješavanje.

Može li se sve to spriječiti?

Uz zdrave temelje može. Potrebna su jasna i dosljedna pravila kojih se svi developeri pridržavaju. Nekada jedno “pravo” pravilo može značiti više nego nabacanih njih 10 koji zapravo ništa ne znače.

Code review bi trebao biti standard, a ne opcija. Kada je opcija počinje “fušarenje” jer “kod ionako nitko ne gleda”. Uz sve veću upotrebu umjetne inteligencije taj problem može postati još izraženiji. Kod se može generirati brže nego ikada, ali ako ga nitko ne razumije, ne provjerava i ne preuzima odgovornost za njega brzina razvoja samo ubrzava gomilanje tehničkog duga.

Vrijeme za mini refaktoring treba biti ugrađeno u postojeće procjene. Bez redovnog refaktoringa dugoročni razvoj i održavanje postaju sve teži. Tada se svaki projekt može ponovno raditi od nule kada više nije moguće dodati novu funkcionalnost bez da se sve raspadne.

Jasno definirana odgovornost smanjuje prostor za međusobno prebacivanje krivnje. Tko je što napravio (dokumentacija) i zašto (dokumentacija), gdje stoji kod (dokumentacija). Ako su svi radili sve, svatko na svoj način i nitko ne zna gdje se koji dio projekta nalazi nitko nije odgovoran.

Kontinuirano održavanje ovisnosti. Nadogradnje frameworka, biblioteka i razvojnih alata trebaju biti planirani dio razvoja. Ne kažem da svaku novu verziju odmah treba uvoditi u produkciju, ali ne smije se godinama niti ignoriorirati njihov razvoj.

Automatizacija pravila jer pravila koja ovise o dobroj volji developera prije ili kasnije će se prekršiti. Zato je korisno automatizirati ono što se može: linting, formatiranje, testove, provjere ovisnosti, CI/CD proces i sl.

Zaključak

Softverski projekti ne propadaju jer su ljudi (developeri, voditelji projekata, Scrum Masteri i ostali) nesposobni. Propadaju kada organizacijski procesi ne uspijevaju prepoznati, spriječiti i ispraviti loše razvojne prakse.

Kada jedna osoba napravi kompromis, druga napravi još veći, a treća više ne vidi problem.

S vremenom ono što je prije bilo neprihvatljivo postaje standard. Pravila gube smisao, dokumentacija zastarijeva, tehnički dug raste, a odgovornost se prebacuje s jedne osobe na drugu.

I možda je upravo to najopasniji trenutak u životnom ciklusu softverskog projekta. Svi znaju da nešto nije u redu, ali više nitko ne očekuje da će se išta promijeniti.