ActiveCollab 8 je primer korišćenja davilice da se softver razvija i pusti bez gubitka funkcionalnosti i pada sistema.

Krajem novembra smo pustili novu veliku verziju našeg alata za upravljanje projektima i praćenje vremena. Neke velike verzije su prekretnice, dok se nek druge nastavljaju na ove prve i dalje nadograđuju na osnovama koje su one postavile. Najnovija verzija 8 pripada ovoj prvoj grupi. Pored niza novih mogućnosti koje donosi, ActiveCollab 8 ima i kompletno prepisan frontend aplikacije.

Prepisivanje nije nešto na šta se lako odlučujemo. Joel Spolsky odluku da se softver prepisuje iz početka jednom od najgorih strateških odluka u klasiku Things you should never do, Part I. Moje iskustvo se u osnovi poklapa sa tom postavkom, ali neke stvari ne radimo zato što želimo, već zato što moramo.

U konkretnom slučaju, razlog zašto smo se odlučili da prepisujemo frontend je to što smo bili saterani u tehnički ćorskokak. Sad već davne 2014. godine, probali smo da budemo studiozni u izboru frontend stacka za ActiveCollab 5. Pogledali smo šta je dostupno, pa izbor suzili na Ember, Angular i Backbone. Probali samo sa pravljenje demo aplikacije i par primera i opredelili se za Angular. Bio je moderan, imao je sve što nam treba, a iza njega je stajao Google. Delovao je kao dobar izbor u skoro svakom pogledu.

U 2015. mi smo izbacili ActiveCollab 5 koji se pokazao kao izuzetno uspešan. Godinu dana kasnije je Google napustio originalni Angular i napravio novi, toliko različit da postojeći kod nije mogao da se prebaci, bez da se aplikacija prepisuje.

Pošto smo za pravljenje verzije 5 “nestali” na dve godine, nismo hteli taj isti poduhvat odmah da ponavljamo. Umesto da opet nestajemo i prepisujemo aplikaciju, nastavili smo da razvijamo proizvod na Angular 1.x verzijama još neko vreme, ali je bilo jasno da to nije dugoročno održivo i da ćemo pre ili kasnije morati da prepisujemo frontend.

Kao platformu za novi frontend tim je odabrao React, a proces se može podeliti u pet osnovnih faze:

  1. Ostrva novog u moru starog interfejsa,

  2. Novi sistem odvojen od starog,

  3. Stari kao defualt, uz mogućnost korišćenja novog,

  4. Novi kao default, uz oslanjanje na stari za nezavršene stvari,

  5. Novi kao potpuna zamena za stari.

Svi su zanimljivi primeri kako se stara aplikacija postupno može zameniti novom, bez da to korisnici osete kroz downtime ili nemanje mogućnosti na koje su navikli.

Idemo redom…

Promotivna ilustracija kojom je najavljivan ActiveCollab 8

Faza 1. Ostrva novog u moru starog interfejsa

Umesto da se odmah pravimo skroz nova aplikacija, dogovor je bio da se nove funkcionalnosti razvijaju kao manje React aplikacije unutar stare Angular aplikacije.

Ideja je bila da ne nestanemo na dug period prepisujući celu aplikaciju, već da je osvežavamo deo po deo. Na ovaj način su korisnici redovno dobijali unapređenja, a mi pravili osnovu za novu verziju korak po korak. Šematski prikaz iz mog opšteg članka o davilici izgleda ovako:

Šematski prikaz stare aplikacija se delovima nove aplikacije unutar nje

ActiveCollab je u ovoj fazi izgledao potpuno identično iz korisničke perspektive, dok je u pozadini postojao niz React ostrva u Angular aplikaciji, sa mehanizmimima da ta dva dela razmenjuju podatke. Na slici dole možete vide aplikaciju iz tog perioda, a ja sam naznačio delove koji su do tada bili prebačeni na React:

Screenshot ActiveCollab 7 aplikacija, sa označenim elementima koji su bili prebačeni na React

ActiveCollab 7 sa naznačenim React elementima

Kako smo razvijali nove funkcionalnosti, procenat aplikacije koje je bio Angular se smanjivao, a koji je bio React se uvećavao.

Odnos nismo gledali kroz broj fajlova, ruta ili linija koda, već kao “velike stranice koje imamo napisane”: Projects lista, My Work, Workload, lista zadataka u sva tri pogleda itd. Tako gledano, delovalo je kao da smo preradili dobar deo aplikacije, jer su to bile najčešće korišćene stranice.

Kada smo procenili da imamo dovoljno mogućnosti napravljeno pomoću Reacta da možemo da krenemo u drugu fazu, napravili smo novi projekat i krenuli dalje.

