"GOTO Considered Harmful" i strukturirano programiranje
Jedan Nizozemac je 1968. napisao pismo, urednik mu je zašiljio naslov, i pola informatike se od tada svađa oko jedne rezervirane riječi.
Godina je 1968., a informatika – riječ koja se tek počinje koristiti, jer se prije toga to zvalo obrada podataka, kao da programiraš rublje – ima problem koji nitko ne želi izgovoriti naglas. Kod je narastao. Sustavi koji su trebali biti alat postali su čudovišta koja se sama jedu, i kad netko pokuša popraviti jednu grešku, otvore se tri nove, kao u onoj igri gdje udaraš krtice čekićem, samo što je čekić drugi programer, a krtice su bube koje si sam posadio prošlog utorka.
NATO – da, ta NATO, ona s tenkovima – organizira konferenciju u njemačkom gradiću Garmisch-Partenkirchenu, i tamo, pred svima, netko izgovori dijagnozu i dade joj ime: softverska kriza. Ne kriza jedne firme, nego kriza cijele struke. (Detaljnije o tome u poglavlju 31 – ovdje samo napomena da je pacijent upravo primljen na hitnu i da je dijagnoza već potvrđena dok se ovo poglavlje događa.)
A dok se to zbiva u konferencijskim salama, u Nizozemskoj sjedi čovjek koji sve to gleda kao netko tko je odavno primijetio simptome i sad čeka da mu ostatak svijeta stigne na predavanje. Edsger Dijkstra ne piše kod za novac. Ne prodaje ništa. Radi u Eindhovenu, drži svežanj papira, i pero mu je oružje na način na koji je drugima lemilica. Piše bilješke koje potpisuje inicijalima – „EWD”, pa broj – i šalje ih prijateljima i neprijateljima poštom, kao da su znanstveni radovi, kao da su ratni brzojavi, kao da nešto od toga ipak jest istina.
Communications of the ACM, znanstveni časopis struke, prima od njega pismo. Nije duže od jedne stranice. U njemu nema ni jedne linije koda. Ima presudu. A onda uredništvo — ne on, uredništvo, upamti to za poglavlje koje slijedi — stavi na vrh naslov koji će nadživjeti autora, časopis, pa čini se i samu potrebu za dokazima: »Considered Harmful«.
Dvije riječi. Nijedna od njih nije „goto”. A opet, cijela struka će sljedećih pedeset godina znati točno na što se odnose.
Sud je otvoren. Optuženi je jedna naredba, stavljena zvučno na optuženičku klupu, iako ona sama, siromašna, nikad nije tražila da bude simbol. Tužitelj ima pero i strpljenje matematičara. Obrana će stići — i imat će, iznenađujuće, dobre argumente. Porota si ti.
Ožujak 1968. Communications of the ACM — časopis američkog udruženja za računarstvo, otprilike ono što bi za liječnike bio ugledni medicinski žurnal, samo umjesto o cijepljenju, tu se svađalo o naredbama u kodu — donosi pismo uredniku. Ne članak, ne studija, ne recenzirano čudovište s deset koautora — pismo. Netko je sjeo, napisao nekoliko odlomaka, poslao poštom (fizičkom, s markicom) i time zapalio raspravu koja traje, ozbiljno, do danas. Ako ti to zvuči kao slaba osnova za pedeset godina svađe — dobrodošao u informatiku, gdje su najveći ratovi počeli s manje od stranice teksta.
Optuženi: naredba GOTO. Da, ona. Ta mala, bezazlena skretnica koja u kodu kaže „skoči tu, nastavi odande”, korisna kao što je korisan prečac kroz susjedovo dvorište — brže je, ali netko će jednom pregraditi ogradu i onda ti se cijela ruta srušila. Tužitelj: Dijkstra, čovjek koji je, dokazat ćemo kasnije, imao mišljenje o apsolutno svemu i nije se sramio to zapisati.
Optužba, sažeto: GOTO ne kvari program. GOTO kvari tebe. Preciznije — kvari tvoju sposobnost da o programu ikad više razmišljaš na ljudski način. Dijkstrina teza nije bila estetska („ovo je ružno”) niti stilska („ovo se tako ne radi”). Bila je epistemološka, što je velika riječ za jednostavnu stvar: tvrdio je da kad program ima previše skokova, više ne možeš u glavi izgraditi jasnu sliku *gdje se program nalazi* u bilo kojem trenutku izvršavanja. Bez GOTO-a, kaže, tok programa ide odozgo prema dolje, s preskočljivim ograncima koje možeš pratiti prstom po papiru. S GOTO-om, tok postaje graf sa strelicama koje skaču natrag, unaprijed, u stranu — i taj se graf, tvrdi Dijkstra, u praksi eksponencijalno komplicira s brojem skokova. Ne linearno. Eksponencijalno. Dodaj tri GOTO-a i dobio si ne tri nova problema, nego kombinatoriku pakla.
Sad, važna sitnica koju treba unijeti u zapisnik odmah, na početku suđenja, jer inače cijela stvar zvuči kao nešto što nije: naslov pisma nije njegov. Dijkstra je poslao tekst pod imenom »A Case against the Goto Statement«. Suho, akademski, bezopasno. Urednik koji je tada uređivao rubriku — Niklaus Wirth, kasnije otac programskog jezika Pascal — promijenio je naslov u »Go To Statement Considered Harmful«. Tri riječi koje su od pisma stvorile parolu, od parole religiju, i od religije — ironično — upravo onu vrstu dogmatskog skakanja o kojem je Dijkstra pisao, samo na razini cijele struke.
Jer nakon tog naslova nešto se prelomilo u kolektivnoj psihi programerske zajednice. »Considered Harmful« je postao žanr sam za sebe — desetljećima nakon toga svatko s mišljenjem i pristupom uredniku pisao je svoje »X Considered Harmful«, o čemu ćemo se pobrinuti kasnije, kad budemo sudili ne Dijkstri, nego imitatorima. Ali za sada, u ovoj optužnici, važno je samo jedno: GOTO je, u očima tužiteljstva, kriv za razaranje strukture mišljenja. Ne kriv za spor kod. Ne kriv za bugove same po sebi. Kriv za to da čovjek, gledajući u ekran pun skokova, prestane moći reći gdje se nalazi — a program kojeg ne razumiješ, kaže optužba, nije program. Bomba je sa zapaljenim fitiljem koja čeka svog čovjeka.
Optužnica je podnesena. Dokazi slijede — a dokazi, kao što ćeš vidjeti, nisu samo teorija jednog ljutitog Nizozemca s olovkom. Iza njega stoji cijela matematička škola koja je tvrdila da se doslovno svaki program, bez iznimke, može napisati bez ijednog GOTO-a — koristeći samo tri osnovna alata: niz naredbi jedna za drugom, odluku (»ako-onda«) i petlju (»ponavljaj dok«). Zvuči kao smjela tvrdnja. Bila je i dokazana — to je danas poznato kao Böhm-Jacopinijev teorem o strukturiranom programiranju.

