Ohjelmistojen elinkaarten aikana tulee usein vastaan tilanteita, joissa järjestelmiä  on tarpeen uudistaa. Tässä blogissa tarkastelen kolmea lähestymistapaa: päivitystä, refaktorointia ja uudelleenkirjoitusta. Käyn läpi, missä tilanteessa kukin lähestymistapa on sopivin ja miten oikea tasapaino löytyy. Lisäksi esittelen AI-pohjaisten apuvälineiden käyttöä osana prosessia.

Käytännössä kaikkien ohjelmistojen elinkaariin tulee epäjatkuvuuskohtia, joiden taustalla on useita tekijöitä:

  • Muuttuneet liiketoimintatarpeet
  • Liian suuret ylläpito- ja käyttökustannukset
  • Puutteellinen suorituskyky
  • Vanhentunut teknologia
  • Riittämätön skaalautuvuus
  • Turvallisuushaasteet

Kaikki nämä (ja monet muutkin) seikat voivat vaatia muutoksia aiemmin hyvin palvelleeseen ohjelmistoon. Tilanteesta riippuen epäjatkuvuuden voi hoitaa periaatteessa kolmella tavalla:

  • Sovelluksen voi päivittää liiketoiminnan tarpeiden muuttuessa
  • Joskus koodi on tarpeen refaktoroida sen suorituskyvyn, ylläpidettävyyden ja laajennettavuuden parantamiseksi
  • Ja silloin tällöin koodi kannattaa (tai se on pakko) kirjoittaa uusiksi, tyypillisesti joko merkittävien teknologisten muutosten tai suurten liiketoimintamuutosten takia

Tuote- ja tuotekehitysjohdon ikuinen haaste on tunnistaa se, mikä on paras tapa hoitaa erilaisia epäjatkuvuustilanteita.

Seuraavaksi tarkastelen tarkemmin näitä kolmea vaihtoehtoa ja analysoin mikä lähestymistapa on milloinkin sopivin ja miten löydetään oikea tasapaino. Lisäksi pohdin myös AI-pohjaisten apuvälineiden käyttöä osana prosessia.

Ohjelmistokehitys sosio-teknisenä systeeminä ja koodin luomisen kolme tasoa

Perinteisesti ohjelmistoja on tarkasteltu teknisinä artefakteina, jotka koostuvat koodista, algoritmeista ja tietokannoista. Viime aikoina on kuitenkin kasvanut ymmärrys siitä, että ohjelmistokehitys on paljon monimutkaisempaa ja sitä tulisi tarkastella sosio-teknisinä systeeminä.

Sosio-tekninen näkökulma korostaa vuorovaikutusta teknologian ja ihmisten välillä. Se tunnustaa, että ohjelmistot on suunniteltu, kehitetty ja käytetty sosiaalisissa konteksteissa, ja ne vaikuttavat ihmisten käyttäytymiseen ja yhteiskuntaan.

Kun ohjelmistoa tarkastelee sosio-teknisenä systeeminä, sen luomisen voi jakaa kolmeen tasoon:

Koodi: mitä koodataan ja miten koodataan

Työkalut: mitä työkaluja ja prosesseja koodaamisessa käytetään.

Sosiologinen konteksti: minkälainen on toimintaympäristö ja kuinka vapaat kädet tuotekehitys saa – esimerkiksi riippumattoman arkkitehtuurin (loosely coupled architecture) luominen ympäristössä, jossa on totuttu luomaan vahvasti kytkettyjä arkkitehtuureja, on haastavaa.

Sosiologinen konteksti heijastelee myös yrityksen johtamiskulttuuria: yksityiskohtaisen johtamisen (management) ja johtajuuden (leadership) välillä on oltava oikea tasapaino, jotta toimintaympäristö sallii riittävän vapauden mutta organisaatio myös tukee käytännön tekemistä tarpeeksi.

Koodin päivittäminen: toiminnallisuuden parantaminen pienemmillä muutoksilla

Jos ohjelmiston arkkitehtuuri ja suorituskyky ovat kunnossa ja on tarpeen vain lisätä tai muuttaa joitain ominaisuuksia, ohjelmiston päivittäminen on tyypillisesti edullisin vaihtoehto. Koodiin tehdään muutoksia tai siihen lisätään jotain esim. uusi moduli. Jos ohjelmisto on alunperin hyvin suunniteltu, myös pienet käyttöliittymämuutokset voi tehdä näin.

Koodin päivittämisen hyvä puoli on se, että kehittäjät todennäköisesti tuntevat koodipohjan ja arkkitehtuurin ja muutosten tekeminen on heille helppoa ja vaivatonta.