Faza 2. Nova aplikacija pored stare

Ideja druge faze je bila da napravimo novu React aplikaciju, u nju preselimo mogućnosti koje smo u staroj verziji imali napisane u Reactu i to iskoristimo kao polaznu tačku za dalji razvoj.

Ključna odlika nove aplikacije i osnova za dalje prepisivanje je bila da nova React i stara Angular aplikacija nastave da koriste isti backend, kroz isti API. Ovo je u praksi značilo da se stara i nova aplikacija mogu koristiti paralelno sa istim podacima. Bitnost ove odluke će biti jasnija u kasnijim fazama, a ovde je navodim jer je ovo bio trenutak kada je ista doneta i izvedena. Šematski prikaz odnosa nove i stare aplikacije:

U ovoj fazi smo gledali da složimo moderno okruženje za razvoj i pakovanje, automatizujemo isporuku koda i postavimo nove standarde za programiranje, sa ciljem da unapredimo iskustvo i efikasnost razvojnih timova.

Nova aplikacija je bila postavljena na novi link, a pristup je bio ograničen tako da joj se moglo prići samo sa naše mreže. Na ovaj način smo osigurali da možemo da radimo, uz stalnu isporuku (Continous Delivery, CD), a da ne rizikujemo da korisnici slučajno završe u nezavršenoj verziji softvera.

Ideja prve faze je bila da će se nove React funkcionalnosti koje smo napravili i već isporučili u okviru stare brzo i bez većih izmena prebaciti u novu aplikaciju. To nije bilo bi ni blizu toliko čisto i lako kao što smo očekivali, pa je uzelo više vremena nego što je planirano.

Problem je bio to što je React kod izvučen iz stare aplikacije imao dosta mesta gde je komunicirao sa Angular aplikacijom. To je sve trebalo posklanjati. Takođe, kako je vreme prolazilo, tako smo postajali bolju u razvoju React koda, pa su neke od prvih stvari koje su razvijane već bile zrele za modernizaciju.

Nakon što smo složili novo okruženje i u njega prebacili ono što se moglo prebaciti iz prve faze, krenuli smo u razvoj novih mogućnosti. Ovaj razvoj je tekao lakše i brže nego u prvoj fazi jer nas novo razvojno okruženje i procesi nisu sputavali kao stari sistem.

Jedini korisnici nove aplikacije u drugoj fazi smo bili mi, jer je bilo mnogo rupa u funkconalnosti. Fokusirali smo se da zaokružimo najbitnijih celina, pre svega deo za rad na projektima, kako bismo mogli što pre uvesti korisnike da probaju novi sistem.

Faza 3. Stari sistem kao default, uz mogućnost korišćenja novog

Sav modernizovan kod, sva mehanika automatskih testova i isporuke, sve unapređene performanse i mogućnosti ne vrede ništa dokle god softver nije pred korisnicima. Osnovna ideja treće faze je bila baš to, da napokon omogućimo delu korisnika da probaju novu aplikaciju i svojim komentarima usmere dalji razvoj.

 

Deo #1: Puštanje korisnicima i zajednički rad na unapređenjima

Kada smo procenili da u novoj aplikaciji postoji dovoljno mogućnosti da može biti zanimljiva korisnicima, krenuli smo u treću fazu. Cilj je bio da se nova aplikacija dovoljno zaokruži da možemo pozvati korisnike da probaju ono što je novo i unapređeno, ali ne i da im odmah nametnemo prelazak.

Prvi put kada smo to probali, bilo je prerano. Iako smo mi smatrali da imamo dovoljno materijala da pokažemo u kom smeru idemo, desetak korisnika kojima je pokazano je bilo zbunjeno. Oni su veći značaj dali stvarima koje nedostaju i pitanje: "A kad možemo da ih očekujemo?" nego onome što je bilo gotovo.

Lekcija naučena. Meni je želja bila da u toj fazi pozovemo bar pedesetak korisnika, ali već nakon deset je bilo jasno da je prerano i da nam za korisnike treba kompletnije iskustvo.

Godinu dana kasnije smo puno bolje prošli. Ideja je u suštini bila ista, ali su tehnička realizacija i način na koji smo komunicirali stvari bili puno zreliji.

Za početak, imali smo puno više gotovih mogućnosti. Umesto da mogućnosti koje nismo uradili vode na prazne stranice ili pucaju, usmerili smo ih na odgovarajuće sekcije u starom sistemu. Takođe smo dodali dijalog u staru verziju koja nudi lak ulazak u novu i mogućnost da vlasnici naloga kontrolišu ko joj može pristupiti:

Dijalog koji omogućava brz ulazak u verziju 8 iz verzije 7