Dokazi optužbe
Tužiteljstvo poziva prvi dokaz: sam kod. Ne treba ga puno tražiti, jer 1968. je gotovo svaki veći program u FORTRAN-u ili COBOL-u imao istu bolest — a to su, ako te ta dva imena ništa ne asociraju, dva od najstarijih programskih jezika, jedan skovan za znanstvene proračune, drugi za poslovne obračune, oba stara kao rokenrol. Zamisli funkciju od tristo linija u kojoj skoro svaka desetak-linija završava s GOTO 340, GOTO 15, GOTO NASTAVI_TAMO_GORE. Nema petlji kako ih danas znaš, nema if-else blokova koji se lijepo uvlače jedan u drugi — ima labela razbacanih po datoteci kao čavala u dasci, i kontrola toka koja skače lijevo-desno kao pijani biljar. Htio pratiti što se događa kad stigneš do reda 212? Sretno. Moraš u glavi držati cijelu mapu skokova, jer program ne teče — on se muva.
Ovo, kaže tužiteljstvo, nije stilska mana. Ovo je epistemološki problem — dovoljno je reći da se ne pita „je li lijepo”, nego „možemo li ikad znati je li točno”. Dijkstra u pismu ne piše da je GOTO ružan — piše da GOTO čini nemogućim da o programu ikad tvrdiš nešto pouzdano. Njegova rečenica, ona najčešće citirana i najčešće krivo shvaćena, glasi da kvaliteta programera opada obrnuto proporcionalno gustoći GOTO naredbi u njegovu kodu. Zvuči kao uvreda. I jest uvreda. Ali iza uvrede stoji tvrdnja koja se dade provjeriti: ako ne možeš nacrtati jasnu, statičku sliku kako se program kreće kroz vrijeme samo gledajući njegov tekst, ne možeš dokazati da radi ono što tvrdiš da radi. A ako ne možeš to dokazati, ne programiraš — kockaš se.
Drugi dokaz je teži i puno zanimljiviji, jer to nije mišljenje nego teorem. Böhm i Jacopini su 1966., dvije godine prije Dijkstrina pisma, matematički pokazali da se svaki program koji se može opisati dijagramom toka — svaki, bez iznimke — može preformulirati koristeći samo tri konstrukcije: sekvencu (radi ovo, pa ono), selekciju (ako je uvjet istinit, radi ovo, inače ono) i iteraciju (ponavljaj dok je uvjet istinit). Nikakav GOTO ti ne treba. Nijedan. To nije preporuka za urednije programiranje, to je dokaz da je urednije programiranje uvijek moguće — pitanje je samo hoće li se programer potruditi ili će posegnuti za skokom kao lijenim prečacem.
I tu tužiteljstvo dolazi do srži svoje optužbe: GOTO nije loš zato što je opasan alat, kao motorna pila bez zaštite. GOTO je loš zato što je nepotreban alat koji postoji samo da bi programer izbjegao razmišljanje. Böhm i Jacopini su dali oružje, a Dijkstra je povukao okidač — spojio matematičku činjenicu s moralnom presudom, i taj spoj je taj koji je čitav strukovni establišment prisilio da posluša.
Treći dokaz je Dijkstrin osobni, i najotmjeniji. Za njega program nije zanat kojim se do rezultata dolazi metodom pokušaja i pogreške, nego matematički dokaz koji se, uzgred, i izvršava na stroju. A dokaz mora biti moguće provjeriti korak po korak, statično, bez potrebe da ga u glavi simuliraš trideset puta zaredom pratећи skokove. Ako svaka petlja i svaki uvjet imaju jednu točku ulaska i jednu točku izlaska, možeš rezonirati o programu blok po blok — dokazati da je ispravan onako kako se dokazuje teorem, a ne onako kako se pipa u mraku dok se program ne prestane rušiti. To je bila njegova prava optužba: GOTO ne kvari samo kod. GOTO kvari mogućnost da o kodu razmišljaš kao matematičar, a ne kao mehaničar koji lupi po kutiji ne bi li prestala škripati.