Haaste voi olla koodiin kertynyt tekninen velka, jota päivittäminen harvoin korjaa. Päivitykset ja muutokset päinvastoin pyrkivät kasvattamaan teknistä velkaa ja jossain vaiheessa sen määrä kasvaa haittaavaksi tai jopa sietämättömäksi.

Koodin refaktorointi: ylläpidettävyyden parantaminen rakennetta muuttamalla

Koodin refaktorointi on pientä koodin muokkaamista suurempi remontti. Puhdas refaktorointi on koodin järjestelmällistä uudelleenrakentamista muuttamatta sen ulkoista toimintaa – mutta yritykset toimivat harvoin näin “puhdasoppisesti”, vaan refaktoroinnin ohessa tai sen jälkeen usein tehdään myös toiminnallisia muutoksia.

Refaktoroinnin ensisijainen tavoite on parantaa koodipohjan laatua, luettavuutta, ylläpidettävyyttä ja tehokkuutta. Toisin kuin uusien ominaisuuksien lisääminen tai virheiden korjaaminen, refaktorointi keskittyy koodin sisäisen rakenteen muokkaamiseen ja puuttuu suunnitteluun, organisaatioon ja selkeyteen liittyviin ongelmiin.

Hyvällä refaktoroinnilla voidaan saavuttaa useita etuja:

  • Ylläpidettävyys: Koodin uudelleenkirjoittaminen helpottaa ylläpitoa, mikä vähentää tulevien päivitysten tai virheenkorjausten viemää aikaa ja vaivaa.
  • Luettavuus: Koodin rakenteen parantaminen ja vakiintuneiden koodaustapojen noudattaminen refaktoroinnin avulla parantaa koodin luettavuutta. Seurauksena yhteistyö kehittäjien kesken sujuvoituu ja uusien tiimin jäsenten oppimiskäyrä lyhenee.
  • Teknisen velan pieneneminen: Teknisen velan hallinta on refaktoroinnin keskeinen tavoite. Säännöllinen refaktorointi estää teknistä velkaa paisumasta hallitsemattomaksi ja takaa kestävämmän koodipohjan.
  • Virheiden ehkäisy: Koodin hajujen ja rakenteellisten ongelmien käsittely refaktoroinnin aikana auttaa ehkäisemään potentiaalisia virheitä ja parantamaan koodin yleistä laatua.

Koodin refaktorointia kannattaa harkita ainakin seuraavissa tilanteissa:

  • Vaatimusten laajentuminen: Kun projektin vaatimukset kasvavat tai muuttuvat, refaktorointi mahdollistaa uusien ominaisuuksien saumattoman integroinnin heikentämättä koodin laatua.
  • Jatkuva parantaminen: Jatkuvan parantamisen mentaliteetin omaksuminen kannustaa säännölliseen refaktorointiin, jotta koodipohja pysyy terveenä ja mukautettavana.
  • Yhteiskehitys: Tiimityöskentelyssä refaktoroinnista tulee olennainen työkalu puhtaan ja yhtenäisen koodipohjan ylläpitämiseksi ja tiimityöskentelyn edistämiseksi.

Koodin uudelleenkirjoitus: uusi koodipohja tehokkuuden ja toiminnallisuuden parantamiseksi

Koodin uudelleenkirjoituksessa koodi kirjoitetaan kirjaimellisesti uudestaan; usein silloin käytetään modernimpeja tekniikoita ja työkaluja. Hyvin tyypillisesti vanhan ohjelmiston uudelleenkirjoituksessa siirrytään käyttämään ketteriä menetelmiä ja sovelletaan CI/CD-työkaluja ja -putkia.

Koodin uudelleenkirjoittamiselle voi olla useita syitä:

Vanhentunut teknologia: Jos koodi on kirjoitettu vanhentuneella teknologialla, joka ei enää tue nykyisiä tarpeita tai vaatimuksia, uudelleenkirjoitus voi olla välttämätöntä.

Huono suunnittelu: Jos koodi on erittäin huonosti suunniteltu ja vaikeasti ylläpidettävä, uudelleenkirjoitus voi tarjota mahdollisuuden rakentaa parempi ja tehokkaampi järjestelmä.

Suorituskyvyn parantaminen: Jos koodin suorituskyky on riittämätön, uudelleenkirjoitus modernilla teknologialla voi tarjota merkittäviä parannuksia.

