Original: https://dannorth.net/the-art-of-misdirection/
Pazi mađioničara. Gledajte kako baca novčić u ruku, zatvara ruku, pokazuje vam zatvorenu ruku, otvara je cvjetanjem i novčića nema! On se smiješi. Gledate njegovu drugu ruku. Preokrene ga i otvori ga istim cvjetanjem. Ni tamo! Zatim ti uzme ruku, zatvori je u šaku, otvori je i stane novčić!
Sad gledajte ponovo. Ovog puta pazite na drugu ruku. Dok on prebacuje gornju ruku i stisne šaku, ugledate novčić kako klizi u donju ruku u mnogo manjem pokretu. Otvori praznu ruku i pomakne donju ruku prema vrhu. Zanemarite očigledan pokret. Umjesto toga, primjetite kako vodi novčić među srednjim prstima. Zanemari kako otvara drugu ruku i umjesto toga vidiš kako opet diskretno baca novčić u prvu ruku. Konačno osjetite kako on gurne novčić u vaš dlan dok zatvara vaše prste. Magija? Možda ne. Ali klasična iluzija.
Čarolija deluje pogrešno. Mađioničar koristi vašu sklonost gledanju očitog, dok se stvarna radnja odvija drugdje. Kad se očigledno učini dovoljno uvjerljivim, teško je čak i zamisliti da potražite negdje drugdje. Ekonomisti imaju naziv za učinak samo gledanja na jednom mjestu: oni to zovu Opportunity Cost. Što god da radite trenutno dolazi po cijenu svega ostalog što biste mogli raditi umjesto toga, a tu su i druge stvari koje biste mogli raditi. Ali ne razmišljate o drugim stvarima, jer ste zauzeti koncentracijom na očigledno.
Skriveni trošak razvoja softvera
Kako se to odnosi na prakse razvoja softvera? Nova praksa obično započinje kao dobronamerni savet: „Isprobali smo ovu stvar (stand-up, par programiranje, TDD, spaljivanje ljestvica, iteracije, automatizacija izrade) i to nam je dobro uspelo. Možda biste i vi trebali probati!”
Prerano je u prilogu dnevni red: „Pokušali smo to i mislimo da možemo zaraditi novac pokazujući ljudima kako to da rade. Trebali biste ga koristiti jer djeluje! Evo bijelog papira za to.”
Usput, ako pročitate taj spisak praksi i mislite „ali to su sve dobre stvari za napraviti“, razgovaram s vama. Gdje ne radi tehnika? Što biste drugo mogli raditi? Koji su kompromisi u odabiru ove alternative?
Posljednjih nekoliko godina radio sam s timovima koji su bili produktivniji od svega što sam vidio prije. Njihove metode su bile kombinacija „tradicionalnih“ agilnih tehnika i ludih, kontraintuitivnih praksi koje su mi zadale kulturološki šok. Morao sam naučiti gomilu primljene mudrosti pre nego što sam uspeo da počnem da razmišljam onako kako su to učinili.
Pokušajte s ovom dvodijelnom vježbom: Razmislite o praksi ili tehnici koju koristite prilikom razvoja softvera, možda i vaša omiljena vježba. Razumeo? Ok, 1. dio: zašto to radite? Kakve koristi vam donosi? Vjerovatno možete pomisliti na nekoliko. Zapiši ih. Sada, drugi deo: gde ga ne biste koristili i koje su neke alternative? Zapišite neke prednosti i nedostatke svakog od njih. Sačekaću
Verovatno ćete smatrati da je taj drugi deo mnogo teži. Ako ste uglavnom izmislili negativne ili ironične razloge za alternative, samo navodite više razloga za korištenje izvorne prakse. Ne možete da prođete preko alternative. Prevarili ste se!
TDD pod reflektorom
Kao primjer ću odabrati TDD jer je to jedna od najgorički zagovaranih praksi sa kojom sam se susreo, ali ovaj pristup možete primijeniti na bilo što. Mi ćemo pogledati TDD – stvarno ga pogledajte – i možemo li otkriti gdje sjaji i gdje nije toliko korisno.
Ako ste TDDer, razmislite o tome gdje to ne biste koristili i šta biste umjesto toga mogli učiniti. Nedavno sam vidio nekoliko ljudi koji ovo pitaju kao retorički ili čak ironični izazov, kao da biste bili ljuti kad biste ikad pomislili da ne koristite TDD.
Zagovornici TDD-a kažu da stvari poput „TDD omogućava stalne, sigurne promene“. To se često događa. „TDD omogućava novi dizajn.“ Možda. „Automatizirani testovi djeluju kao regresijski paket i sprečavaju vam ponovno unošenje grešaka.“ To se često događa. “Testovi djeluju kao živa dokumentacija.” “Softver vođen testom je čistiji i lakši za promenu od softvera koji nije testiran.” Zapravo ću se pobrinuti za ovaj. Video sam šokantne baze TDD-a i čiste i pogodne baze podataka bez automatiziranih testova.
Pogledajmo prigodni trošak – kompromise – u svakoj od ovih tvrdnji. Svaki bi mogao biti članak sam po sebi. Samo vam želim pružiti osjećaj da pronađete kompromise svojstvene zvučnim zalogajima poput ovih.
Oportunitetni trošak stalnih, sigurnih promjena
Šta ne želite voljeti u stalnim, sigurnim promjenama? Pa ponekad možete opisati problem, ali ne možete vidjeti očit odgovor. Aplikacije za financijsko trgovanje mnogo su slične: možete isprobati nekoliko pristupa i vidjeti kako oni rade, poput niza eksperimenata. Želite da svaki eksperiment bude jeftin, tako da možete isprobati nekoliko. TDDing će svaka opcija djelovati, svakako, ali bit će skuplje od skiciranja nečega ako se vidi da li se osjeća dobro.
Koliki su oportunitetni troškovi za sve to dodatno vrijeme provedeno na TDDing skice? Možete skicirati šest desetina ideja u vremenu koje je potrebno da TDD bilo koja od njih. I tu se ne završava. Rezultat jednog pokušaja može promijeniti vaše razumijevanje problema koliko nudi potencijalno rješenje, koje vas šalje u novom, neočekivanom smjeru. Neki zagovornici TDD-a reći će da je ovo niz uboda i ne morate ih TDD-a. Međutim, govorim o potpunom stavljanju softvera u proizvodnju i održavanju uspješnih eksperimenata kao proizvodnog softvera, tako da to zaista i ne vrijedi.
TDD zaključava u vašoj pretpostavci o željenom krajnjem cilju. Pretpostavlja se da znate odakle krećete ili barem odakle krećete. Ako ne znate kako rješenje uopće izgleda, ovo bi mogla biti nepoželjna strategija. Možda biste trebali odgoditi ulaganje u rješenje dok ne saznate više o problemu.
Oportunitetni trošak novog dizajna
Ponekad vas pravi dizajn ne gleda u lice. Bilo bi potrebno pomicanje perspektive, preispitivanje cijele premise, da se jednostavnost vidi kroz prividnu složenost. TDD govori o inkrementalnim promjenama i poboljšanju. Izvrsno je za pronalaženje lokalnih maksima, ali najbolje rješenje bi moglo zahtijevati radikalno promišljanje. Oportunitetni trošak u ovom slučaju je da budemo zarobljeni u ovom lokalnom maksimumu i propustimo veću pobjedu. U vitkom smislu, ovo je razlika između kaizen-a, stalnog poboljšanja i kaikaku-a, nagle transformacije. Niti jedno ne može uspjeti bez drugog, ali skloni smo fokusiranju samo na kaizen kao oblik optimizacije.
TDD je epitet kaizenskog programiranja. Da bi zablistao potrebno mu je okruženje u kojem se možete koraknuti, otići na mentalnu šetnju blokom, vratiti se i možda sve promijeniti. Potrebna vam je sveobuhvatna vizija, dizajn ili arhitektura velike slike. TDD vam to neće dati. Međutim, snažna provedba složenog ponašanja će imati koristi od inkrementalnog pristupa koji pruža TDD. Primijetit ćete da ne predlažem da ne upotrebljavam TDD, ali kvalificiram gdje i na koji način je to učinkovito.
Ne pišete softver jer želite softver, pišete softver da biste mu pružili mogućnost. Na nekoliko nedavnih aplikacija stigli smo do točke kada smo ponovo napisali sistem da bismo dodali novu mogućnost. Zvuči nepristojno, nebitno rasipno, ali ono što smo naučili doći do mjesta gdje su nam rekli da bi bilo efikasnije prepisati – često drugom tehnologijom – podskup aplikacije koja sadrži pravu vrijednost. Jedan sistem započeo je u Scali i prešao je, na komade, na Javu (sigurno u pogrešnom smjeru!). Još jedan je započeo u Python-u i prešao je na JavaScript i node.js. Još jedan je započeo u Pythonu i prepisan je u drugu aplikaciju Python! Svako prepisivanje je rezultat dobivanja softvera pred ljudima, radnicima kao i korisnicima i odgovaranja na njihove povratne informacije. U tom kontekstu nije bilo važno koliko je originalni kod kreiran ili testiran jer smo ga odbacili.
Nismo pretjerano uložili u softver okružujući ga sveobuhvatnim automatiziranim testovima, inače bi to bila skupa vježba. Ali šta je s softverom koji je preživio? Otkrili smo da je moguće proizvesti nivoe TDD kvaliteta nakon toga. Znamo kako izgleda dobro utemeljen softver i do ove faze smo znali da smo spremni uložiti u ovaj softver: on je dokazao svoju vrijednost. Počeli smo uvođenjem TDD stilu testova za složenije ili kritičnih dijelova koda, što nas je dovelo do refactor da bi ga više testirati, koji je stvorio prirodne šavovima i podsistema u kodu, što dovodi do veće refaktorisanih, i tako dalje. Ja sam opisuje ovu tehniku kao Šiljak i stabilizirati: dobiti nešto, bilo šta, u proizvodnju da traže brze povratne informacije, i ulagati u bilo kojem opstaje.
Oportunitetni trošak automatiziranih testova
Automatizirani testovi daju sigurnost da kôd radi ono što bi trebao. Ovo sugerira dva pitanja: Postoje li drugi načini za postizanje tog uvjerenja? A je li jamstvo uopće vrijedno?
Automatizirani testovi su dobri u vježbanju određenih dijelova koda. Da li biste uočili greške u tom kodu bez testova? Ne možete pomoći da ne primijetite nedostajuće ili nepovezano dugme za slanje. Ako aplikacija propadne na pola puta putem dohvaćanja podataka, što bi trebala učiniti? Jednom kada ste to kodirali da li će to prestati raditi? Hoće li vam automatizirani test dati još više sigurnosti? Šta biste mogli učiniti umjesto toga?
Vrijednost automatiziranog testa je funkcija brojnih stvari: kritičnost koda, utjecaj lošeg događaja, trošak ispravljanja loše stvari, koja može biti ugledna i operativna, vjerojatnost da ćete to učiniti ne primećujući ga redovnim korišćenjem u razvoju, vaše poznavanje domene. Kôd na ivicama sistema često je teže testirati od unutarnjeg koda. UI widgeti, vanjske integracijske točke, usluge trećih strana, automatiziranje mogu biti skupe. Da li trošak opravdava vrijednost? Opet ne kažem da to ne radim, već da dovodim u pitanje kompromise i odlučujem gdje ima smisla. Vidio sam kako timovi spašavaju razvojne napore stvarajući prekrasne automatizirane testne skupove koji gotovo da i nisu dobili dodatno jamstvo ili povratne informacije o korištenju aplikacije. Tamošnji ugledni troškovi su visoki: gube vjerodostojnost kod svojih dionika, koji bi radije vidjeli da im se značajke isporučuju. Opet trebate uspostaviti ravnotežu, shvaćajući gdje je automatizacija korisna, a gdje navika.
Oportunitetni troškovi testova kao žive dokumentacije
Postoji mnogo vrsta dokumentacije. Vrijedna dokumentacija vas educira. To vam govori stvari koje inače ne biste znali jer nisu očigledne. Želite znati šta ovaj sistem razlikuje od svih ostalih sličnih sistema koje ste vidjeli. (Takođe možete postavljati pitanje zašto dokumentirate ove prepirke, umjesto da ih eliminirate iz sistema i smanjite nivo iznenađenja za novopridošlog novaca, ali to je druga priča.)
Neki automatizirani testovi čitaju više poput povijesnih dokumenata, pružajući uvid u prošlost vremena. Možda se u jednom trenutku dogodila glupa buba gdje je osvježavanjem trenutnog statusa otpuštena adresa e-pošte do povratak officea. Oni primećen je odmah, naravno, tako da programeri napisao test pod nazivom “ne bi trebalo da pošalje e-mail na back office kada osvježavajuće trenutni status”. Šta? Naravno da ne bi trebalo. Ali, s vremenom smo akumulirane mnoge od tih “Naravno da ne” testova, čime se povećava buka među signal, tako da postaje teže pronaći zaista korisne stambene dokumentaciju. Živim nije sinonim za koristan. Kuratorstvu žive dokumentacija – automatizirani testovi – je jednako važno aktivnost kao kustos bilo koje druge vrste dokumentacije. Prečesto ga je zanemarena.
Zaključak
Iako sam se u ovom članku fokusirao na TDD, postoji značaj u prepoznavanju oportunitetnih troškova i kompromisa u svim vašim postupcima i aktivnostima. Na TDD vidim kao vrijednu i važnu razvojnu tehniku, ali postoje konteksti u kojima on svijetli i drugi u kojima ga ometa. Dakle, nemojte uzimati ništa po nominalnoj vrijednosti, a umjesto toga potražite kompromise u svakoj odluci koju donesete, jer su takvi kompromisi tu bilo da ih vidite ili ne. A ako možete naučiti da ih uočite možete napraviti magiju.
Povijest: Ovaj članak je prvi put objavljen u Developer časopisu izdanje broj 2/2012, a dostupan je kao pdf download.