Dokazi obrane
Obrana ustaje. I obrana, iznenađujuće, ne poriče dokaze optužbe — obrana poriče presudu koju su svi izveli iz njih. Da, GOTO može stvoriti kod koji se ne da pratiti. Nitko to ne spori. Pitanje je drugo: znači li to da GOTO treba ukinuti, ili da ga treba koristiti kao odrasla osoba? Za odgovor, obrana zove svog glavnog svjedoka, čovjeka koji je napisao knjigu o umijeću programiranja u pravom, doslovnom smislu te fraze.
Donald Knuth 1974. objavljuje rad naslovljen »Structured Programming with go to Statements«. Već sam naslov je poanta — ne »protiv«, ne »umjesto«, nego S. Knuth pročita Dijkstrino pismo, pročita histeriju koja je uslijedila, i onda učini nešto što se u ovoj sudnici rijetko viđa: umjesto da bira stranu, sjedne i pogleda konkretan kod. Stvaran kod, s brojevima performansi, s primjerima gdje strukturirana verzija programa radi identičan posao sporije i nejasnije od one sa skokom. Njegov zaključak nije da je Dijkstra u krivu. Njegov zaključak je da je vojska koja je Dijkstru citirala kao svetog oca dogme — u krivu, i da je ta vojska čitala naslov, a ne pismo.
Knuth ovdje kuje rečenicu koja će nadživjeti oboje: „predčasna optimizacija je korijen svih zla”, piše on — ali odmah dodaje, u istom dahu, ono što se uvijek ispusti kad se ta rečenica citira: da to ne znači da treba odbaciti sve prilike za optimizaciju. GOTO u kritičnoj petlji, ondje gdje svaki takt procesora broji, nije lijenost. Nije špageti. Katkad je to jedina alatka koja obavi posao bez plaćanja skrivenog poreza u obliku dodatnih usporedbi i skokova koje strukturirani ekvivalent tiho ugura unutra, samo da bi izgledao pristojno.
Ovo nije usamljen slučaj koji se može otpisati kao izuzetak koji potvrđuje pravilo. Rukovanje greškama (error handling) u C-u izgleda potpuno drukčije nego u modernim jezicima — tamo nema mehanizma zvanog exception, koji bi automatski prekinuo tok programa kad nešto pođe po zlu, ni finally bloka, koji jamči da se određeni kod pokrene i počisti za sobom bez obzira na to je li sve prošlo kako treba. U C-u toga nema; resurs koji ne oslobodiš ručno jednostavno ostaje procuriti, sve do sljedećeg restarta stroja. Upravo tamo je goto na kraj funkcije često čitljiviji od alternative, ne manje. Pitaj programera koji je pisao driver za nekakav senzor u tri ujutro je li mu draže pratiti pet ugniježđenih razina uvlake ili jedan ravan skok na cleanup. Odgovor neće biti onaj kojeg je Dijkstra očekivao 1968.
I tu obrana postavlja pitanje koje je zapravo najozbiljnije od svega izrečenog na ovom suđenju: kad se argument iz jednog konteksta — akademski dokaz korektnosti programa, matematička ljepota — pretvori u zakon za sve kontekste, tko je onda taj koji ne razmišlja? Optužba je Dijkstru optužila da je propovijedao dogmu. Obrana kontrira da dogma nikad nije bila njegova. On je pisao o dokazivosti programa, o mogućnosti da matematički garantiraš da program radi upravo ono što tvrdi da radi — uzak, precizan, plemenit cilj. Generacija koja je njegovo pismo pretvorila u religijski zakon za svaku liniju koda koju su ikad napisali — ta generacija nije čitala Dijkstru. Čitala je naslov.
Jer to je ono što se dogodi kad argument postane previše zgodan da bi se provjeravao: prestaje biti argument i postaje lozinka. Reci »goto considered harmful« na code review-u i nitko te ne pita zašto — svi kimnu, jer svi su čuli tu frazu negdje, valjda je istina, valjda postoji neki Dijkstra koji je to dokazao. Umjesto da pogledaju kod pred sobom i procijene je li ovaj konkretan skok, u ovoj konkretnoj funkciji, problem ili rješenje — oni citiraju autoritet umjesto da razmišljaju. To, tvrdi obrana, nije programiranje. To je cargo cult s formalnijim rječnikom — izraz koji dolazi od pacifičkih otočana koji su nakon Drugog svjetskog rata gradili drvene makete aerodroma i kontrolnih tornjeva, vjerujući da će, ako dovoljno vjerno kopiraju formu, avioni puni robe opet sletjeti kao za vrijeme rata. Nisu razumjeli zašto su avioni dolazili, samo su imitirali izgled. Isto to, kaže obrana, radi programer koji citira Dijkstru bez da je ikad pročitao ni jedan njegov dokaz.