Dijalog koji omogućava brz ulazak u verziju 8 iz verzije 7

Arhitektura aplikacije koju smo postavili u drugoj fazi, gde novi i stari sistem koriste iste podatke kroz isti API se nije menjala. Celo iskustvo je bilo mnogo smislenije zahvaljujući olakšanom kretanju između dve verzije. Korisnicu su kroz dijalog mogli lako pristupiti novoj verziji, a kada bi u novoj veziji kliknuli na nešto što nije gotovo sistem bi ih vratio na odgovarajuću stranicu u staroj.

Poruka koju je cela postavka slala korisnicima je bila jednostavna: stari sistem je i dalje glavni, a novi koristite kada nudi bolje alate i da biste se upoznali sa predstojećim promenama.

Iako je nama u razvoju nova verzija bila prioritet, korisnicima je bila u drugom planu. Njima su fokus bili rad na njihovim projektima, a na verziju 8 su gledali kao na nešto što bi trebalo da im olakša taj posao nekada u budućnosti. Tu su bili da prokomentarišu stvari na kojima smo radili, da prodiskutujemo i da kroz tu komunikaciju usmere dalji razvoj.

Deo #2: Pripreme za fazu 4

Kada smo procenili da imamo dovoljno spremnih stvari da akcenat prebacimo na novu verziju, krenuli smo u pripreme za četvrtu fazu, gde nova verzija preuzima volan, a stara ide na suvozačko mesto.

Jedno je nuditi novi sistem kao sidekick starom, a drugo je napraviti da je novi glavni. Prvi daje osećaj opcionalnosti, drugi je konačan, kako tehnički, tako i kroz korisničko iskustvo.

Dijagram dole pokazuje kako se korisnik kreće između dve aplikacije. Na prvom koraku, vidite verziju 8 gde crni elementi predstavljaju sekcije koje su već bile prerađene, a sive koje tek treba da napravimo:

Dijagram koji pokazuje da linkovi iz v7 ne vraćaju korisnike u v7

Kada bi korisnici kliknuli na link ka nezavršenoj sekciji, verzija 8 bi ih prebacivala u odgovarajuću sekciju verzije 7, ali bi svi budući klikovi bili u okviru te verzije. To je davalo osećaj opcionalnosti.

Četvrta faza je podrazumevala drugačiji tok:

Dijagram koji pokazuje da stara verzija prebacuje korisnika u novu za sve stvari koje u novoj postoje

Kao što vidite, ovde je verzija 7 “svesna” šta je novo dostupno u verziji 8. Svaki klik na nešto što postoji u verziji 8 bi vraćao korisnike u nju, a u verziji 7 bi mogli da koriste samo stvari koje nisu gotove.

Na ovaj način su izleti u stari sistem retki, za manje korišćene mogućnosti i kratki. Novi sistem je nedvosmisleno glavni. Korisnička perspektiva drugog toka je da smo lansirali novu verziju. Ovakva ozbiljna promena nije smela da se uradi brzopleto, već smo joj pristupili na više frontova.

Korisničku perspektivu smo stalno morali imati na umu. Za nas koji smo dugo radili na novoj verziji, prelazak sa jednog načina šetanja između verzija na drugi je bio samo jedan u dugom nizu koraka kroz koje prolazimo na putu ka novoj verziji, ali puno korisnika nije bilo dovoljno informisano o onome što predstoji. Za mnoge bi taj prelaz predstavljao "iznenadnu" promenu. Da bi se smanjio taj šok, trebalo ih je obavestiti.

Za početak, poslali smo još pozivnica i upetostručili broj ljudi u programu ranog pristupa verziji 8 (među korisnicima i nama poznat kao Early Access Program, ili EAP skraćeno). Održali smo na desetine prezentacija, beležili zanimljiva pitanja i momente gde su ljudi bili zbunjeni, komentare na stvari koje su bile preskočene ili nisu bile dobro napravljene, bagove… Sa svakom novom prezentacijom bili smo bolji u objašnjavanju novih mogućnosti, kako će tranzicija teći i kakav će uticaj imati na korisnike.

To su bila bitna učenja i iskustva, jer je trebalo utegnuti i sistem i poruku zbog konačnosti četvrte faze. Jednom kad u nju uđemo, nije bilo povratka. Lansirali smo, to je to.

Faza 4: Novi kao default, uz oslanjanje na stari za nezavršene stvar

U četvrtak, 28. novembra 2024. smo ušli u četvrtu fazu prelaska sa starog na novi sistem. Tog dana smo napravili da svi novi nalozi koriste verziju 8 kao primarnu, a u staru verziju odlaze samo da obave stvari koje još nismo završili. S druge strane, verzija 7 je vizuelno zategnuta tako da dosta liči na novu. Ovo peglanje je čak i nas često umelo da prevari tako da nismo na prvi pogled ni primećivali da smo prebačeni u staru verziju.

