U pripremama za .debug 2025 razgovarali smo s developerima iz tvrtke Porsche eBike Performance (nekada poznate pod nazivom Greyp Bikes), koja ponovno sudjeluje na konferenciji i tamo će se predstaviti predavanjem i izlagačkim boothom. Naši sugovornici su Davor Jankolija (mobile) i Danijel Mitar (backend), koji su nam odgovorili na niz pitanja o raznim developerskim izazovima, svaki iz svojeg kuta, s kojima se svakodnevno njihovi timovi susreću.
Za početak, možete li nam reći nešto o svojem timu i projektima na kojima trenutno radite?
Davor: Naš Mobile tim trenutno broji osam ljudi, podijeljenih na iOS i Android developere. Fokusirani smo na razvoj companion aplikacije za vozače električnih bicikala. Aplikacija omogućuje korisnicima praćenje telemetrijskih podataka u realnom vremenu, kao i detaljnu analizu prethodnih vožnji. Cilj nam je vozaču pružiti osjećaj povezanosti s biciklom te omogućiti dodatnu razinu kontrole i uvida u performanse vozila.
Danijel: S druge strane, Backend tim trenutačno čini pet full-time developera, uz jednog studenta koji je trenutno na Erasmus razmjeni. Naš primarni zadatak je razvoj i održavanje cjelokupnog cloud rješenja koje stoji iza eBike sustava. Radimo na arhitekturi koja povezuje sve ključne komponente: od VCU-a (mozak bicikla), preko mobilnih i internih aplikacija, do sustava koji se koriste na proizvodnim linijama. Cloud rješenje je svojevrsna “kičma” cijelog sustava i sve što radimo usmjereno je prema tome da ono bude skalabilno, pouzdano i lako prilagodljivo.
Davor&Danijel: Iako smo organizirani kao dva odvojena tima, suradnja nam je vrlo bliska i kontinuirana. Projekte razvijamo koordinirano, s čvrstom komunikacijom i zajedničkim razumijevanjem ciljeva, što nam omogućuje bržu isporuku funkcionalnosti i bolju integraciju između softverskih komponenti sustava.
Vaši sustavi, koliko znamo, još nisu u produkciji. Kako pristupate dizajnu arhitekture s obzirom na potrebu za budućim skaliranjem?
Danijel: Točno, još smo u fazi razvoja, ali to ne znači da ne razmišljamo o skaliranju od samog početka. Kod dizajna cloud arhitekture glavni nam je fokus fleksibilnost – znamo da će se zahtjevi mijenjati i zato sustav gradimo modularno, s mogućnošću brzih prilagodbi. Budući da je cloud osnova koja povezuje sve dijelove sustava, važno nam je osigurati da skaliranje može biti i horizontalno i vertikalno – ovisno o opterećenju i potrebama u budućnosti. Koristimo moderne alate i principe kao što su event-driven arhitektura, servisna izolacija i automatizacija testiranja i deploya kako bismo mogli brzo reagirati na promjene i zadržati visoku razinu pouzdanosti.
Davor: S mobilne strane pristup je malo drugačiji – tu je ključ zadržavanje jednostavnosti. Pridržavamo se KISS principa i pazimo da izbjegnemo premature optimization. Umjesto da unaprijed gradimo kompleksna rješenja, fokusirani smo na solidne temelje, dobru arhitekturu i jasno definiran API. Sve to čini aplikaciju dugoročno održivom i lako proširivom. Skaliranje u mobilnom kontekstu često se odnosi i na rast korisničke baze, podršku za različite verzije hardvera i OS-a te održavanje performansi, što uzimamo u obzir pri svakom dizajnerskom odabiru.
Davor&Danijel: Naš je pristup razvoj skalabilnog sustava u kojem se svi dijelovi – cloud, mobilna aplikacija, hardver – mogu neovisno razvijati, testirati i nadograđivati. Iako produkcija još nije krenula, svjesno gradimo temelje koji će podržati budući rast, bilo da se radi o tisućama, desecima tisuća ili stotinama tisuća korisnika. Temelj za to je dobra komunikacija, arhitekturalna dosljednost i spremnost na iteracije.
Kako izgleda proces definiranja API-ja između backend i mobilnih timova?
Danijel: Pristupamo dizajnu API-ja prema principu API contract first, što znači da backend i mobilni tim zajedno sudjeluju u definiranju specifikacije prije nego što se krene u implementaciju. To nam omogućava da rano uočimo potencijalne nesporazume, dogovorimo formate podataka i ponašanje endpointova te osiguramo da su potrebe obje strane uvažene.
Davor: Suradnja je vrlo tijesna – često radimo kroz zajedničke sesije gdje raspravljamo o konkretnim use casevima i predviđamo kako će korisnik koristiti aplikaciju. Nakon što se API specifikacija dogovori i dokumentira, backend i mobile timovi mogu paralelno raditi na implementaciji, svaki u svom ritmu i prema vlastitim prioritetima. Iako se tada razvoj može odvijati neovisno, ostajemo u stalnoj komunikaciji i spremni smo brzo reagirati ako dođe do promjena ili novih saznanja.
Davor&Danijel: Trudimo se da backend bude uvijek barem jedan korak ispred mobilea kako bismo izbjegli potrebu za mockanjem podataka na mobilnoj strani. Također, koristimo alate za dokumentaciju API-ja kako bismo osigurali da svi članovi tima imaju točan i ažuriran uvid u dogovorene specifikacije. Na kraju, ključno nam je da API dizajn bude jasan, stabilan i jednostavan za korištenje – jer dobra API suradnja znači i bržu isporuku kvalitetnog proizvoda.
Koji su najveći izazovi u komunikaciji između timova koji rade na različitim dijelovima sustava?
Davor: Jedan od najvećih izazova je usklađivanje prioriteta. Svaki tim – bilo da se radi o mobilnom, backend, embedded ili hardverskom – ima svoje roadmapove i tehnička ograničenja. U praksi to znači da je teško sve timove sinkronizirati tako da u isto vrijeme rade na istim funkcionalnostima. Kada jedan tim kasni s nekom komponentom, to zna usporiti ostale.
Danijel: Poseban izazov dolazi iz suradnje sa segmentima koji ovise o hardveru. Za razliku od softvera, hardver ima stroži release ciklus i manje je fleksibilan za promjene u zadnji čas. Ako dođe do promjene na hardverskoj strani – primjerice u ponašanju VCU-a – to direktno utječe na backend API-je i poslovnu logiku, što posljedično može zakomplicirati i rad mobilnog tima.
Davor&Danijel: Ključ za prevladavanje tih izazova je otvorena i česta komunikacija, kao i rano uključivanje svih dionika u proces planiranja. Trudimo se raditi s jasnim specifikacijama i realnim vremenskim okvirima, ali ostavljamo prostor za promjene jer znamo da su iteracije sastavni dio razvoja. Redoviti cross-team sastanci i bliska suradnja između voditelja timova pomažu nam da ostanemo usklađeni i minimiziramo uska grla.
Možete li podijeliti neki konkretan primjer izazovne situacije?
Danijel: Jedna od kompleksnijih situacija nastala je kad se u kasnijoj fazi razvoja pojavila potreba za promjenom formata poruka koje se razmjenjuju između svih komponenti sustava – backend, mobilne aplikacije i ostalih servisa. Budući da se radi o temeljnom dijelu komunikacije unutar sustava, takva promjena nije mogla biti izvedena jednostrano, već je zahtijevala koordiniranu akciju svih timova.
Davor: Za mobilnu aplikaciju to je značilo refaktoring dijela koji parsira i prikazuje podatke, kao i prilagodbu poslovne logike. Istovremeno, trebalo je paziti da se ne uvedu breaking changes za razvojne buildove i kolege koji su radili na drugim funkcionalnostima. Složili smo privremene fallback mehanizme, paralelno podržavali stari i novi format, te pažljivo tempirali rollout.
Davor&Danijel: U toj situaciji ključno je bilo imati jasan dogovor oko koraka, dobar API contract i puno međutimenske komunikacije. Svaki tim imao je svoju ulogu u tranziciji, ali sve se moralo dogoditi usklađeno kako bismo očuvali stabilnost sustava. Takvi slučajevi testiraju tehničku disciplinu, ali i timsku koordinaciju – i dugoročno nas čine jačimai otpornijima na promjene.
Na koji način pokušavate predvidjeti probleme prije nego što se pojave u produkciji?
Danijel: Iako naši sustavi još nisu formalno u produkciji, ponašamo se kao da jesu. To znači da već sada primjenjujemo produkcijske standarde kvalitete, stabilnosti i nadzora. Svaki commit prolazi kroz statičku analizu koda i automatizirane testove, a svaki deploy se provodi s istom pažnjom kao da ide prema stvarnim korisnicima. Tako osiguravamo da eventualne greške otkrijemo što ranije u razvoju, dok je njihova cijena još niska.
Davor: Na mobilnoj strani, naši QA stručnjaci uključeni su već u fazama planiranja i dizajna. To omogućava da testiranje ne bude samo validacija funkcionalnosti, već i proaktivna potraga za potencijalnim rupama u dizajnu ili korisničkom iskustvu. Povratne informacije se vraćaju development timu odmah, što nam omogućuje brzu iteraciju. Osim toga, koristimo feature flagove kako bismo nove funkcionalnosti postupno uključivali i testirali ih u izolaciji.
Davor&Danijel: Osim automatizacije i dobrih testnih pokrivenosti, redovito provodimo reviziju arhitekture sustava te uspoređujemo stanje sustava s tehničkim i poslovnim zahtjevima. Na taj način ne tražimo samo greške, već i mjesta gdje sustav može postati krhak pod opterećenjem. Pristup “kao da smo u produkciji” pomaže nam da razvijamo s osjećajem odgovornosti i zrelošću, čak i prije nego što do prvih korisnika stvarno dođemo.
Koji su najveći problemi na koje ste dosad naišli u tom pristupu?
Danijel: Jedan od većih izazova je održavanje balansa između temeljitog testiranja i brzine razvoja. Kad se ponašate kao da ste već u produkciji, lako je upasti u zamku pretjeranog opreza, što može usporiti isporuku. S druge strane, ako forsirate brzinu, riskirate tehnički dug. Traženje te ravnoteže je stalni izazov – osobito kad imate više timova koji ovise jedni o drugima.
Davor: S mobilne strane, složenost raste kako aplikacija postaje bogatija funkcionalnostima. Upravo zato inzistiramo na čistoj arhitekturi i modularnosti. No, čak i uz najbolju namjeru, zna se dogoditi da optimizacije ili workaroundi uvedeni zbog kratkoročnih ciljeva postanu dugoročni problemi. Također, paralelni rad više developera na istim dijelovima aplikacije može otežati testiranje i integraciju.
Davor&Danijel: Još jedan izazov je upravljanje promjenama koje utječu na više timova – bilo da se radi o promjeni u API-ju, formatu podataka ili logici poslovnog procesa. Čak i uz dobru komunikaciju, nije uvijek jednostavno održati sinkronizaciju u realnom vremenu. No, te izazove rješavamo postupno – iskustvom, boljim alatima i sve jasnijim procesima. Svaka prepreka koju prođemo unaprijedi nas za sljedeći korak.
Kada pogledate unatrag, što biste u ovoj fazi razvoja napravili drugačije?
Davor: Vjerojatno bismo još odlučnije i dosljednije primjenjivali KISS princip od samog početka. Neke odluke koje su u tom trenutku djelovale “proaktivno” pokazale su se kao nepotrebno kompleksne kada su stvari krenule drugim putem. Jednostavnost u arhitekturi, jasnoća odgovornosti i fokus na ono što je stvarno potrebno – to su stvari koje uvijek isplivaju kao najbolji put, ali ih je lako zanemariti u brzini razvoja.
Danijel: Slično i kod nas – ponekad smo pokušavali predvidjeti previše scenarija unaprijed, što je vodilo prema overengineeringu. S vremenom smo shvatili da je puno vrednije graditi sustav koji se lako prilagođava promjenama nego pokušavati sve predvidjeti unaprijed. U retrospektivi, napravili bismo neke stvari jednostavnije, s više povjerenja u iterativni razvoj.
Davor&Danijel: Učenje iz ranih odluka sastavni je dio svakog kompleksnog projekta. Svaka iteracija donosi nova saznanja i uvide. Ključno je biti dovoljno otvoren i samokritičan da se te spoznaje pretoče u konkretnu promjenu u načinu rada – i tu mislim da smo s vremenom postali puno bolji.
Postoji li neki “aha” trenutak koji vam je promijenio pristup razvoju skalabilnih sustava?
Danijel: Jedan od tih “aha” trenutaka bio je kad smo shvatili da se skalabilnost ne gradi samo kroz tehnologiju, nego i kroz procese. Možete imati najmoderniji stack, ali ako timovi nisu usklađeni ili se odluke donose stihijski, sustav neće skalirati kako treba. Prava skalabilnost dolazi kroz modularnost, jasno definirane granice odgovornosti i dobre dogovore – ne samo kroz tehničke optimizacije.
Davor: S mobilne strane, spoznaja da less is more bila je presudna. Kad aplikaciju gradite s idejom da sve mora biti “enterprise-ready” od prvog dana, vrlo brzo se zakomplicira kod, UX i održavanje. U trenutku kada smo osvijestili da je najvažnije brzo i stabilno dostaviti korisnicima ono što im zaista treba – a ne sve što bi moglo zatrebati – stvari su postale puno jasnije. Od tada imamo bolju kontrolu nad razvojem i manje problema s “teškim” naslijeđem.
Davor&Danijel: Taj “aha” moment naučio nas je važnosti iterativnosti – da je puno učinkovitije krenuti s nečim jednostavnim i postupno graditi dalje, nego pokušati isporučiti savršeno rješenje iz prve. Sustavi koji mogu lako rasti i mijenjati se zapravo su oni koji su pažljivo pojednostavljeni, a ne prenatrpani ranim ambicijama.
Što biste savjetovali timovima koji tek kreću graditi ovakve sustave s ambicijom skaliranja?
Davor: Prvi savjet bio bi: ne žurite. Krenite polako, s jasnim fokusom na jednostavnost i razumijevanje problema koji rješavate. Ako pokušate sve predvidjeti i izgraditi “savršenu arhitekturu” odmah na početku, vrlo lako ćete završiti s prekompliciranim sustavom koji se teško mijenja. KISS i YAGNI (“You Aren’t Gonna Need It”) nisu samo fraze, nego principi koji dugoročno čuvaju kvalitetu i zdravlje projekta.
Danijel: Dodao bih i da je jako važno postaviti čvrste temelje – ne nužno savršene, ali dovoljno stabilne da na njima možete graditi bez straha od pucanja. Gradite fleksibilnost u sustav, ne kroz gomilu opcija, nego kroz modularnost i jasnoću granica između komponenti. I, možda najvažnije – od prvog dana gradite tim koji razumije zašto stvari radite na određeni način. Ljudi su ti koji skaliraju sustav.
Davor&Danijel: Skalabilnost nije samo tehnički izazov – to je i organizacijski i kulturološki proces. Krenite malim koracima, učite brzo, ne bojte se refaktoringa, i ne zaboravite da će najviše vrijednosti doći iz iskustava koje ne možete unaprijed predvidjeti. Ako to prihvatite, skaliranje neće biti nešto što vas plaši, nego prirodan nastavak rasta.
Na kraju, postoji li nešto (knjiga, blog, predavanje) što biste preporučili nekome tko se prvi put susreće s ovakvim izazovima? Osim, naravno, da dođu na .debug…
Davor: Teško je izdvojiti jednu knjigu ili predavanje jer kontekst jako ovisi o tome tko što traži – ali najvažnije je imati naviku stalnog učenja. Bilo da čitate blog, gledate talk ili istražujete open-source projekte, najbitnije je da aktivno tragate za znanjem i ne bojite se testirati ono što ste naučili u praksi.
Danijel: Dodao bih da je jednako važno učiti iz dobrih i loših primjera. Često najviše naučimo iz tuđih pogrešaka, pa čak i iz svojih ranijih odluka. Moguće je da će vam u nekom trenutku više koristiti jedan GitHub repo ili konkretan Slack thread, nego formalna literatura. Zato se ne fokusiramo na jedan izvor, već gradimo kulturu u kojoj znanje stalno cirkulira među članovima tima.
Davor&Danijel: Resursa ima zaista puno i ne postoji “jedan pravi” – važno je da ostanete znatiželjni, otvoreni za učenje i spremni isprobavati naučeno u praksi. Čitajte blogove, gledajte predavanja, kopajte po dokumentacijama i ne bojte se učiti iz konkretnih projekata – i vlastitih i tuđih.
A ako ste na .debugu, svakako svratite i na predavanje našeg kolege Jakova Kusića – “Kad monolit glumi mikroservis: kome tu vjerovati?“. U njemu će pokazati kako modularni monolit (modulith) može biti odličan kompromis između monolitne i mikroservisne arhitekture. Govorit će o organizaciji aplikacije u jasno odvojene module unutar jedne deployable jedinice i vlastitim iskustvima iz prakse. Vjerujemo da će to biti izuzetno korisno za svakoga tko razmišlja o skalabilnosti i održivosti softverskih sustava.
I da, ne zaboravite – najvažnije je dijeliti znanje unutar tima. Jer rast sustava uvijek počinje s rastom ljudi.