Karakter svjedoka: Dijkstra kao žanr
Prije nego što porota povuče crtu ispod dokaza, sud mora upoznati svjedoka koji je sve ovo pokrenuo. Jer Edsger Dijkstra nije bio čovjek koji je jednom napisao pismo i onda otišao dalje. On je bio žanr. Cijeli je život pisao — ne kod, kod mu je bio odbojan koliko i naredba GOTO — nego EWD bilješke. Bilo ih je preko 1300, u rasponu od jedne rečenice do tridesetak stranica matematike. Neke su duge tridesetak stranica matematike. Neke su jedna rečenica koja nekoga uništi u prolazu.
I tu dolazimo do dijela suđenja gdje svjedok, umjesto da odgovara na pitanja, počne sam sebe inkriminirati — na najbolji mogući način. Dijkstra nije bio suzdržan kritičar. Bio je umjetnik uvrede. Njegova najpoznatija rečenica o BASIC-u glasi da studenti koji su prvo učili taj jezik gotovo da se ne mogu rehabilitirati kao programeri — mentalno su unakaženi, bez nade u izlječenje. Za COBOL je bio jednako milosrdan: tvrdio je da već samo njegovo predavanje sakati um, da bi ga trebalo zabraniti u obrazovanju kao potencijalno kriminalno djelo. Ne kaže da su ti jezici loše dizajnirani. Kaže da te oštećuju. To nije kritika alata, to je optužnica protiv svih koji su ga ikad koristili — uključujući i tvoju majku koja je 1979. kucala platne liste u COBOL-u, i nemaš srca to njemu ikad ispričati.
Obrana bi ovdje mogla reći: pa dobro, genija se ne sudi po manirama. I djelomično bi bila u pravu. Dijkstra je zaista vjerovao da je programiranje intelektualna disciplina najbliža matematici, da program mora biti dokaz, a ne pokušaj-pa-vidi. Ta uvjerenost ga je dovela do stvarnih otkrića — semafori (mehanizam kojim se sprječava da dva procesa istovremeno zgrabe isti resurs, poput brave na kupaonici u zajedničkom stanu — jedan unutra, ostali čekaju u redu), algoritam najkraćeg puta koji danas svaki navigacijski sustav koristi bez da ga imenuje, cijela škola strukturiranog razmišljanja o softveru. Arogancija mu nije bila mana koja je slučajno pratila genija. Bila mu je metoda. Kad je bio siguran da ima dokaz, ponašao se kao da ima dokaz — bez ublažavanja, bez diplomatskih formulacija, bez onog akademskog »možda bismo mogli razmotriti«.
Ali metoda ima i cijenu, i tužiteljstvo bi tu odmah, kao čarolijom, pokazalo prstom: ta ista sigurnost koja mu je dala pravi rezultat kod semafora, dala mu je i pogrešnu presudu kod GOTO-a — ili barem presudu grublju od onoga što je situacija tražila. Kad si ubijeđen da imaš matematički dokaz, teško ti je priznati da netko drugi možda ima praktičan slučaj koji dokaz ne pokriva. Knuth mu to nije zamjerio kao osobu; zamjerio mu je kao propust u metodi. Svjedok je vjerodostojan. Svjedok je i opasan. Oboje odjednom, i to je upravo razlog zašto ga se citira pola stoljeća poslije — ne unatoč njegovoj netaktičnosti, nego djelomično zbog nje. Tekst koji ubode, pamti se.