Siirtyminen pilveen: Jos yritys haluaa siirtää vanhan sovelluksen pilvialustalle, se on usein tarpeen kirjoittaa uudelleen nykyaikaisia arkkitehtuureja ja teknologioita hyödyntäen. Usein tällaisissa tilanteissa siirrytään esimerkiksi monoliittisistä arkkitehtuureita mikropalveluihin.

Koodin uudelleenkirjoittaminen ei ole kuitenkaan ongelmatonta. Potentiaalisia sudenkuoppia on runsaasti:

  • Korkeammat kustannukset: Uuden koodin kehittäminen voi olla kallista ja vaatia merkittäviä resursseja.
  • Riski epäonnistumiseen: Uudelleenkirjoitusprojekti voi olla riskialtis ja johtaa epäonnistumiseen, jos sitä ei suunnitella ja toteuteta huolellisesti.
  • Yhteensopivuusongelmat: Uudelleenkirjoitetun järjestelmän integrointi muihin olemassa oleviin järjestelmiin voi olla haastavaa.
  • Projektin kesto: uudelleenkirjoittaminen voi viedä pitkään.

Päätöksen tekeminen: Refaktorointi vs. uudelleenkirjoitus

Päätös siitä, päivitetäänkö refaktoroidaanko vai kirjoitetaanko koodi uudelleen, riippuu useista tekijöistä, kuten koodin tilasta, projektin vaatimuksista ja käytettävissä olevista resursseista.

Alla on jotain kysymyksiä, joita kannattaa pohtia päätöstä tehdessä:

  • Onko koodi ylläpidettävää ja ymmärrettävää?
  • Voiko koodin laatua parantaa refaktoroinnilla?
  • Vaaditaanko koodiin merkittäviä muutoksia?
  • Onko käytettävissä riittävästi resursseja uudelleenkirjoitukseen?
  • Mitä ovat uudelleenkirjoituksen mahdolliset riskit ja hyödyt?

Huolellinen suunnittelu ja analyysi ovat avainasemassa oikean päätöksen tekemisessä. On tärkeää punnita eri vaihtoehtojen etuja ja haittoja ja valita lähestymistapa, joka parhaiten vastaa yrityksen ja projektin tarpeita. Lisäksi tulee huomioida yrityksen tuotekehityksen maturiteetti ja kyvykkyys erilaisiin malleihin viedä projekti läpi.

AI-työkalut refaktoroinnin ja uudelleenkirjoittamisen apuna

Tekoäly (AI) on tuonut suuria muutoksia ohjelmistokehitykseen, ja se tarjoaa lukuisia etuja sovelluksen uudistamisessa riippumatta valitusta lähestymistavasta. Lisäksi AI-työkalut auttavat koodikannan analysoinnissa ja lähestymistavan valinnassa. Seuraavassa on jotain AI-teknologioiden tarjoamia hyötyjä:

  • Koodin “hajujen” tunnistaminen: AI-algoritmit voivat analysoida koodia ja löytää tehottomuuksia, huonoja käytäntöjä ja suunnittelumalleja, joita tulisi parantaa. Tämä auttaa kehittäjiä kohdistamaan refaktorointi- ja uudelleenkirjoitusponnistelujaan kriittisimmille alueille.
  • Automaattisten refaktorointiehdotusten tarjoaminen: AI-työkalut voivat ehdottaa refaktorointeja, jotka parantavat koodin laatua ja ylläpidettävyyttä. Nämä ehdotukset voivat vaihdella yksinkertaisista muutoksista, kuten muuttujien nimeämisestä uudelleen, toimintojen jakamisesta tai luokkarakenteiden uudistamisesta, monimutkaisempiin muutoksiin, kuten koodin uudelleenjärjestelyyn tehokkuuden parantamiseksi.
  • Koodin uudelleenkirjoittaminen: Generatiiviset AI-mallit voivat tuottaa uutta koodia tai jopa kokonaisia moduuleja, mikä voi nopeuttaa uudelleenkirjoitusta ja auttaa kehittäjiä luomaan modernimman ja tehokkaamman koodin.
  • Testauksen automatisointi: AI:ta voidaan käyttää testauskehysten luomiseen ja kattavien testitapausten automatisointiin. Tämä varmistaa, että refaktoroidun tai uudelleenkirjoitetun koodin laatu ja toiminnallisuus pysyvät korkeina. Testitapausten luominen on raskas ja kallis prosessi (ja ylläpitäminenkin on kallista), mutta AI:n avulla prosessi muuttuu tehokkaamaksi ja kannattavammaksi.