Verzija 8 je sada pred korisnicnica i posle par godina razvoja napokon pružamo za probu, korišćenje i kupovinu najbolji ActiveCollab koji možemo da ponudimo.

Razvoj teče dalje. Sa svakim danom i svakom iteracijom nastavljamo da unapređujemo sistem. Nekada su to potpuno nove mogućnosti, a nekada zamena za stare.

Kako vreme bude prolazilo i mi nastavimo da unapređujemo sistem, sve će biti manje razloga zbog kojih će korisnici morati da prelaze u verziju 7:

Ilustracija koja pokazuje da veći deo zahteva ide na novu verziju aplikacije

Biće tako dok jednog dana ne preradimo sve i više ne bude razloga da korisnici odlaze u staru verziju. Tada ćemo biti spremni da uđemo u petu i konačnu vazu ovog procesa.

Faza 5: Novi kao potpuna zamena za stari

Zadnja faza podrazumeva brisanje stare verzije jer su sve stvari koje je imala dostupna u novoj. Što se korisnika tiče, ova faza ih ne dotiče ni na koji praktičan način. Sve što se dešava radimo mi, u pozadini.

Davilica je u osnovi tehnički dug u koji ulazimo da bi smanjili neke druge poslovne rizike. Dug kao takav treva vratiti - izbaciti stari sistem za rutiranje, počistiti redudantne podatke, nepotrebne apstrakcije, flegove i toglove koji su omogućavali da softver radi različite stvari u različitim uslovima.

Na dijagramu ispod se vide zadnji koraci, kada nova aplikacija u potpunosti preuzme sve odgovornosti od stare i kada se na kraju ukloni kod za rutiranje:

Dijagram koji pokazuje zadnju fazu, kada se briše stara aplikacija i kod za rutiranje

U trenutku pisanja ovog članka još uvek nismo došli do ove faze. Kada u nji uđemo i kada je naposletku i završimo, dopisaću neke detalje ovde.

Zaključak

Koliko sam imao prilike da vidim u različitim člancima koji objašnjavaju davilicu, svi se slažu oko osnovnog principa, gde se stari sistem postepeno menja novim, kako bi na kraju bio ugašen kada novi može u potpunosti da preuzme. Načini na koji to možemo da postignemo su razni i zavise od tipa aplikacije, korišćenih tehnologija, poslovnih okolnosti, kao i afiniteta razvojnih timova.

U okviru rada na ActiveCollab 8, mi smo krenuli na poprilično netipičan način, gde nove funkcionalnosti razvijamo kao ostrava unutar stare aplikacije, da bi se već u sledećoj fazi prebacili na jedan od tipičnijih pristupa, sa dve aplikacije i sistemom koji rutira korisnike ispred njih.

Ono što nam je davilica konkretno omogućila je da prepišemo ceo frontend aplikacije bez unošenja nestabilnosti i narušavanja produktivnost korisnika. Nismo ih terali da iznenada uče novu aplikaciju, da prelaze na sistem koji nema sve željene mogućnosti, da rade u bagovitom i nestabilnom okruženju i slične probleme koja prate velika prepisivanja (ko je rekao Sonos?). Umesto toga smo pružili lagan prelazni period gde smo zajedno mogli da radimo na stabilizaciji i unapređenju sistema.

Ono što nismo dobili davilicom je brzina. Davilica je u svojoj osnovi tehnički dug koji uzimamo na sebe da bi imali prostora za laganiju tranziciju sa starog na novi sistem. Trebalo je složiti način na koji novi kod radi u okviru starog, pa onda te iste mehanizme izbaciti kada smo prešli u novo okruženje, trebalo je praviti kompromise i peglati podatke i API-je kako bi stara i nova aplikacija mogle da koriste isti backend bez da ugrožavaju stabilnost jedna drugoj itd. Sve je to neki dodatni posao koji se mogao preskočiti da smo kretali sa čistim sistemom. Sa druge strane, imamo iskustva i sa takvim razvojem (kada je izlazio ActiveCollab 5) i ni to nije bilo bez niza svojih izazova.

U ovom članku mi je želja bila da navedem korake kroz koje smo prolazili i razmišljanja koja su do tih koraka dovela. Na kraju dana, sama softverska kompanija i ljudi u njoj bi trebalo da procene sopstvene potrebe, prateće rizike i tržišne prilike, pa da u skladu sa istima odaberu smer u kome smatraju da treba da se kreću.