Presuda čitatelju
Dakle, poroto. Izvoli, presudi. GOTO je, u praktičnom smislu, mrtav — ili bar u komi iz koje ga povremeno budi neki razvojni programer jezgre (kernela) — onog dijela operacijskog sustava, recimo Linuxa, koji upravlja svime iznutra, od procesora do memorije — kad mu strukturirano izlaženje iz duboko ugniježđenih petlji počne izgledati kao mučenje. Danas se piše petlje, uvjete, funkcije, sve po Dijkstrinom receptu, i nitko se ni sekundu ne pita je li to ideologija ili zdrav razum. Pobjeda je, po tom mjerilu, potpuna. Ali ono drugo — ono zbog čega smo se uopće sjeli u ovu sudnicu — nije nestalo. Dogma je samo presvukla kostim.
Jer evo što se stvarno dogodilo: pismo od pola stranice postalo je predložak. Svako toliko, negdje na internetu, neki frustrirani programer sjedne za tastaturu s istom energijom kao Dijkstra 1968., i napiše svoj vlastiti manifest. »Goroutines Considered Harmful.« »Microservices Considered Harmful.« »Agile Considered Harmful.« Formula je uvijek ista: uzmi nešto što svi koriste, proglasi ga štetnim, budi dovoljno oštar da te citiraju, i pusti internet da se posvađa umjesto tebe. Nitko od tih ljudi nije Dijkstra. Ali svi su naučili njegov trik — ne argument, trik. Naslov koji zvuči kao presuda dobiva pročitanost koju argument nikad ne bi dobio sam.
Pa dobro, pitat ćeš — je li onda uopće bitno je li pobijedio argumentom ili stilom? Ili je to pitanje za filozofe koji nemaju deadline? Reći ću ti zašto jest bitno, iako priznajem da je pitanje malo nepravedno postavljeno: jer svaki put kad neki mladi inženjer danas pročita naslov s riječju »harmful« u njemu i odmah povjeruje, bez da provjeri dokaz, on ponavlja baš onu grešku koju je Dijkstra — čovjek koji je inzistirao da se svaka tvrdnja dokaže — prezirao najviše na svijetu. Ironija je debela kao Delphi priručnik: otac strukturiranog razmišljanja postao je otac najveće nestrukturirane navike u industriji, slijepog vjerovanja naslovu.