Autor: Rino Kovačević, Lead Software Developer, Devōt
“Tko radi, taj i griješi“, “Na greškama se najbolje uči“ – izreke su kojima se tješimo kada napravimo pogrešku. Programeri vole puno raditi, a ako žele pratiti nove trendove, stalno moraju učiti. Na temelju ovih izreka, izmišljenih podataka i mojih 7 godina rada kao programer, okružen drugim programerima, došao sam do zaključka da programeri jako puno griješe. Kako bi se te greške pronašle na vrijeme ili izbjegle, pišemo automatizirane testove, međusobno si pregledavamo kod, koristimo staging i preproduction okoline, radimo backupe, radimo s QA inženjerima te koristimo razne alate koji će ukazati na greške u što ranijoj fazi.
Unatoč mjerama opreza, i dalje se događa da pokoja greška procuri te dođe do produkcije. Što onda? Brzo otkriti uzrok te greške, popraviti je i što brže staviti u produkciju. Što manje korisnika osjeti posljedice tvoje greške, to bolje. S druge strane, što je ta greška veća ili duže na produkciji, to će se duže unutar firme o njoj pričati.
Međutim, nekada greške mogu biti prevelike ili pretjerano interesantne da o njima pričaju samo oni koji su ih doživjeli. Bit će na vijestima, o njima će se pisati po novinama, neke će dobiti svoju vlastitu Wikipedija stranicu, a neke će se pamtiti i 60 godina kasnije. U ovom članku ćemo istražiti neke od tih poznatih grešaka, saznati kako je došlo do tih grešaka te što iz njih možemo naučiti.
Mariner 1
Davne 1962. godine NASA je lansirala svoju prvu interplanetarnu letjelicu Mariner 1. Trebala je letjeti pored Venere, mjeriti njenu temperaturu, magnetska polja i druge stvari koje zanimaju te pametne ljude, no stvari nisu pošle po planu. Ubrzo nakon lansiranja, počela je letjeti u krivom smjeru te su odlučili radije pokrenuti protokole za samouništenje, nego riskirati potencijalnu štetu na Zemlji.
Tom neuspjehu obično se pripisuje programerska greška. Međutim, to nije bila bilo kakva greška, već jedna jedina izostavljena crtica u kodu. Što se dogodilo? U kodu je bila matematička operacija koja je sadržavala oznaku “R“ kao radius. Tu je zapravo trebao biti prosječni radius, čija je oznaka trebala biti “R-bar“ u kodu, a u fizici R̄. Ipak, nije u pitanju samo “jedna crtica”, ali za naslov članka “najskuplja crtica na svijetu“ zvuči bolje nego “najskuplja 4 znaka na svijetu“.
S obzirom na to da je kod ove greške riječ o fizici i matematici, zašto to onda nazivaju programerskom greškom? Greška je izvorno bila u izračunima, a programeri su je samo prepisali. U idealnom slučaju, bila bi otkrivena testiranjem ili kroz suradnju programera i matematičara ili fizičara. Programeri će često pisati kod za aplikacije izvan njihove domene. Stoga ne moraš biti pravnik kako bi radio aplikaciju za odvjetnike, niti građevinar da bi napravio alat za projektiranje, ali bitno je naučiti osnove te u suradnji s profesionalcima u tim domenama raspisati neke scenarije kojima ćeš kod moći testirati (i po mogućnosti pokriti automatiziranim testovima).
Što možemo naučiti iz Mariner 1 greške? Prije svega, za kod je potrebno pisati što više testova. Na velikim projektima gdje se miješa više domena, jako je bitna suradnja. Također, uvijek je dobro imati rezervni plan, možda ne nužno protokol za samouništenje kao NASA, ali dobro je planirati za situacije kada stvari krenu po zlu.
Milenijski (Y2K) bug
Svi koji se sjećaju svog dočeka 2000. nove godine, sjećaju se i svih razgovora o tome hoće li nakon ponoći računala prestati raditi, banke izgubiti sve podatke i avioni prestati letjeti. Nakon ponoći se gotovo ništa od toga nije dogodilo. Bilo je nekoliko slučajeva računalnih sustava koji su zakazali, ali se sve brzo popravilo.
Da TikTok generaciji, koja je propustila milenijski bug, dam malo konteksta, a i za one koji su imali pametnijeg posla kasnih 90-ih, pa su samo letimice čuli o tome:
Pedesetih godina kompjuterska memorija bila je jako skupa, otprilike $1 po bitu, dakle $8 po bajtu. Ondašnji programski jezici poput COBOL-a su zato u memoriju spremali samo zadnje 2 znamenke godine. Program je podrazumijevao da su prve 2 znamenke “19”.
Programeri su time uštedjeli nekoliko bitova tj. dolara po spremljenom datumu. Vjerovali su da će cijena kompjuterske memorije padati i ostavili su gotovo 50 godina da to poprave. Pretpostavke su im bile točne, greška je bila u odgađanju te prilagodbe.
Ljudi poput Boba Bemera su već 60-ih godina pričali o tome kako je potrebno napraviti prilagodbu,a 70-ih je pisao i članke o tome. Evidentno, nije ga baš puno ljudi slušalo te se na tome krenulo raditi tek 1994. godine. Do tada su se sustavi koji imaju tu grešku toliko rasprostranili i napravilo se toliko novog softvera baziranog na toj grešci da je količina posla za ispraviti postala ogromna. Neke estimacije kažu da je na tu prilagodbu potrošeno preko 300 milijardi dolara.
Jesmo li išta naučili iz Y2K greške? Vidjet ćemo 2038., kada nas čeka Y2K38 bug (ili the Epochalypse). To se odnosi na Unixove 32-bitne zapise vremena koji će doživjeti sličan problem 19.01.2038. godine, kada će mu ponestati bitova za prikazivanje vremena. Odgađanje stvari za kasnije nije nužno loše jer postoje situacije kada se to može isplatiti. Ali, kad god odgodiš nešto, pobrini se da to obaviš na vrijeme. Ako u kodu ostavljaš “TODO“ komentare, obavezno uz njih napiši tko je odgovoran riješiti ih i do kada.
World of Warcraft Corrupted blood pandemija
World of Warcraft je kompjuterska igrica za koju su svi vjerojatno čuli. Oni koji nisu, trebaju znati samo da je 2005. bila jako popularna i puno ju je igrača istovremeno igralo online na istom serveru. Jedan od elemenata igre je zajedničko osvajanje tamnica u kojem grupa igrača treba surađivati kako bi pobijedila sve neprijatelje koji se u njoj kriju. Na kraju jedne takve tamnice, dodane u rujnu 2005., glavni neprijatelj bi bacio magiju koja bi polagano ozljeđivala sve koji su pogođeni. Taj negativni efekt, naziva Corrupted blood, bi se širio na sve obližnje igrače. Nije bilo zamišljeno da to ikada izađe iz te tamnice jer bi igrači po izlasku iz tamnice bili izliječeni. Međutim, greška u kodu je omogućila da se preko igračevih ljubimaca negativni efekt proširi u ostatak virtualnog svijeta.
Corrupted blood “virus“ se brzo počeo širiti cijelim World of Warcraftom poput pandemije. Zbog gustoće igrača i NPC-ova (Non player character – likovi kojima ne upravljaju igrači, ali su bitan dio svih gradova) su se prvo zarazili najveći gradovi. Likovi igrača bi od tog virusa s vremenom bili ili izliječeni ili umrli, pa bi opet oživjeli, dok bi NPC-ovi ostali zaraženi cijelo vrijeme i jako doprinosili širenju virusa. Bilo je igrača koji su se trudili koristiti svoje magije kako bi izliječili što više drugih, ili bi stajali ispred gradova i upozoravali slabije igrače kako je ulazak opasan, sve u namjeri da zaustave širenje. Nekima je pak bilo zabavno pokušavati to što više proširiti.
Programeri su brzo doznali za svoj propust i krenuli su pokušavati popraviti situaciju. Isprobali su nekoliko zakrpi, ali nijedna nije uspjela u potpunosti maknuti taj virus jer bi uvijek ostao prisutan barem negdje i iznova se proširio. Nakon gotovo mjesec dana pokušavanja, odlučili su resetirati servere i vratiti ih u stadij prije nego što je ta tamnica uopće izašla i sve započelo.
Što možemo naučiti iz WoW Corrupted blood greške? Dogodila se na sličan način kao i većina programerskih grešaka – nije se razmišljalo o svim mogućim rubnim slučajevima. Širenje virtualnog “virusa“ poput pravog virusa unutar kompjuterske igrice raznim ljudima bio je jako interesantan koncept. Na primjer, neki igrači su godinama nakon tražili kompaniju da to ponovi (ovaj puta namjerno). Tu su bili i programeri koji vole slušati o tuđim propustima i razmišljati o kaosu koji se trebao događati da ih je natjerao da vrate servere na stanje od prije mjesec dana. Zanimljivo je da su čak i imunolozi bili zainteresirani za ovaj slučaj, pa su tako ovaj događaj koristili kao simulaciju pandemije za istraživanje, ne samo širenja virusa, već i ljudskog ponašanja u takvim situacijama.
The Heartbleed Bug
OpenSSL je tzv. cryptographic software library, odnosno open source kod koji pomaže složiti sigurnu, enkriptiranu vezu između servera i klijenta prateći sigurnosne standarde industrije. Kada programeri žele pratiti te sigurnosne standarde, umjesto da izmišljaju toplu vodu i rade stvari iz nule, samo dodaju taj library u svoj kod i koriste gotova rješenja.
Vrlo je nezgodno kada tvoj kod, koji je namijenjen za sigurnost, ima sigurnosnu rupu. OpenSSL je imao problem s curenjem informacija koje bi trebale biti zaštićene, zbog greške u implementaciji TLS heartbeat ekstenzije, zbog čega je dobio tako dramatično ime: Heartbleed Bug.
Problem je s vremenom bio popravljen, no svi koji koriste starije verzije OpenSSL librarya (izašle između 2011. i 2014.) ga moraju ažurirati s novijom verzijom kako bi se riješili sigurnosnog rizika. Procjenjuje se da su 2014. godine čak dvije trećine svih aktivnih internetskih stranica koristile OpenSSL. Naime, razlog tomu je što ga koriste popularni open source web serveri kao Apache i Ngnix.
Što možemo naučiti iz The Heartbleed Bug greške? Korištenje open source librarya danas je svakodnevica programerima. Programiranje bi bilo bitno sporije kada bi svaki problem morali rješavati ispočetka, ignorirajući tuđa dostupna rješenja. Bez obzira na to, treba biti oprezan svaki puta kada dodaješ novi library u svoj sustav, a sama činjenica da je nešto popularno, ne garantira da je i sigurno.
GitLab backup incident
GitLab je platforma za kolaboraciju prilikom razvoja softvera. Procjenjuje se da ima oko 30 milijuna korisnika.
U siječnju 2017. inženjeri u GitLabu su primijetili veće opterećenje baze od očekivanja. Dok su istraživali što se događa i pokušavali normalizirati situaciju, naišli na nekoliko problema. Stoga su odlučili ručno sinkronizirati određene baze podataka. Prilikom toga, došlo je do pogreške koju su primijetili i prekinuli u roku od nekoliko sekundi, no već su bili izgubili 300 GB korisničkih podataka.
U ovakvim slučajevima su korisni backupi, koje je GitLab i imao. Međutim, kada su krenuli primjenjivati taj backup, primijetili su da njihove procedure za oporavak ne funkcioniraju dobro i da nemaju svježi backup. Na kraju su morali koristiti podatke stare šest sati koje su imali u svrhu kopiranja na testno okruženje. Izgubiti šest sati podataka kada imaš 30 milijuna korisnika nije mala stvar i novost da tvoj proces za spremanje i primjenjivanje backupa nije dobar, tek kada ti treba, zasigurno nikoga nije razveselila.
Što možemo naučiti od ove greške? Kao programer, znaš da kada su god neki podaci u pitanju, uvijek moraš imati backup. Ova situacija nas uči da imati backup samo po sebi nije dovoljno. Način na koji radiš backupe treba prilagoditi sustavu, tipu podataka i korisnicima. Osim toga, jako je bitno redovito testirati svoje backupe, kao i backup procedure.
Što možemo zaključiti iz ovih programerskih grešaka?
Neki filozof je jednom rekao “Oni koji ne pamte prošlost, osuđeni su na to da je ponavljaju.“ Mi programeri imamo tu sreću što povijest koja nas zanima počinje tek u 20-om stoljeću, pa je nema puno. To je dvosjekli mač, jer je dosta jednom zaraziti stotine tisuća igrača magičnim virusom u svojoj igri, i ljudi će o tome pričati i 18 godina kasnije.
Svaki puta kada pročitate neki članak o tome kako je neka firma nešto zeznula, predlažem vam da razmislite o tome kako biste vi u toj situaciji reagirali i pokušajte zaključiti što možete naučiti iz njihovih propusta. U Devōtu volimo učiti iz tuđih grešaka, pa mogu ponosno reći da do sada nismo morali uništiti niti jednu svemirsku letjelicu vrijednu 20 milijuna dolara.