Working Effectively with Legacy Code

Evo jedan članak u duhu knjige koju upravo čitam: Working Effectively with Legacy Code. Misija je izmeniti klasu koja pravi izveštaje na osnovu praćenog vremena i troškova u activeCollab 3 tako da podržava više valuta.

Wewlc

Podrška za više valuta je dodata u međuvremenu i sistem za izveštavanje je nije svestan, tako da trenutno meša babe i žabe (troškove napravljene u Eurima tretira isto kao i troškove napravljene u dinarima i dolarima i samo ih sabira).

Problem je što trenutno ne postoje apsolutno nikakvi testovi za klasu za izveštavnje, pa:

  1. Nisam siguran da li klasa radi kako treba bez ikakvih izmena. Malo sam se igrao i sve deluje OK, ali nisam baš 100% siguran da sam pokrio sve slučajeve.
  2. Ukoliko krenem sada da prepravljam kod, nisam siguran da li će novi kod raditi kako treba bez mnogo ručnog njakanja izveštaja sa znanim podacima. Može to da radi neko drugi umesto mene (QA), ali bi se time krug između izmene i testiranja produžio na sate u najboljem slučaju (dane realno) što je previše sporo i troši vreme dve osobe umesto jedne.

Izveštavanje podržava prikaz individualnih zapisa ili sumiranih podataka, plus četiri načina grupisanja u oba slučaja, tako da baš treba vremena za ručnu pripremu podataka i testiranje. Iz tog razloga, prvi korak je napisati automatizovan test koji će nam potvrditi da kod radi ono za šta je originalno napisan da radi:

Test tracking reports

Pošto koristim activeCollab Timer da pratim vreme, znam koliko mi je vremena bilo potrebno da postavim testove: 1 sat i 15 minuta efektivno. Uzimajući da iz svog dana retko kada uspem da izvučem više od 3 sata efektivno programiranja, to stvarno deluje kao jako mnogo vremena za posao koji tehnički ni na koji način nije unapredio proizvod: ni jedna nova mogućnost nije dodata, ni jedna stranica nije ubrzana, ni jedna labela u sistemu nije prepravljena da bude jasnija…

Međutim, ono što je to uloženo vreme donelo je postavljanje sigurnosne mreže za sve današnje i buduće izmene koje će se desiti toj klasi. Pa krećemo…

Prvo što sam uradio je refaktorisao metod koji barata sumiranim izveštajima. U momentu kada je pisan, delovalo je da će prost switch raditi posao, ali je metod vremenom prerastao 300 redova koda. Kada sam ga rastavio i ponovo sastavio tako da koristi više pravilno imenovanih metoda, poterao sam ranije napisane testove da vidim da nisam nešto u međuvremenu pokvario. 10 sekundi kasnije testovi su mi rekli da klasa radi na identičan način kao i ranije, iako je sada osetno jednostavnija za čitanje i ispravke. Lepo!

Nakon refaktorisanja ide i onaj deo zbog čega je cela priča i počela: dodavanje mogućnosti izveštaja da sumiraju podatke kada je u sistemu definisano više valuta. Pre nego što se bacim na prepravljanje koda same klase, prvo treba da se napiše test koji proverava naša nova očekivanja. Naravno, pošto je ovo urađeno pre nego što smo stvarno i dirali kod, test neće proći:

Test tracking reports 2

Možda zvuči malo glupo pisati test pre koda, ali to je cela poenta iza Test-Drive Development pristupa. Pisanjem testa pre pisanja koda imamo priliku da lepo ispišemo očekivanja i uočimo neke rane problem u dizajnu.

Ovo je zanimljiv momenat. Ranije bih počeo ovde, međutim u ovom konkretnom slučaju iza sebe već ima dva sata efektivnog programiranja, a kao rezultat tu su sistem kojim mogu oceniti da li izmene koje budem napravio rade kako treba, plus je sam rad sa klasom jednostavniji jer sam neke komplikovane delove refaktorisao.

Idemo lagano - sada treba da izmeniti klasu da zadovoljili nova očekivanja. Uz izmenu klase i test se možda promeni na nekim mestima koja bih još dodatno da pokrijem, a koja sam prevideo kada sam ga pisao. Kada je sve gotovo, dobijemo lep rezultat:

Test tracking reports 3

activeCollab Timer kaže: 45 minuta za novu funkcionalnost, plus 2 sata ranije za pisanje testova i refaktorisanje.

Ovakav pristup programiranju je investicija u kvalitet softvera koji će biti poslat klijentima (najskuplji je bug koji korisnik nađe), kao i u budući razvoj. Modifikovanje bilo koje klase je osetno jednostavnije ukoliko već postoji test za nju, tako da će razvoj postajati lakši ako se sistematski prolazi kroz postojeći kod i pišu testovi za njega, iako sama aplikacija u međevremenu raste i postaje komplikovanija.

I za kraj, proces, ukratko:

  1. Postavimo testove koji proveravaju da li postojeći kod radi na očekivani način;
  2. U svakom kodu uvek ima nešto da se refaktoriše, tako da uzmemo lepo pa prepravimo par stvari, kako bi kod bio čitkiji, a buduće izmene lakše;
  3. Prepravimo testove tako da proveravaju naša nova očekivanja i poteramo ga iako znamo da neće proći. Korisno je videti tačke u kodu na kojima nova očekivanja nisu ispunjena;
  4. Prepravimo klasu tako da zadovoljava nova očekivanja;
  5. Otvorimo jedno 'ladno jer smo sebi i kolegama upravo uštedeli sate posla u budućnosti, a korisnicima napravili kvalitetnije rešenje koje će manje pucati i za koje ćemo lakše i brže objavljivati unapređenja i ispravke.