Asiakas kysyy: "Jos tämän toiminnon lisääminen uuteen sovellukseen veisi viikon, miksi täällä siihen tarvitaan kolme viikkoa?"
Se on erittäin hyvä kysymys.
Ja usein vastaus ei kuulu: "koska ohjelmoijat työskentelevät hitaammin".
Ongelma voi olla paljon syvemmällä - järjestelmän arkkitehtuurissa, sen riippuvuuksissa, tiedon tallennustavassa, testien puutteessa, historiallisissa päätöksissä ja vuosien varrella lisätyissä muutoksissa.
Juuri siksi ohjelmistokehityksen kustannus ei ole vakio.
Sama toiminto voi maksaa täysin eri summan kahdessa eri järjestelmässä.
Koodin hintaa ei määritetä vain toimintojen määrän perusteella
Ensisilmäyksellä tehtävä voi näyttää hyvin yksinkertaiselta.
"Lisätään mahdollisuus viedä tiedot Exceliin."
Tai: "Lisätään uusi käyttäjärooli."
Tai: "Yhdistetään järjestelmä CRM:äämme."
Ongelma on siinä, että toiminto ei koskaan ole täysin irrallaan muun järjestelmän kokonaisuudesta.
Uusi toiminnallisuus voi vaatia muutoksia:
- tietokantaan,
- API:in,
- taustajärjestelmään,
- etupäähän,
- käyttöoikeusjärjestelmään,
- lokitukseen,
- raportointiin,
- integraatioihin,
- testeihin,
- välimuistimekanismeihin,
- dokumentaatioon,
- julkaisuprosessiin.
Mitä tiiviimmin järjestelmä on kytkeytynyt, sitä useampia osia on analysoitava ennen muutosta.
Suurin kustannus voi syntyä ennen ensimmäisen koodirivin kirjoittamista
Kypsässä järjestelmässä ohjelmoijan ei pitäisi vain ryhtyä kirjoittamaan.
Ensin on vastattava:
- Minne tämä toiminto pitäisi lisätä?
- Minkä moduulien kanssa se kommunikoi?
- Mitä tietoja se käyttää?
- Peittävätkö olemassa olevat käyttöoikeusmekanismit sen?
- Vaikuttaako muutos muihin prosesseihin?
- Mitkä testit on päivitettävä?
- Antaako nykyinen arkkitehtuuri edes mahdollisuuden tehdä tämä oikein?
Kaikki tämä on osa toiminnon toteutuskustannusta.
Siksi vanhassa järjestelmässä merkittävä osa työstä voi olla itse ohjelmoinnin sijaan olemassa olevan ratkaisun riippuvuuksien ja rajoitteiden selvittämistä.
Tekninen velka toimii kuin korko
Hyvä tapa ajatella teknistä velkaa on juuri seuraavien muutosten kustannus.
Jos jokin ratkaisu tehtiin aikoinaan nopeasti, se voi olla täysin perusteltu.
Ongelma syntyy silloin, kun väliaikaisesta ratkaisusta tulee pysyvä osa järjestelmää.
Syntyy uusi toiminto.
Sitten toinen.
Ilmestyy poikkeus.
Sitten toinen poikkeus.
Lisäksi tulee integraatio, ongelman kiertotapa, manuaalinen prosessi ja ylimääräinen sääntö.
Muutaman vuoden kuluttua kukaan ei enää muista, miksi järjestelmä toimii juuri niin kuin toimii.
Mutta jokaisen uuden muutoksen on otettava huomioon kaikki nämä historialliset päätökset.
Martin Fowler kuvaa teknistä velkaa lisätyöksi, joka aiheutuu järjestelmän muutoksista sen sisäisen laadun ongelmien vuoksi.
Voisi siis sanoa: tekninen velka ei välttämättä pysäytä kehitystä heti. Ensin se tekee jokaisesta seuraavasta muutoksesta kalliimman.
Ensimmäinen merkki: "sivussa pitää korjata vielä viisi asiaa"
Tämä on yksi tyypillisimmistä oireista.
Asiakas tilaa yhden toiminnon.
Analyysin aikana käy ilmi, että sen toteuttamiseksi pitää:
- korjata taulukon rakennetta,
- muuttaa valtuutustapaa,
- päivittää kirjasto,
- korjata vanha API,
- kirjoittaa osa etupäästä uudelleen.
Yhtäkkiä pieni toiminto ei enää olekaan pieni toiminto. Ei siksi, että vaatimus olisi monimutkainen. Vaan siksi, että järjestelmällä ei enää ole asianmukaisia arkkitehtuurisia rajoja.
Toinen merkki: yksi muutos vaatii koko järjestelmän testaamista
Jos pieni muutos vaatii täydellisen manuaalisen regressiotestauksen, organisaatio maksaa automaation puutteesta.
Järjestelmän kasvaessa mahdollisten yhdistelmien määrä kasvaa.
Ilman riittävää testikokonaisuutta on yhä vaikeampaa olla varma, ettei uusi toiminto rikkonut vanhaa.
Tämä puolestaan johtaa varovaisuuteen.
Julkaisuja tehdään harvemmin.
Muutokset ovat suurempia.
Riski kasvaa.
Ja suurempia julkaisuja on vaikeampi diagnosoida ongelmien ilmetessä.
Syntyy noidankehä.
Kolmas merkki: "tuota moduulia kannattaa mieluummin olla koskematta"
Tämän lauseen pitäisi sytyttää varoitusvalo.
Jos tietystä moduulista on tullut alue, jota tiimi välttää, koska sen käyttäytyminen on ennalta-arvaamatonta, järjestelmässä on merkittävä ylläpito-ongelma.
Pahenee entisestään, jos vain yksi henkilö tuntee sen toiminnan. Silloin yrityksellä ei ole vain teknistä velkaa. Sillä on myös knowledge risk.
Yhden työntekijän lähtö voi tarkoittaa sen tiedon menettämistä, jota tarvitaan järjestelmän turvalliseen kehittämiseen.
Neljäs merkki: jokainen toiminto vaatii poikkeuksia
Hyvin suunnitellulla järjestelmällä pitäisi olla ennustettavat säännöt.
Jos jokainen seuraava toiminto vaatii erityisen poikkeuksen, ylimääräisen ehdon tai yksilöllisen polun lisäämistä, arkkitehtuuri alkaa todennäköisesti rajoittaa kehitystä.
Tämä johtaa usein koodiin, jonka käyttäytymistä ei enää voi helposti ennustaa.
Ja ennustettavuuden puute tarkoittaa suurempaa analyysin, testauksen ja ylläpidon kustannusta.
Pitääkö kaikki kirjoittaa uudelleen?
Ei.
Ja tässä pääsemme erittäin tärkeään erotteluun.
Tekninen velka ei automaattisesti tarkoita rewrite-tarvetta.
Mahdollisia ratkaisuja ovat:
Refaktorointi
Eli olemassa olevan koodin rakenteen parantaminen muuttamatta sen liiketoimintakäyttäytymistä.
Se on hyvä suunta, kun järjestelmän arkkitehtuuri on edelleen järkevä, mutta tietyt osat ovat vaikeita ylläpitää.
Valittujen komponenttien modernisointi
Koko sovellusta ei tarvitse vaihtaa.
Voi aloittaa ongelmallisimmasta moduulista, integraatiosta tai kerroksesta.
Vaiheittainen migraatio
Uudet osat voivat toimia vanhan järjestelmän rinnalla, ja seuraavat alueet siirretään vähitellen.
Tämä lähestymistapa auttaa rajoittamaan kertaluonteisen migraation riskiä. Vanhojen järjestelmien modernisointia käsittelevässä kirjallisuudessa käytetään usein juuri toiminnallisuuden asteittaista irrottamista ja järjestelmän seuraavien osien korvaamista.
Rewrite
Uuden järjestelmän rakentaminen on järkevää silloin, kun nykyinen arkkitehtuuri on niin rajoittava, ettei jatkokehittäminen enää tuota perusteltua hyötyä.
Mutta rewrite-kohdan pitäisi olla analyysistä syntyvä päätös, ei tiimin turhautumiseen perustuva reaktio.
Milloin modernisointiin ei vielä kannata investoida?
Tekninen velka ei itsessään ole syy pysäyttää kehitystä. Jokaisessa järjestelmässä on jonkin verran teknistä velkaa. Joskus sen maksaminen takaisin ei ole taloudellisesti järkevää.
Jos sovellus:
- toimii vakaasti,
- on turvallinen,
- sisältää vain vähän muutoksia,
- hoitaa prosessia, joka ei tule merkittävästi kasvamaan,
- ei aiheuta operatiivisia ongelmia,
saattaa olla järkevää jättää se nykyiseen tilaansa.
Kyse ei ole siitä, että jokaisen järjestelmän pitäisi olla teknologisesti täydellinen.
Kyse on siitä, että velan taso on tietoinen päätös.
Milloin velan kustannuksesta tulee liiketoimintaongelma?
Silloin, kun se alkaa vaikuttaa yrityksen tuloksiin.
Esimerkiksi:
Uuden ominaisuuden piti tulla markkinoille kuukaudessa, mutta siihen menee kolme.
Integraatio uuden kumppanin kanssa venyy, koska vanhan järjestelmän API ei salli uusien tietojen helppoa käsittelyä.
Tiimin avainhenkilön on osallistuttava työhön joka kerta, koska vain hän tuntee vanhan moduulin.
Jokainen suurempi käyttöönotto vaatii tuntikausien regressiotestauksen.
Kilpailija tuo uusia ominaisuuksia nopeammin markkinoille, koska hänen alustansa mahdollistaa nopeamman kokeilun.
Tässä vaiheessa technical debt lakkaa olemasta IT-osaston ongelma.
Siitä tulee liiketoimintaongelma.
Miten mitata, heikkeneekö tilanne?
Ei tarvitse luoda monimutkaista KPI-järjestelmää.
Kannattaa seurata muutamaa yksinkertaista mittaria:
Lead time - kuinka paljon aikaa kuluu muutostyön aloittamisesta sen käyttöönottoon.
Käyttöönottojen tiheys - kuinka usein tiimi voi toimittaa muutoksia turvallisesti.
Change failure rate - kuinka usein käyttöönotot aiheuttavat ongelmia.
Palautumisaika - kuinka nopeasti voidaan palata vakaaseen toimintaan häiriön jälkeen.
Ominaisuuden läpimenoaika - vaativatko vastaavat tehtävät jatkuvasti enemmän työtä.
Lisäksi kannattaa analysoida manuaalisten toimintojen määrää, testikattavuutta, riippuvuuksien ajantasaisuutta ja aikaa, joka tarvitaan uuden ohjelmoijan perehdyttämiseen projektiin.
Tällaiset tiedot auttavat näkemään, onko ongelma todella tekninen vai johtuuko se prosessista, vaatimuksista tai työn organisoinnista.
Pahin ratkaisu on "vielä yksi nopea korjaus"
Jos tiimi tietää, että arkkitehtuuri kaipaa muutoksia, mutta siirtää asiaa aina eteenpäin, järjestelmä voi ajautua noidankehään.
"Tehdään nyt workaround."
"Teemme refaktoroinnin myöhemmin."
"Toistaiseksi tämä riittää."
"Seuraavan version yhteydessä."
Ongelma on siinä, että seuraava julkaisu tuo mukanaan uusia vaatimuksia.
Ja jokainen uusi workaround kasvattaa seuraavan muutoksen kustannusta.
Siksi päätöksen teknisen velan maksamisesta takaisin pitäisi olla osa tuotekehityksen strategiaa, ei satunnainen reaktio kriisiin.
Hyvä sovellus ei ole sellainen, joka ei koskaan vanhene
Jokainen järjestelmä muuttuu.
Teknologiat muuttuvat.
Asiakkailla on uusia tarpeita.
Uusia integraatioita ilmestyy.
Yrityksen toimintatapa muuttuu.
Siksi tavoitteena ei pitäisi olla sellaisen sovelluksen luominen, jota ei koskaan tarvitsisi modernisoida. Tavoitteena pitäisi olla sellaisen arkkitehtuurin luominen, jossa modernisointi on mahdollista pysäyttämättä liiketoimintaa. Se on valtava ero.
Sillä paras järjestelmä ei ole se, joka näyttää käyttöönottohetkellä moderneimmalta. Se on järjestelmä, jonka avulla yritys voi vielä muutaman vuodenkin kuluttua reagoida nopeasti muutoksiin.
Ja jos jokainen uusi ominaisuus maksaa yhä enemmän, se ei aina tarkoita, että ominaisuus on vaikea.
Ehkä vaikeaksi on tullut jo itse järjestelmä.