AI-työkalut voivat olla tehokas työkalu koodipohjan uudistamisen ja uudelleenkirjoittamisen tehostamiseen ja koodin laadun parantamiseen sekä kustannusten vähentämiseen. Käyttäessään näitä työkaluja tehokkaasti kehittäjät voivat säästää aikaa ja vaivaa ja varmistaa, että heidän koodinsa on ylläpidettävää, luettavaa ja skaalautuvaa.

On kuitenkin tärkeää muistaa, että AI-työkalut ovat vain apuvälineitä. Kehittäjien on aina tarkistettava AI:n tuottama koodi huolellisesti ja varmistettava, että se vastaa projektin vaatimuksia ja tavoitteita. Lisäksi AI-työkalut eivät aina pysty ymmärtämään koodin kontekstia ja merkitystä täydellisesti, joten kehittäjien on oltava valppaita ja varmistettava, että AI:n ehdotukset eivät aiheuta ei-toivottuja seurauksia.

Kuristajaviikunan opit

Perinteinen "big bang" -uudelleenkirjoitus, voi tuntua houkuttelevalta mutta siihen liittyy paljon riskejä, potentiaalisia viivästyksiä ja odottamattomia kustannuksia.

Arvostettu ohjelmistoasiantuntija Martin Fowler kannattaa varovaisempaa ja strategisempaa lähestymistapaa, joka on saanut inspiraationsa Australiassa esiintyvistä kuristajaviikunasta (strangler fig) – nämä kasvit kasvavat toisten ympärille vähitellen ja sitten tukahduttavat isäntäkasvinsa vähitelleen.

Fowlerin filosofia perustuu vanhentuneiden järjestelmien asteittaiseen korvaamiseen. Kuvittele uutta järjestelmää kasvamassa hitaasti olemassa olevan ympärille, aivan kuin kuristajaviikuna. Ajan mittaan se sieppaa keskeisiä toimintoja ja kaappaa arvokasta dataa, tukahduttaen lopulta vanhan järjestelmän elinvoiman. Tämä menetelmä saattaa kuulostaa monimutkaiselta, mutta sillä on useita keskeisiä etuja:

  • Pienempi riski: Tiheiden julkaisujen ja jatkuvan arvon toimittamisen myötä kehittäjät voivat seurata tarkasti edistystä, mukautua muuttuviin vaatimuksiin ja lieventää perinteisiä uudelleenkirjoituksia vaivaavia riskejä.
  • Keskittyminen arvon luomiseen: Asteittainen lähestymistapa auttaa välttämään "big bang" -projekteissa usein esiintyvien tarpeettomien ominaisuuksien lisäämistä. Painopiste on aina konkreettisen arvon toimittamisessa loppukäyttäjille.
  • Tulevaisuudenkestävyys: Yksi Fowlerin tärkeimmistä oivalluksista on uusien järjestelmien suunnitteleminen siten, että ne on tulevaisuudessa helpompi korvata. Helpottamalla järjestelmien "kuristettavuutta" tulevaisuudessa suunnittelemme proaktiivisesti ohjelmistojemme väistämätöntä kehitystä.

Vaikka kuristajaviikuna-lähestymistavalla on omat haasteensa, se voi olla avain sujuvampiin ja menestyksekkäämpiin modernisointiprojekteihin. Jos organisaatiosi kamppailee vanhentuneen järjestelmän kanssa, tämä strategia on kelpo vaihtoehto perinteiselle uudelleenkirjoitukselle.

DevOpsista turvaverkko kehitykseen

Hyvät DevOps-käytännöt ovat välttämätön turvaverkko, kun lähdetään tekemään refaktrointia tai ohjelmistoa lähdetään tekemään uudelleen. Jos yritys lähtee tekemään esim. refaktorointia ilman kattavaa testiautomaatiota ja vahvaa CI/CD-putkea, ei kannata olettaa, että uusi ohjelmisto on hyvin yhteensopiva tarvittaviin rajapintoihin koodaustyön jälkeen – ja tässähän ei ole mitään järkeä.

Eficode on DevOpsin ammattilainen ja asiantuntijoillamme on runsaasti kokemusta sekä vanhojen ohjelmistojen päivityksistä että kokonaan uusien ratkaisujen toteuttamisesta asiakkaan tarpeiden mukaan. Pystymme myös auttamaan nykytilanteen arvionnissa, parhaiden etenemisvaihtoehtojen löytämisessä ja uudistusprosessin suunnittelussa.

Tutustu ketterän ohjelmistokehitykseN palveluihimme

Julkaistu: 23. huhtikuuta 2024

Software developmentCI/CD