Legacy applicaties moderniseren - een praktische gids

Wanneer je "legacy software" hoort, is het eerste beeld dat in je opkomt misschien dat van een aftandse applicatie, die de hele tijd vastloopt en een waslijst van onopgeloste bugs bevat.
Meestal is dit echter niet het probleem, en zijn legacy-applicaties net de applicaties die de langste staat van dienst hebben binnen een organisatie, en die routinematig de meest kritische bedrijfsprocessen op dagelijkse basis ondersteunen.
In dit e-book zoomen we in op de problematiek rond legacy software en bekijken we hoe je je ontwikkelingen terug op de rails krijgt.

 

Wat is legacy software en waarom is het een probleem?

Voordat je over een probleem kan nadenken en er een oplossing voor kan vinden, moet je het exact kunnen benoemen. Laat net dat nu niet zo evident zijn in het geval van problematiek rond legacy systemen. Op Wikipedia vind je een correcte, maar weinig verhelderende definitie: 'een computersysteem dat, ondanks dat het verouderd is, nog steeds in gebruik is'. Met name 'verouderd' lijkt een zeer subjectief gegeven.

Wanneer je "legacy software" hoort, is het eerste beeld dat in je opkomt misschien dat van een aftandse applicatie, die de hele tijd vastloopt en een waslijst van onopgeloste bugs bevat. Meestal is dit echter niet het probleem, en zijn legacy applicaties verrassend genoeg de applicaties die de langste staat van dienst hebben binnen een organisatie, en ook de applicaties die routinematig de meest kritische bedrijfsprocessen op dagelijkse basis ondersteunen.

 

If it ain't broken - don't fix it. Waar moet je net wel voor uitkijken?

Je bedrijf is slechts zo digitaal wendbaar als de applicaties waarop het draait. Je zorgt er dus best voor dat ze in topconditie zijn en zich gemakkelijk kunnen aanpassen aan een snel veranderende wereld.

De problemen en risico's zijn meestal niet acuut, maar ze worden wel steeds groter op de lange termijn. Vervolgens zijn de noodzakelijke maatregelen plots verrassend drastisch.

De problematiek bouwt zich vooral op rond drie grote pijlers:

  • Kennis over het systeem die in kleine stapjes achteruit gaat. De neiging en het zelfvertrouwen om veranderingen door te voeren nemen af - de nodige effort wordt steeds groter in verhouding aan de gewenste veranderingen.
  • Evolueerbaarheid in achteruitgang. Een systeem dat bij aanvang vlot wijzigingsaanvragen kon absorberen, loopt meer en meer vast in onmogelijke of minstens dure en complexe aanpassingen.
  • Efficiëntie - een systeem dat ooit z'n oorsprong had in een licht andere business context en een ander IT-landschap dan datgene waarin het ondertussen mee moet draaien, wordt op termijn sowieso minder efficiënt.

Wanneer je met ontwikkelaars of IT-mensen begint te overleggen, detecteer je waarschijnlijk al snel de eerste tekenen van legacy software. Maar hoe dan ook, technologie op zich zou geen einddoel mogen zijn, en ook zonder de laatste nieuwe technologie snufjes zal het nog steeds prima werken, nietwaar?

Ook voor business vormt legacy software doorgaans geen acuut probleem. Al moet je door een ietwat verouderde gebruikersinterface kijken of genoegen nemen met enkele workarounds om resultaten te bereiken. Net vanwege de stevige historiek vind je typisch nog weinig problematische bugs en worden deze systemen door gebruikers in het algemeen dan ook als zeer stabiel ervaren.

Al bij al wordt legacy software vaak uitsluitend gezien als een probleem van de IT-afdeling, die er uiteindelijk voor moet zorgen dat de noodzakelijke bedrijfsprocessen - met bestaande of nieuwe systemen - operationeel blijven. Het risico bij het vervangen van een legacy systeem is groot - denk aan change management, kinderziektes en bugs die steeds invloed hebben op de operationele activiteiten. Kortom, problemen die hand in hand gaan met de introductie van nieuwe tools en systemen, maar die met het legacy systeem al jaren niet meer voorgevallen zijn, en dan ook als achteruitgang ervaren worden.

De directe toegevoegde waarde van vervanging, is functioneel meestal klein tot onbestaand, en een echte business case voor vervanging is vaak moeilijk te maken, vooral als de tekortkomingen van het legacy systeem zich aan de technologische kant bevinden en niet direct business-vereisten hypothekeren. 

Het resultaat is dat er vaak niets actief ondernomen wordt, totdat minstens één van de drie genoemde factoren écht problematisch wordt.New call-to-action

 

Kennis & support

icoon_kennisStel jezelf de vraag: hoe goed kent je team een applicatie?  Kan je bij het plannen van wijzigingen de impact correct inschatten, of wordt dat telkens een heikel avontuur met veel trial-en-error?  Vind je de nodige hulp indien van toepassing? 
Documentatie is vaak een goede leidraad om één en ander te reconstrueren maar vervangt nooit de parate kennis van mensen die op regelmatige en kwalitatieve manier een applicatie onderhouden. 

Het komt geregeld voor dat organisaties weinig tot geen wijzigingen durven te maken aan een applicatie. Voornamelijk omdat er niemand is die deze opdracht zelfverzekerd durft aan te gaan. Wanneer een applicatie wordt opgeleverd, is er (normaal gezien) een duidelijk beeld over de functionaliteiten, business rules en opbouw van de software. Jammer maar helaas, hoezeer je ook het tegenovergestelde hoopt, gaat parate kennis over het systeem zeer snel achteruit. Code die je 6 maanden geleden schreef, kon even goed "door een andere ontwikkelaar geschreven zijn" is een quote de zeker niet uit de lucht gegrepen is. Er is geen betere leerschool voor een ontwikkelaar dan een tijdje op de support van een codebase te werken die je niet zelf geschreven hebt.

Je kan dit deels oplossen door de kwaliteit van de applicatie-code hoog genoeg te houden. Vaak is ondoordacht of overhaast onderhoud de norm en eindig je met een platgeprogrammeerde codebase waar niemand aan durft komen.

Externe hulp van de community én vendors zelf, houdt op een gegeven moment ook op.  Als je externe software componenten gebruikt, houdt de support op een zeker moment op - bugfixes en security patches worden dan niet meer verdeeld, het risico rond je legacy applicatie wordt daar groter mee.

Een beperkte kennis over je systeem plus verouderde technologieën hebben een sneeuwbaleffect op motivatie, maar ook op de retentie van je team en het recruteringspotentieel. Hoe meer veroudert de technologie, hoe moeilijker het zal zijn om ontwikkelaars geëngageerd te houden.
Het risico is dat het grote voordeel van je op maat gemaakte applicatie - de vrijheid om die aan te passen en te laten mee-evolueren met de business - ondergraven wordt door een te beperkte kennis en inzicht in het systeem.

infographic_legacysoftware-3.1

Evolueerbaarheid

icoon_evolueerbaarHoe vlot kan en durf je wijzigingen aanbrengen in je bestaande applicatie?  In hoeverre is de impact op de oplossing en nodige effort voorspelbaar en proportioneel ten overstaan van de gevraagde wijziging?
Aangezien je business altijd wel evolueert, wordt een applicatie die niet vlot meekan telkens een groter probleem en betekent ze gemiste opportuniteiten!  De gap met de nieuwe business requirements wordt dan alleen maar groter.

Vaak zie je applicaties waarvan de evolueerbaarheid eerder beperkt is: ze kan de huidige werkwijze nog wel ondersteunen (vaak betreft het zelfs de kritische bedrijfsprocessen), maar krijgt het steeds moeilijker om nieuwe vereisten te absorberen en is steeds moeilijker in te passen in een wijzigend technologie-landschap. Denk hierbij aan wijzigende werkprocessen, data-ontsluiting, nieuwe integraties, nieuwe kanalen, enz...
Evolueerbaarheid hangt sterk af van de kwaliteit van de applicatie-architectuur en codebase - als deze te complex of te slordig opgebouwd is, dan is elke wijziging een moeilijke en risicovolle actie.

Niet alleen de applicatie zelf, maar ook al de processen en tooling errond moet je evalueren: heeft je team nog een degelijke ontwikkelstraat en toegang tot verschillende omgevingen, die toelaten om in een minimum aan tijd wijzigingen gecontroleerd aan te brengen en degelijk uit te testen, alvorens de wijzigingen in productie uit te rollen? En wordt deze nog op regelmatige tijdstippen gebruikt of is de routine weg?  

Een laatste belangrijke vraag om jezelf te stellen, is of je nog een duidelijke "business owner" van de applicatie hebt. Het risico dat je loopt met applicaties waarrond niemand actief plannen maakt, is dat je in een reactieve onderhoudsmodus komt: enkel bij zichtbare problemen wordt er ingegrepen, en dan altijd onder tijdsdruk met als enige doelstelling om zo snel mogelijk te deblokkeren.

infographic_legacysoftware-3.3

Efficiëntie

icoon_efficiëntieIs je software operationeel en kostgewijs nog efficiënt? Hoe ver staat ze ondertussen af van de oplossing die je vandaag in een tabula rasa scenario zou uittekenen?
De wet van de remmende vooruitgang weegt ook op applicatie-ontwikkeling: technieken en oplossingen van vandaag zijn vaak efficiënter dan diegene die gebruikt werden bij het bouwen van de software.  

Functionele inefficiënties ontstaan door zeer diverse situaties: wijzigende werkstromen, een wijzigend applicatie-landschap, overnames, enz...  Veelal gaat het dan om dingen als dubbele invoer in twee applicaties, problemen rond data-duplicatie, data-kwaliteit en workarounds om de business realiteit in het systeem te laten passen. Ad-hoc oplossingen zoals bv één-op-één data-integraties tussen applicaties, kan je dan telkens als een korte-termijn oplossing hanteren, maar een aanpassing ten gronde van de applicatie aan de nieuwe omstandigheden gebeurt vaak niet.

Delen van de applicatie kunnen over de tijd heen overbodig of vervangen worden door functionaliteiten in andere pakketten. Vaak wordt software niet aan de basis aangepast aan deze nieuwe situaties, maar blijft die onaangeroerd en wordt er rond gewerkt.

Operationele kost (Opex) van een applicatie wordt vaak over het hoofd gezien. Meestal ligt de focus op de investeringskost (Capex) en de termijn waarop die afgeschreven kan worden.
De omvang van hosting- en onderhoudskosten hangen af van de applicatie zelf, en kan op termijn zeer inefficiënt worden ten opzichte van nieuwere oplossingen.
Mogelijkheden van commerciële softwarecomponenten die ondertussen kwalitatief in de open source wereld gevonden worden, de footprint van moderne technologieën kan een stukje lichter worden, verouderde tooling weegt op de productiviteit, enz... Kortom, keuzes die bij aanvang gemaakt werden, waren toen de juiste maar zijn dit op dit moment niet meer.
 infographic_legacysoftware-3.2

Applicatie modernisering

Alle software heeft een (eerder) beperkte levenscyclus. Of je nu de eerste tekenen van legacy in je applicaties ziet verschijnen, dan wel reeds enige tijdje met steeds grotere problemen geconfronteerd wordt... op een gegeven moment moet je aan modernisatie van een applicatie denken om terug in een vlot werkbare situatie te geraken.

Door de juiste acties te identificeren (en in te plannen) om de business kritische deelgebieden te onderhouden, kan de levensduur aanzienlijk verlengd worden.

Daar is spijtig genoeg geen algemene oplossing voor, en dus moet je voor elke applicatie specifiek bekijken wat de beste oplossing is.
Belangrijk om te weten is dat applicatie modernisering geen alles-of-niets verhaal is, de klassieke 80/20 regel is ook hier van toepassing - met 20% van de investering in tijd en budget los je doorgaans 80% van het probleem op!

We zien alvast 5 belangrijke doelstellingen om na te streven bij elke modernisatie:

De levensduur van de applicatie kwalitatief verlengen

Wanneer je beslist een applicatie niet volledig te vervangen maar door te laten evolueren in een modernisering, kies je voor een strategische beslissing om verder te investeren in de applicatie, mits de nodige souplesse in het onderhoud en doorontwikkeling te brengen. Met andere woorden, even op de rem gaan staan om dan terug voluit verder te kunnen.

Belangrijk is dus om in de modernisering de continuïteit veilig te stellen en toekomstgericht te denken. Neem zowel de business-functioneel als technisch grootste blockers onder handen en los ze op.

Een belangrijk aspect hierin is dat de levensduur van een software applicatie zeer vaak onderschat wordt bij aanvang - veel applicaties worden in praktijk veel langer gebruikt dan je bij aanvang voorstelde. De architectuur is dan ook niet voorzien op het vlot doormaken van enkele stevige ombouw-cycli.
Voorzie je applicatie-architectuur op vlotte vervangbaarheid van technologieën en veranker ze niet vast rond één specifieke technologie-component.

Big Bang vervanging vermijden

Wanneer je aan applicaties gaat sleutelen die dagdagelijks werkprocessen in je business ondersteunen, introduceert dit telkens een risico bij elke release. Deze kan je onder andere opvangen door een degelijke testing strategie te hanteren.
Ga je echter een geheel systeem in één keer vervangen dan wordt dit risico én de potentiële impact enorm, afhankelijk van de rol van de applicatie, het aantal gebruikers, enz...

Vermijd waar het kan een Big Bang aanpak die naast risicovol ook moeilijk te organiseren is. Werk liever stapsgewijs vanuit de huidige situatie. Op die manier hou je ook het change management errond behapbaar en kan je gaandeweg het nut van verdere modernisering én de juiste prioriteiten herevalueren.

Integreerbaar maken

Als er één karakteristiek is waar je je applicatie graag aan ziet voldoen, dan is het integreerbaarheid. Een business werkt niet geïsoleerd van de buitenwereld, maar vormt onderdeel van een eco-systeem van partijen die minstens op een vlotte manier data willen kunnen uitwisselen en liefst rechtstreeks in elkaars geautomatiseerde processen integreren.

Laat integreerbaarheid nu net een pijnpunt zijn bij veel legacy applicaties die één gesloten monolitisch systeem vormen en waar de enige gebruikersinterface vaak mee verweven zit in het volledige systeem. Dit doorbreken is een van de belangrijkste doelstellingen van je modernisering en zorgt ervoor dat de applicatie weer meekan in de toekomst.

Een moderne toepassing vertrekt vanuit het omnichannel idee en laat gebruikers toe om via meer dan één kanaal te werken. Van een webapplicatie over een mobiele toepassing, een chatbot, enz... In praktijk vereist dit een applicatie-architectuur die hierop voorzien is, met API (Application Programming Interface) gebaseerde integraties die een duidelijk contract bieden naar alle aansluitende kanalen, waarbij de interne werking van de applicatie geëncapsuleerd wordt en op die manier vlot z'n eigen evolutie kan doormaken zonder externe implicaties.
Een recentere evolutie is om de gebruikersinterfaces als een aparte applicatie te beschouwen - typisch hebben die een veel kortere levenscyclus. Zo krijg je voor je business processen en informatie-ontsluiting headless software die mee-evolueert met de business maar minder onderhevig is aan technologie-trends.

Daarbij aansluitend is het ook nuttig om te kijken of er geen meerwaarde uit onderdelen van de applicatie of de data die erin vervat zit, te halen valt. Vaak is - geanonimiseerde of geaggregeerde - business data waardevol voor partners, en in wat tegenwoordig een API Economy genoemd wordt kan het ontsluiten van één specifieke set business data, rules of processen zeer waardevolle service zijn voor andere partijen.
Een applicatie voorzien op zo'n type ontsluiting (een vlot API beheer, gedetailleerde beveiliging, e.d.) maakt deze ook meer toekomstgericht.

Een laatste concept rond integratie-doelstellingen is het repurposen van software - waarbij je onderdelen een andere bestemming geeft dan waar ze ooit voor gemaakt zijn. Data en logica worden vaak als onderdeel van een toepassing beschouwd, maar realiseren eigenlijk business capabilities die ook in andere situaties nuttig zijn. Denk bijvoorbeeld aan productconfiguratie logica die in manufacturing software verwerkt zit die je kan ontsluiten om op kost-efficiënte wijze een eenvoudige product-configurator voor klanten te realiseren. Modernisering van een applicatie moet dit soort rationeel hergebruik mogelijk maken. 

Evolueerbaarheid en beheersbaarheid verbeteren

Belangrijk is dat je de actieve kennis van een systeem terug gaat opbouwen, wat uiteindelijk de belangrijkste factor is in de evolueerbaarheid van een toepassing. Een team dat met vertrouwen plannen maakt naar wijzigingen toe, is je beste garantie voor een vlot onderhoud.

Daarnaast zorg je ervoor dat je terug een vlotte routine rond het bouwen, testen en deployen van de applicatie op gang brengt.  Dit betekent in praktijk het zorgen voor een moderne en performante ontwikkelstraat, die toelaat om - zo geautomatiseerd mogelijk - snelle aanpassingen te doen en uit te rollen. Vaak zie je bij legacy applicaties veel handmatig werk voor het bouwen en deployen van de software, waarvoor veelal zeer specifieke kennis van systemen en procedures nodig is.  Belangrijk is dat deze acties routine worden - ook voor mensen die de applicatie niet goed kennen, en geautomatiseerd worden waar mogelijk met parameters die het risico op misconfiguratie tegengaan.

Een laatste aspect hierin is de architectuur van de applicatie: eenvoud is hierin de de belangrijkste factor. Een complex systeem is altijd moeilijker om te evolueren dan een eenvoudig systeem - ga altijd op zoek naar de eenvoudigste en elegantste oplossing die mogelijk is, en vermijd technologie om de technologie. 

Operationele kost reduceren

Als je toch gaat sleutelen aan een applicatie, kan je net zo goed de operationele kost optimaliseren - veelal is dit trouwens een belangrijke factor om toch een duidelijke business case op korte termijn te kunnen maken.

Door cloud-computing kan investering in én beheer van eigen infrastructuur én middleware gereduceerd worden.

Als je toewerkt naar een scale-to-zero architectuurmodel kan je de effectieve runtime kost van een applicatie naar nul reduceren op momenten dat die niet gebruikt wordt. In plaats van een basisvoorziening in infrastructuur te gebruiken, gaat zo'n architectuur uit van componenten die enkel aangerekend worden als ze effectief gebruikt worden - Serverless computing is daar een mooi voorbeeld van.  Het potentieel van deze aanpak is vaak groter dan op het eerste zicht lijkt: veel applicaties worden slechts tijdens de werkuren gebruikt, of de basis-infrastructuur is gebaseerd op piekgebruik dat helemaal niet representatief is voor het gemiddelde gebruik.

Mogelijke strategieën voor modernisering  

Afhankelijk van de situatie kan je verschillende kanten uit met je huidige applicatie. Ga je ze stapsgewijs toewerken naar een situatie die terug toekomstgericht is?  Of is het beter om ze in één keer te vervangen? Vertrek je dan met een baseline die functioneel gelijk is aan de bestaande toepassing?

We zetten de grote strategieën rond modernisatie op een rijtje - hou zeker voor ogen dat sommige ervan ook perfect als opeenvolgende stappen te realiseren zijn.

Rehost

icoon_rehost-roosAls je je applicatie gaat rehosten dan verplaats je ze van een bestaande infrastructuur naar een nieuwe, zonder fundamenteel aan de werking of de structuur van de applicatie te raken. In praktijk betekent dit meestal een "lift-and-shift" van een eigen datacenter naar een publieke cloud provider (Amazon AWS, Microsoft Azure, Google Cloud Platform, ...). 

De voordelen die je hieruit kan halen zijn afhankelijk van de situatie :

  • De cloud biedt een grote mate van flexibiliteit om meer of minder resources toe te wijzen aan de applicatie, iets wat in een klassiek datacenter of in je eigen hosting niet altijd evident is. Even een extra server toevoegen voor de piekperiode, of eens kijken of de performantie van de applicatie verbetert door de database server van extra geheugen te voorzien? Allemaal zeer evident.
  • Daarnaast is je core business waarschijnlijk ook geen applicatie hosting en vervang je het beheer van de netwerk-infrastructuur, firewall, load balancers, servers en file systems liefst door managed services bij een cloud provider, waar je enkel configureert welke zaken je nodig hebt, maar niet zelf in hoeft te staan voor realisatie, onderhoud en monitoring ervan.
  • Door zowel het schaalvoordeel als het gebruik van managed services, waarbij je op je eigen activiteiten kan rationaliseren is vaak ook een kostreductie voor de TCO (total cost of ownership) realiseerbaar.

schema_rehost

Belangrijk bij een rehosting is dat de applicatie zelf onaangeroerd blijft. Er is dus geen impact op functionaliteiten of werkprocessen en eens de migratie gevalideerd is, is er geen risico of impact op de applicatie op zich.
Meestal is rehosting een eerste stap ter voorbereiding van verdere modernisatie van de applicatie, om de nodige flexibiliteit in de infrastructuur te brengen die verdere aanpassingen uberhaupt mogelijk maakt.

 

Replatform

icoon_replatform-roosReplatforming betekent dat je je huidige applicatie gaat draaien op een nieuw platform, dus geen eenvoudige lift-and-shift, maar effectief een andere technische basis waarop die draait. Uiteraard zal je hiervoor beperkte aanpassingen aan de applicatie moeten doorvoeren, maar de werking en de functionaliteit voor de gebruikers blijft in principe exact dezelfde.

Merk op dat de term "replatforming" soms ook gebruikt wordt om een herimplementatie van een systeem op basis van een ander off-the-shelf product te benoemen (bv migratie van het ene E-commerce pakket naar het andere, wat in feite neerkomt op minstens een rebuild of zelfs een vervanging van de bestaande software).  

De algemene doelstelling die je hier nastreeft, is om een stukje "hoger" in de technische stack te gaan werken en zoveel mogelijk managed services en managed platforms te gebruiken waarvoor je de dagdagelijkse operationele verantwoordelijkheid dan externaliseert.
In praktijk dus een besparing van kosten, een reductie van risico, en een applicatie die vlotter te onderhouden en te evolueren zal zijn.

Over de hele applicatie-architectuur zijn er heel wat punten waarop je zo kan rationaliseren op operationele verantwoordelijkheden die typisch niet je core business zijn, bv:

  • Een applicatie-server op een virtuele machine met Linux operating system vervangen door een managed PaaS platform bij een cloud provider
  • Een database server vervangen door een managed database instantie, waarbij je niet meer hoeft in te staan voor management, patching, en eventueel zelfs backups van de database
  • Een mailserver vervangen door een managed mail service (bv: Azure Email Service, Google Cloud Email Service, Amazon SES), waarbij je enkel e-mails verstuurt via de service, en niet meer hoeft in te staan voor het beheer van de mailserver zelf
  • Een shared filesystem met de nodige ontsluiting – NFS, FTP, ... - dat je zelf ingericht hebt en beheert, kan je vervangen door een high-level file system service (Amazon Elastic File System, Google Filestore, ...) waarbij je louter de inhoud en toegangen daarop instelt.

Een concreet voorbeeld: een Java applicatie die nu op een Tomcat application server draait in een hosting die je zelf installeerde en beheert op een gevirtualiseerde Linux host, kan je laten draaien op een managed Tomcat PaaS (Platform-as-a-service) omgeving bij een cloud provider (bv Amazon AWS), waardoor alle bezorgdheden rond zowel het beheer en patching van de Linux installatie als het beheer en patching van de Tomcat instantie "gehuurd" worden, en je je focus volledig op de applicatie zelf kan leggen.

schema_replatform

Zoals je ziet, zal een rehosting naar een omgeving die deze services biedt (public of private cloud) meestal nodig zijn alvorens je aan replatforming kan starten.

 

Refactor

icoon_refactor-roosRefactoring van een applicatie houdt in dat je de opbouw en structuur van de codebase gaat wijzigen, zonder de functionaliteit zelf aan te passen, of aan de algemene architectuur te raken. In principe ga je dus enkel kwalitatieve aanpassingen doen, geen functionele.
De redenen hiervoor sluiten allemaal redelijk kort bij elkaar aan:

  • Het onderhoudbaar maken of houden van de applicatie
  • Het evolueerbaar maken of houden van de applicatie 
  • Het vereenvoudigen van de structuur en architectuur
  • Het standaardiseren van de gekozen oplossingen 
  • Het leesbaar en begrijpbaar houden van broncode
  • Het verlengen van de levensduur van de software

Als je denkt "dat klinkt als opkuisen" - dan ben je helemaal juist! De "technical debt" die zich over de tijd onvermijdelijk aandient verminderen, om een gezonde, bevattelijke en onderhoudbare applicatie te garanderen. In principe is refactoring een activiteit die tijdens bouw én onderhoud mee vervlochten hoort te zitten in de activiteiten, maar vaak gebeurt dat onder tijdsdruk niet, wat de inhaalbeweging later alleen maar groter maakt.

Voordat we blind aan de knoppen beginnen draaien, voorzien we - indien deze ontbreken - een reeks aan geautomatiseerde test cases om de meest kritische paden van de applicatie af te dekken.

Vaak gaat refactoring vooraf aan grotere aanpassingen, die goedkoper én met minder risico op een codebase uitgevoerd kunnen worden na een goede ronde aan refactoring. Een belangrijke vereiste voor een refactoring is dat je de nodige voorzieningen getroffen hebt om de applicatie na refactoring grondig door te testen - doorgaans komen tijdens refactoring nog andere verborgen gebreken en bugs in de software naar boven.

Na refactoring is de zin en het zelfvertrouwen in het maken van aanpassingen in je team logischerwijs een stuk groter dan daarvoor.

Een goed startpunt om met refactoring ideeën aan de slag te gaan én ze te benoemen om de communicatie errond in je team te vergemakkelijken, is de lijst van refactoring acties in de refactoring catalog van Martin Fowler, ook in boekvorm terug te vinden.

 

Rearchitect

icoon_rearchitect-roosHeel wat problemen aanpakken en optimalisaties doorvoeren in een applicatie lukt je niet zonder gegrond de structuur of architectuur te herbekijken.

Vaak maakt rearchitecting het leeuwendeel van een modernisatie uit, eens de juiste context gecreëerd is om vlot ingrijpende aanpassingen te doen.

De mogelijke technieken zijn zeer talrijk en divers  - we hebben er een volledig hoofdstuk 'Rearchitecting - ideeën en patronen'  over voorzien.

 

Rebuild

icoon_rebuild-roosAls je beslist dat de weg van stapsgewijze verbeteringen te complex of te lang zou zijn, kan je uiteraard beslissen om de bestaande applicatie-functionaliteiten te herbouwen in een nieuwe technologie-stack. Als je van technologie wil wijzigen (JQuery naar React, .NET naar Java, ...) dan is een rebuild van minstens meerdere delen van de applicatie meestal de enige optie.

Om ervoor te zorgen dat dit voor de organisatie gezien geen al te groot avontuur zou worden, kan je dan as-is gaan herbouwen zodat de nieuwe toepassing een één-op-één vervanging kan zijn voor de legacy toepassing, en werkprocessen en activiteiten voor alle gebruikers initieel dezelfde blijven, zodat er geen groot change management traject bij komt kijken.

Uiteraard loop je de kans dat herimplementatie nieuwe fouten in het systeem introduceert, belangrijk is dus dat je de werking exact kan verifiëren tegen die van het bestaande systeem. Als je herbouwen gaat combineren met het doorvoeren van aanpassingen dan valt deze zekerheid uiteraard weg - heel belangrijk is dat iedereen het erover eens is of het om een rebuild (as-is) of een vervanging (met wijzigingen en nieuwe functionaliteiten) van de toepassing zal gaan.

Vanuit gebruikersstandpunt zijn deze problemen met de herbouwde toepassing zeer vervelend.  Werkprocessen die al jaren goed draaien in de software lopen het risico erdoor geïmpacteerd te worden, terwijl er geen nieuwe mogelijkheden of functionaliteiten worden toegevoegd. Maar ook naar beslissingsvorming is zoiets geen evidentie: aangezien je een budget moet uittrekken voor een rebuild die enkel een technologische vernieuwing inhoudt, geen nieuwe functionaliteiten biedt, en mogelijk nieuwe problemen introduceert, wordt deze vorm van modernisering nogal eens als het oplossen een IT-probleem aanzien - een puur technische oefening om weer mee te kunnen met nieuwste technologie.  Vaak is een rebuild - zeker zonder aansluitende verdere wijzigingen - dan ook moeilijk verteerbaar voor heel wat stakeholders.

Overschat ook zeker niet de kennis die je in de organisatie over een legacy systeem hebt.  Mensen die betrokken zijn geweest bij de bouw zijn vaak niet meer aanwezig, documentatie is nooit concreet bijgewerkt geweest, en tal van andere problemen kunnen maken dat je geen up-to-date dossier ter beschikking hebt.  Als je de recentste broncode van de applicatie ter beschikking hebt kan een technische migratie (al dan niet geholpen door tools) helpen, indien niet zal je een stukje reverse engineering moeten toepassen om de juiste werking te achterhalen.

Gebruikers voeren hun dagelijkse taken in de legacy applicatie vaak uit zonder nog echt stil te staan bij de achterliggende processen en logica, vaak moet je dus gaan uitzoeken hoe een applicatie exact werkt, welke business rules en berekeningen er net achter de schermen schuil gaan. 

Als de technische gap tussen de legacy applicatie en de huidige gangbare of gewenste technologie-stack onoverbrugbaar is, overweeg dan zeker het herbouwen van de applicatie, met de huidige functionaliteiten als houvast voor het implementatietraject én de gebruikers.

 

Replace

icoon_replace-roosAfhankelijk van de situatie kan je voor een volledige vervanging van het legacy systeem kiezen. Dit houdt in dat er zowel technisch als functioneel een nieuw systeem wordt gekozen of gebouwd dat de legacy applicatie zal vervangen.
Uiteraard geeft dit alle vrijheid naar keuze tussen kopen of bouwen (buy-or-build beslissing), maar gaat het ook wel degelijk om een nieuwe implementatie: buiten een data-migratie wordt meestal weinig of niets gerecupereerd van het legacy systeem, en ook de business processen en dagdagelijkse gebruikersactiviteiten zullen sterk wijzigen. 

In principe komt dit neer op een nieuwe software applicatie die geheel of gedeeltelijk de rol van de legacy applicatie in een aantal business processen zal overnemen.

Als de functionele gap tussen de legacy applicatie en de huidige noden groot zijn, is het vaak een goed idee dat je voor een totale vervanging gaat.

 

Moderniseringsstrategie bepalen

Wanneer je gaat bepalen met welke strategie je de modernisering van je legacy applicatie gaat aanvliegen, hou dan volgende punten voor ogen:

  • Elke applicatie en elke situatie is verschillend
  • Legacy is leerzaam - software die al jaren de business ondersteunt, bevat veel waardevolle informatie
  • Hergebruik van legacy code die al jarenlang stabiel draait, kan een geweldige opstap zijn naar een nieuwe applicatie 
  • Je kan het risico én de investering spreiden door de modernisering stapsgewijs aan te pakken
  • Vervanging van sommige legacy systemen met moderne technologie is niet noodzakelijk triviaal - als je je oude mainframe applicaties gaat herschrijven naar open systemen is het soms een hele uitdaging om dezelfde stabiliteit, veiligheid, snelheid en efficiëntie te realiseren

De investering én meerwaarde van de verschillende strategieën zijn nogal verschillend:grafiek_strategie

Sommige van de beschreven strategieën zijn alternatieve keuzes, terwijl andere een logisch opstapje zijn naar de volgende.  Dat ziet er als volgt uit:

workflow_strategie

Belangrijk is dus om initieel je algemene strategie te bepalen:

  1. ofwel in stapjes investeren in een modernisering van je huidige applicatie, wat kosten in de tijd spreidt, toelaat om te focussen op de meest relevante of urgente aspecten, en naar wijzigingsbeheer behapbaar blijft
  2. of de applicatie volledig wil herbouwen op basis van de huidige functionaliteit, wat naar wijzigingsbeheer, opleiding, hergebruik van test scenario's en dergelijke beheersbaar is
  3. oftewel een volledige vervanging van de applicatie verkiest (op maat ontwikkeld of configuratie van een standaardpakket), waarbij functionaliteiten en werkprocessen volledig herdacht worden.

Ideeën en patronen rond rearchitecting

Wanneer je er voor kiest om je applicatie te gaan rearchitecten, is de volgende vraag welke acties je net gaat ondernemen. Alles hangt uiteraard af van de situatie en je doelstellingen, maar een aantal algemene patronen en gangbare technieken kunnen alvast de nodige inspiratie bezorgen.

Een overzicht van de acties die typisch de grootste positieve impact zullen hebben op de kwaliteit van je applicatie vernieuwing:

 

Ontsluit legacy code via een API

Integratie is een aspect waar je legacy applicatie vaak slecht op scoort - het ontwerp is afgestemd op het wereldbeeld dat er van uit ging dat alle activiteiten en data beheer in de applicatie zelf konden afgehandeld worden, of de technologie is zo oud dat het niet voor de hand lag om ze vlot aansluitbaar te maken.

Nochtans is een applicatie die zich vlot laat integreren cruciaal geworden in de huidige context, denk aan:

  • Omnichannel vereisten, waarbij data en functionaliteit beheerd door de applicatie via meerdere en telkens nieuwe kanalen ter beschikking wordt gesteld van de gebruikers.
  • Het verschijnen van een API Economy waarbij partijen data, processen en inzicht tegen vergoeding ter beschikking stellen van anderen, vlot integreerbaar als kleine bouwstenen in plaats van als volledige software-pakketten.

Er zijn er ook wel wat interne redenen waarom je je applicaties primair vanuit API's wil gaan benaderen:

  • je bereikt een grote mate van vrijheid om de applicatie volgens een eigen levenscyclus te laten evolueren, zonder impact naar integraties toe zolang het API contract gelijk blijft
  • je bent in staat om correcties en modernisaties van de applicatie te doen zonder externe impact
  • je bent voorbereid op het afsplitsen van front-end gebruikersinterfaces die standaard sneller evolueren dan de business logica of backend componenten
  • je bent voorbereid om de applicatie indien gewenst fijnmaziger te maken - bijvoorbeeld richting een microservices architectuur
  • API-gebaseerde testing is eenvoudiger op te zetten dan die op specifieke gebruikersinterfaces, en rationaliseert de test-aanpak aangezien grote delen van de applicatie slechts 1x getest kunnen worden voor alle kanalen  

Een gigantische stap vooruit bereik je door de functionaliteiten van je applicatie in te pakken in API's en deze als basis voor alle integraties te gaan hanteren.  Door documentatie over die API te publiceren kan je interne en eventueel externe ontwikkelaars autonoom maar gecontroleerd aansluitingen laten maken, en doordat de API fungeert als een contract kan je de integraties op lange termijn actief beheren door versionering en uitfasering te plannen in de tijd.  

Je zal zien dat het meestal redelijk vlot lukt om een API laag rond je legacy applicatie te bouwen, wat ineens een gigantisch voordeel biedt.

Ofwel doe je dat door de API's bij te bouwen in de applicatie zelf, wat al dan niet makkelijk is afhankelijk van de technologie waarin de applicatie is opgebouwd.  Denk aan een klassieke monolitische Java-applicatie met een web interface en business logica in één component - hier is het toevoegen van een API laag bovenop de logica meestal vlot haalbaar én een voorbereiding naar het afsplitsen van de gebruikersinterface.schema_legacy-code-api

Een andere aanpak is om een API component voor de applicatie te plaatsen, en deze als het ware tussen de buitenwereld en je applicatie te laten vertalen. 
schema_legacy-code-api-component

Als het beheer van deze API's een uitdaging wordt, of je vereisten verder gaan dan pure integratie - als je bijvoorbeeld data en processen wil gaan commercialiseren - dan kan een API Management oplossing soelaas bieden.

 

Scheid applicatie- en business-componenten  

Een IT-landschap is vaak een aaneenschakeling van applicaties die op verschillende momenten in de tijd ontworpen, gebouwd en geïntegreerd zijn, waarbij er vaak te weinig planmatig gewerkt is kunnen worden.
Het beeld dat je vaak terugvindt, is dat van een applicatie die als een "stovepipe" alle aspecten van gebruikersinteractie tot business transacties in één pakket bundelt, en daarmee een aantal business processen ondersteunt of automatiseert.

Vanuit applicatie-ontwikkeling lijkt dat op zich geen onlogische aanpak - de volledige project scope vormt immers een belangrijke deliverable, maar naar verder onderhoud en evolueerbaarheid toe, zijn hier wel een aantal stevige nadelen aan verbonden:

  • Bij elke applicatieve wijziging moet de volledige scope van de applicatie hertest worden - ook de onderdelen die helemaal niet applicatie-specifiek zijn, wat minstens het validatie-proces maar ook de ontwikkeling zwaarder maakt dan nodig
  • Nieuwe kanalen, use cases e.d. worden vaak bij in de scope van de applicatie genomen, wat het aantal wijzigingspunten binnen deze scope nog doet toenemen het het probleem verder uitvergroot
     

De applicatie-specifieke functionaliteiten hebben vaak een directe link met het kanaal, de gebruiker of een specifieke use case:

  • kanaal-specifieke functionaliteiten zijn bijvoorbeeld specifieke schermen voor de website, generatie van push notificaties naar de mobiele toepassing, enz ...
  • gebruiker-specifieke functionaliteiten zijn bijvoorbeeld schermen voor de eindklanten, dashboards voor specifieke business gebruikers, enz...
  • use case-specifieke functionaliteiten zijn bijvoorbeeld voorlopige data die door gebruikers in het systeem kan ingevoerd worden ter voorbereiding alvorens er een business transactie mee te gaan ondernemen

Functionaliteiten die de business reflecteren hangen niet af van de specifieke gebruiker, het kanaal of de specifieke use case

Denk maar aan:

  • Business transacties: het registreren van een contract, order, betaling, of het nemen van een business beslissing rond prijszetting, enz...
  • Business data: welke informatie hebben verzamelen we waarover?
  • Processen: welke beslissingen nemen we, wat is de logische volgorde der dingen, wat is de volgende te nemen actie in de huidige situatie?
  • Business rules: wat is wel en niet toegelaten, of hoe ziet het beslissingsproces rond bepaalde vragen er uit? 

Realiseer je dat elke applicatie een combinatie bevat van; enerzijds business aspecten die typisch zeer stabiel zijn over lange termijn en algemeen gelden, en anderzijds applicatieve aspecten die vaak veel vluchtiger zijn. Analyseer even je applicaties, en stel jezelf telkens de vraag welke onderdelen effectief je business representeren, en welke onderdelen eerder situationeel zijn ingericht naar een bepaald type gebruiker, kanaal of een specifieke use case.
De grote lijnen voor je volgende doel-architectuur zullen snel duidelijk worden.

Als je de architectuur van je applicatie gaat hertekenen, zorg dan dat je deze beide goed scheidt.  Zo isoleer je frequente wijzigingen aan de technologie of interfaces langs de gebruikerskant tot dat specifiek kanaal, zonder impact op andere uitdeinenden.
Dit is niet zo triviaal als je op eerste zicht zou denken - het gaat niet om de scheiding tussen gebruikersinterface en achterliggende logica, maar wel rond waar de breuklijn tussen algemene business en specifieke toepassing ligt.

Een voorbeeld van deze aanpak is het "backend-for-frontend" principe, waar je een frontend samen met een applicatie-specifieke backend als één component ziet, die op hun beurt aanhaken bij achterliggende business componenten die volledig agnostisch zijn over het kanaal of de specifieke use case.

Je architectuur in deze zin herinrichten zorgt ook dat je voorbereid bent op nieuwe kanalen, use cases en applicaties - bijvoorbeeld een mobiele applicatie naast de website, een chatbot of een integratie met een nieuwe business partner - zonder dat die je huidige architectuur in vraag stelt of een evolutie moet laten doormaken. Door de specifieke scope voor componenten te definiëren kan je de aanpak voor elk apart bepalen in functie van de noden en verwachte evolutie, in plaats van uit te gaan van één aanpak voor het geheel. 

schema_scheid-applicatie-en-business-componenten

Het idee om een onderscheid te maken tussen applicatieve componenten en business componenten sluit ook enigszins aan bij het idee van bimodal ITwaarbij je in je IT organisatie twee verschillende modi van werken gaat hanteren:

Modus 1 is gericht op het opleveren en onderhouden van alles wat voorspelbaar en bekende materie is - in praktijk dus vaak je core business transacties, processen en rules (systems of record). In deze modus worden alle tools, processen en procedures ingericht in functie van kwaliteit, stabiliteit en lange termijn roadmap, met een matig tot zelfs trage ontwikkelstraat en release kalender als typisch resultaat.
Vaak zie je dan ook dat modus 1 wordt ingevuld met een klassiekere benadering van software ontwikkeling zoals upfront analyses, business acceptance testing na oplevering, een release kalender met een beperkt aantal releases per jaar, enz...

Modus 2 is gericht op snelheid en innovatie - vaak wordt ook naar een startup-approach verwezen - en wordt gebruikt voor alles wat snel naar de markt moet, nog getoetst moet worden aan de realiteit of minstens nog een bepaalde onzekerheid bevat, en waar de levensduur mogelijk beperkter wordt, al is het maar vanwege snel evoluerende technologie.

Een agile project-methodologie, nieuwe technologieën en concepten als prototyping en MVP releases vormen vaak een praktische invulling van deze modus.

Als je van plan bent om de principes van bimodal IT toe te passen en de twee modi naast elkaar te gaan hanteren dan is het cruciaal om naast je procedures en projectaanpak ook in je architectuur andere voorzieningen te treffen om dit te faciliteren.
Zorg dat je aparte componenten definieert die elk duidelijk in één van beide modi gebouwd en onderhouden worden. Wijs elke vereiste en functionaliteit duidelijk aan één van beide toe.  

 

Vervang In-house oplossingen door standaard componenten

Software op maat bouwen geeft je de vrijheid om software in te richten zoals je zelf wil, zonder compromissen met de visie van een pakket vendor. Realiseer je wel dat elke lijn code tijd en budget vraagt voor ontwikkeling, testing, support en onderhoud - deze wil je gedoseerd en zeer gericht inzetten daar waar je een competitief voordeel ziet, en niet in allerlei standaard functionaliteiten die even goed in open source of SaaS oplossingen te vinden zijn.  

Vaak is er ook wel wat twijfel rond de integratie van bestaande software in een oplossing, maar meestal wegen de voordelen van een bewezen component niet op tegen het zelf bouwen en onderhouden als het over redelijk standaard functionaliteiten gaat. Een veelgehoorde term hier rond is het NIH (Not Invented Here) syndroom - dat gebruikt wordt om te verwijzen naar het fenomeen dat organisaties een afkeer hebben van software componenten die niet zelf ontwikkeld zijn.  

Als je je applicatie gaat rearchitecten, is er heel wat meerwaarde te halen uit het kritisch evalueren van gebouwde functionaliteit tegenover beschikbare software op de markt (in open source, SaaS, of commercieel pakket). Delen van de oplossing die geen differentiator zijn kan je best als commodity integreren. Alle standaard functionaliteiten die je zo uit de scope kan halen reduceren de complexiteit van het onderhoud en de leercurve om in te werken in het systeem.


Ga op zoek naar functionaliteiten in je applicatie die je kan externaliseren in een bestaande software en integreren, vaak krijg je er heel wat nieuwe functionaliteiten bovenop. Wat vooral belangrijk is, is dat deze niet-core functionaliteit van je applicatie beperkt wordt tot een integratie in plaats van een software engineering scope.

Enkele voorbeelden van typische functionaliteiten die je in de meeste gevallen best integreert en niet zelf bouwt:

  • Authenticatie & autorisatie is een klassieker onder de vereisten die een hele hap uit je ontwikkel- en onderhoudsbudget kan nemen.
    Het beheer van gebruikers, groepen, rechten en rollen, maar ook beveiligde password opslag, SSO (single sign on) en 2FA (Two-Factor Authentication) vind je vaak in maatontwikkeling terug, terwijl er perfecte oplossingen zijn om deze kritieke component eenvoudigweg te integreren - denk bijvoorbeeld aan tools als Auth0.
  • Contact informatie: ontwikkelingsprojecten voorzien vaak in een beheerssysteem voor contactgegevens van personen en organisaties.  Deze typische CRM (Customer Relationship Management) functionaliteit  - het bijhouden van de signalitieke gegevens van gebruikers zoals een naam, telefoonnummer, e-mail, e.d. kan ook vaak beter betrokken worden in een externe tool die daarenboven meestal nog heel wat extra functionaliteiten bevat (detecteren van duplicaten, validatie, opt-in, enz...) 
  • Workflow - zelfgebouwde workflow oplossingen zijn vaak complex en maken geen gebruik van bestaande standaarden (BPMN, ...) kunnen niet visualiseren wat er at runtime gebeurt, enz...Kwalitatieve BPM (Business Process Management) componenten bestaan zelfs in open source en kunnen vlot integreren in je applicatie om alle workflow aspecten af te handelen.
  • Het verzenden van e-mails
  • Typisch bevat dit wel wat complexiteit rond het templaten van deze e-mails, een integratie met een eigen mailserver als integratiepunt, foutafhandeling en herzenden, en als de vereisten te ver beginnen te gaan het traceren van openen van e-mails en doorklikken op links in de e-mail.
  • Document generatie
    Ook hier is template beheer, het genereren van documenten in verschillende technische formaten enz ... iets wat beter met bestaande software wordt aangepakt
  • Document beheer
    Van zodra documenten opgeslagen in een systeem van meta-informatie moeten voorzien worden, opzoekbaar en zelfs doorzoekbaar moeten zijn brengt een DMS (Document Management System) een meerwaarde tegenover eigen ontwikkelingen
  • Content beheer
    Assets zoals afbeeldingen, filmpjes, geluidsfragmenten, teksten, met alle bijhorende vertalingen en in diverse ondersteunde formaten stop je best in een CMS (Content Management System)
    Identificeer dit soort functionaliteiten en evalueer telkens of het nuttig kan zijn om deze te door standaard implementatie te vervangen, onder de vorm van:

    schema_rearchitecten-3-mogelijkheden
  • Een SaaS (Software-as-a-Service) - meestal is zo'n platform voorzien van goed gedocumenteerde API's die toelaten om data uit te wisselen en functionaliteiten aan te roepen.
  • Open source libraries - de open source community heeft een heel aantal zeer mature producten en libraries voortgebracht, die ook in zeer veel verschillende omstandigheden en gebruiksscenario's zijn doorgetest
  • Commerciële pakketten - waar de afweging moet gemaakt worden van de kost van het aankopen versus het zelf bouwen en onderhouden van de functionaliteit

Een applicatie wordt op die manier gebouwd als de integratie van een aantal (best-of-breed) componenten, aangevuld met eigen ontwikkelingen en geïntegreerd waar nodig. Zolang die integraties API-gebaseerd zijn is er veel mogelijk, de grootste problematiek ontstaat echter meestal in het integreren van visuele componenten aan de gebruikersinterface. Je wil je gebruikers geen waslijst aan verschillende applicaties aanbieden die samen een aantal end-to-end processen realiseren, maar zelfs als je er technisch in slaagt om de visuele componenten van elk stuk software te integreren, is het resultaat qua UX (user experience) meestal geen fraai zicht.

Een goede strategie om dit aan te pakken is om de geïntegreerde componenten nooit user-facing te gebruiken, maar ze in te pakken in een eigen visualisatie, er met andere woorden je eigen schermen op bouwen. Op deze manier hou je ook de mogelijkheid open om één component te vervangen door een andere, zonder dat dit zichtbaar moet zijn naar de gebruiker van de software toe.

Een concreet voorbeeld: een SaaS CRM pakket wordt "op de achtergrond" geïntegreerd voor het beheer van contactinformatie maar deze informatie wordt wel ontsloten via eigen applicatie-schermen zodat er geen directe gebruikersinteractie met het CRM pakket is. Als dit ooit uitgefaseerd of vervangen wordt, dan kan dit zonder impact op de aansluitende applicaties.

Het idee rond headless software gaat helemaal deze richting uit, meer en meer tools nemen deze manier van value leveren als standaard. Uiteindelijk zit de waarde in de business kennis, business logica en informatiestructuur van een softwarepakket, niet in de mooie schermen die daarbovenop gebouwd worden. Op die manier kan je ook zeer diverse functionaliteiten combineren tot een volledig systeem, en er een optimale gebruikersapplicatie op bouwen. 

Een voorbeeldje:

schema_headless-software

Overweeg zeker een architectuur waarbij je de integratie tussen de verschillende componenten abstraheert op het niveau van een geïntegreerde API, en waar bovenop je dan een gebruikersapplicatie bouwt   Het resultaat zal een kleinere scope en codebase zijn, met een bewezen oplossing voor elke standaard functionaliteit, wat een snellere implementatie en vlotter onderhoud oplevert.  Meestal is de totale kost (TCO) van de oplossing ook lager dan voor een volledig op maat gebouwde toepassing.

 

Containerisatie van je applicatie

Als je je legacy applicatie gaat opdelen dan is het resultaat uiteraard een groter aantal componenten, die allemaal een eigen runtime omgeving nodig hebben. Elk van die componenten inrichten in een virtuele machine zou voor een hoge operationele kost én intensief onderhoud zorgen.

Hierop rationaliseren kan met container-technologie – Docker is een de facto standaard geworden - die toelaat om processen apart te verpakken in containers, zonder dat je een hele virtuele machine moet opstarten.
De voordelen zijn dan ook dat je containers zeer snel kan opstarten, dat de images een veel kleinere omvang hebben dan virtuele machines, en dat je er heel wat op één machine naast elkaar kan laten draaien, terwijl ze toch mooi afgescheiden van elkaar blijven en interacties enkel mogelijk zijn waar jij dat wil.

schema_containeriseer-je-applicatie

Naast deze infrastructuur-voordelen, zijn er ook heel wat andere redenen om container-technologie te overwegen: 

  • Containers kunnen overal draaien: van een developer-laptop over een private hosting-omgeving tot op een multi-region infrastructuur bij een public cloud provider
  • Containers maken het bouwen van omgevings-onafhankelijke software makkelijk door standaard manier te voorzien om parameters die een container nodig heeft te specifiëren en de nodige configuratie vanuit elke omgeving door te geven
  • Containers abstraheren infrastructuur en leggen het basisplatform voor applicaties een stuk hoger in de technologie-stack, wat helpt om je focus op business functionaliteit te houden
  • De output van elke build proces is vormelijk gelijk: een container image- hetgeen automatisatie van deployments gestandaardiseerd maakt
  • Elke software component in de architectuur is op dezelfde manier te beheren, onafhankelijk van de technologie die erin gebruikt wordt - een polyglot architectuur wordt dan ook praktisch een stuk makkelijker te realiseren
  • Containers zorgen voor een duidelijke scheiding tussen applicatie en infrastructuur, wat samenwerking tussen ontwikkeling en operations eenvoudiger maakt

Containerisatie van je legacy applicatie is meestal een zeer haalbare stap:

  • Pak het pragmatisch aan: start gerust met één container voor de volledige applicatie en splits de applicatie nadien verder op, en maak gebruik van een container beheersplatformen zoals Kubernetes (K8S) - het beheer van meer dan enkele containers zonder tool wordt al snel problematisch.
  • Gebruik containers niet voor services zoals databases maar richt die in als een aparte service naast je container infrastructuur.
  • Beschouw de opzet en het beheer van een containerisatie platform als Kubernetes niet als een verantwoordelijkheid van een ontwikkelploeg, maar als een applicatie-platform die je bij voorkeur als managed service betrekt
  • Pas je applicatie waar nodig aan in functie van containerisatie: maak containers omgevingsonafhankelijk door secrets, configuratie parameters en dergelijke, via het container mechanisme binnen te brengen.
  • Zorg ook voor een goede structuur in je container images: onderhoudt basis-images met nodige die regelmatig patches krijgen voor security- en andere updates, en werk met voldoende verschillende lagen om per applicatie component kleine images te kunnen bouwen vanuit je ontwikkelstraat, zodat de logistiek rond container images niet gaat wegen op een snelle CI/CD pipeline.

Migreer een monoliet naar (micro-)services

Rearchitecting van een applicatie impliceert dat je ook terug gaat nadenken over de opdeling van je software in verschillende componenten, met de granulariteit van deze opdeling - ga je voor één of enkele grote componenten, of net heel vele kleintjes?

De meest geschikte opdeling én granulariteit vinden is niet evident, maar wel sterk bepalend voor heel wat kwalitatieve aspecten rond beheersbaarheid:

  • deployment - ben je in staat je componenten apart te updaten en te deployen?
  • schaalbaarheid - kan je onderdelen van de software apart laten schalen in functie van de noden?
  • ownership - wie beheert welke componenten, welk team is verantwoordelijk voor welke componenten, wie neemt uiteindelijk beslissingen
  • release management - welke afhankelijkheden zijn er tussen componenten en hoe beïnvloeden die elkaars roadmap en kalender?
  • technologie - zijn er redenen om software op te delen in meerder componenten en zo aparte technologieën naast elkaar te kunnen hanteren?

De strategieën die gevolgd kunnen worden om een applicatie op te delen in componenten zijn divers, denk bijvoorbeeld aan:

  • Applicatie-georienteerde opdeling
    Deze aanpak bestaat erin om een applicatie die gebouwd wordt als een apart component te zien, wat vanuit project-insteek logisch lijkt, maar een indeling achterlaat waarbij ownership gedeeld wordt en business capabilities niet altijd vlot herbruikbaar zijn.
  • Data-georienteerde opdeling
    Ook de informatie-structuur kan als basis voor opdeling gebruikt worden - gerelateerde stukken informatie ("orders", "klanten", ...) worden dan in één component ondergebracht, wat zorgt voor een redelijk hoge cohesie.
    Het grootste nadeel is dat wijzigingen aan business requirements meestal niet per entiteit maar per proces gemaakt worden, wat resulteert in impact op vele data-gebaseerde componenten.
  • Proces-georienteerde opdeling
    Deze aanpak wordt te weinig gebruikt, maar er zijn vaak zeer goede resultaten mee te behalen én deze garandeert dan de architectuur van je software gecorreleerd is aan het ownership (elk proces heet immers een process owner),
    en de dynamiek van wijzigingen beperkt ook vaak de aanpassingen tot één business proces en dus ook één component

schema_monoliet-strategisch-opdelen

Je zal niet alleen moeten beslissen op welke basis je je software gaat opdelen, maar ook hoe granulair je wil gaan werken.

Vaak is je legacy software een monolitische applicatie, die als één massief blok - met een soms onduidelijke interne structuur opgebouwd - is, moeilijk of niet te integreren is met andere systemen, en qua onderhoud problematisch kan zijn.
Tegenwoordig is een microservice architectuur populair, een aanpak die kleine services nastreeft die onderling communiceren en events genereren. 

Deze aanpak levert vele voordelen, maar kan soms ook een uitdaging zijn naar beheer en genereert altijd een zekere extra complexiteit naar ontwikkeling, beheer en performance management. Kleinere services zijn dus niet per definitie altijd beter - microservices het gaat erom het juiste evenwicht te vinden voor jouw specifieke situatie.

Een transitie van een monolitische applicatie naar een (micro)services architectuur kan je perfect stapsgewijs en iteratief aanpakken. Zorg altijd dat je functionaliteit ontsloten is via API's, en splits dan delen van de functionaliteit af als een apart component. Voor de aanroepende systemen is de impact beperkt als je er in slaagt om de API stabiel te houden. Alvorens componenten te beginnen opsplitsen is het vaak een goed idee om eerste containerisatie door te voeren, zodat het management van componenten evident wordt. Een monoliet die op een virtual machine draait opdelen in een systeem met een heel aantal virtuele machines is meestal niet zo handig.

schema_monoliet-opdelen

Eens je je (micro)services bepaald hebt, is het belangrijk om te zorgen dat je coherentie in het gehele systeem brengt en het manageable houdt:

  • Documenteer en ontsluit de API's van de verschillende services, gebruik hiervoor een API Gateway
  • Plaats authenticatie & high-level autorisatie uit je services en gebruik technieken als OAuth2 en JWT om security informatie (identiteit, ...) te valideren
  • Pas versionering toe zodat je (micro)service kan evolueren zonder aanroepende services te breken, laat eventueel meerdere naast elkaar draaiende versies toe
  • Voorzie logging en monitoring om aanroepen te traceren en te correleren doorheen je systeem
  • Voorzie degelijke tooling en automatisatie om vlot een groot aantal services te bouwen, beheren én te monitoren
  • Pas je applicatie aan om concepten als circuit-breakers te introduceren, en maak zoveel mogelijk communicatie asynchroon. Werk eventueel met een service mesh (bv: Istio) die heel wat van deze aspecten in regelt. Zo vermijdt je dat je applicatie in feite een gedistribueerde monoliet wordt, met de nadelen van én een monoliet, én een gedistribueerd systeem.

Herbekijk je strategie rond data

De rol van data is in ongeveer elk software systeem geëvolueerd van operationeel noodzakelijk naar strategisch voor je business. Data science, big data, advanced analytics ... heel wat hedendaagse concepten stellen de data die verzameld en verwerkt worden centraal, en plaatsen die zelfs in een leidende rol: beslissingen worden niet enkel meer genomen op basis van business kennis en operationele informatie, maar op basis van analyses van historische gegevens, voorspellingsmodellen, enz...

Als je een applicatie gaat moderniseren dan kan je best ook ineens even stil te staan bij de data in je applicatie en hoe je meer data-gedreven kan gaan werken.  

Meerwaarde uit data 

icoon_rol-meerwaarde-roosGa op zoek naar scenario's waarin je applicatie extra business waarde zou kunnen creëren, of operationele efficiëntie zou kunnen verhogen. Een applicatie die ooit enkel operationele data opsloeg om business transacties uit te voeren, kan een bron worden van inzichten die op zich waarde hebben, of zelfs gecommercialiseerd kunnen worden.

Een mooi voorbeeld is de stad Kortrijk, die van Telecom-operator Proximus geanonimiseerde data aankocht van welke type klanten (leeftijdsgroepen) waar en wanneer aanwezig zijn in de stad - iets wat uiteraard zeer bruikbaar is voor gerichte reclame-doeleinden op de juiste plaats en het juiste moment.

Allicht zal je zelf niet altijd even duidelijke cases voor het grijpen hebben, maar wat inspiratie om op zoek te gaan kan volgende zijn:

  • Vervang evidente en repetitieve menselijke beslissingen door een machine learning model. Applicaties bieden functionaliteiten om binnen geautomatiseerde data-verwerking op gerichte momenten menselijke beoordeling toe te passen. De klassieke "aanvaard" of "weiger" functionaliteit of het routeren van een case naar de juiste volgende persoon voor verdere analyse. Deze functionaliteit situeert zich tussen binnenkomende informatie, en produceert een uitgaande beslissing. Door een machine learning model te trainen kan je vaak een significant deel van de cases automatisch beslissen met een hoge mate van accuraatheid en precisie, wat de operationele werklast een stuk van verlicht en de efficiëntie verhogen

  • Bouw voorspellingsmodellen die interessante indicaties kunnen geven die operationeel bruikbaar zijn - denk bijvoorbeeld aan het voorspellen hoe lang de afhandeling van een taak of dossier gaat duren op basis van historische data.
    Deze feedback naar gebruikers geven - "deze taak wordt typisch in x dagen afgehandeld" kan een functionele meerwaarde zijn.

  • Outlier detectie kan dan weer de basis vormen voor het detecteren van problematische situaties of fraude waar het systeem proactief op kan reageren of waar manuele actie kan gevraagd worden

Data verzamelen

icoon_rol-data-verzamelen-roosAlles begint natuurlijk bij de data die je gaat verzamelen: business data, maar eventueel ook alle wijzigingen die er aan gebeuren, gebruikersgedrag in een applicatie, doorlooptijden, enz.... 

  • Bedenk of je data storage - in vele gevallen een relationele database - nog de beste keuze is voor elk type gegevens die je wil bijhouden, of dat je bijvoorbeeld beter een NoSQL of Graph database inzet
  • Geef de nodige aandacht aan log output en audit trails die niet alleen een interessante bron van informatie zijn in support en troubleshooting, maar vaak ook interessante feiten bevat over het gebruik van de toepassing en gedrag van gebruikers.
  • Herbekijk je architectuur in functie van de load en sizing van de applicatie. Hou je een klassiek database model aan dat je gaat bevragen (CRUD - Create/Read/Update/Delete), of is er een groot verschil in het aantal lees- en shrijfacties en scheid je deze dan beter met technieken zoals CQRS (Command Query Responsibility Segregation) zodat je kost-efficiënter kan schalen naar één van beide kanten toe?
  • Zorg altijd voor een duidelijk data ownership - één component in de architectuur dient de unieke bron rond specifieke informatie te zijn, waar nodig kan data gedupliceerd maar uiteindelijk moet er altijd een single-source-of-truth zijn.
  • Hou tenslotte rekening met wetgeving en regulering - ander andere de GDPR wetgeving bepaalt hoe je moet omgaan met gegevens en gedraging die je van gebruikers bijhoudt. Ook data beveiligingcrypto shredding en aandacht voor mogelijke data lekken zijn cruciaal. 
    Je legacy applicatie stamt mogelijk uit een tijd waar regulering beperkter was, en deze zaken niet evenveel aandacht kregen als vandaag de dag.

Data analyseren

icoon_rol-data-analyseren-roosData gaat niet enkel over het hier en nu, maar ook over lange termijn trends, historische data, die vaak geconsolideerd worden en gekruist met elkaar en externe databronnen.

  • Loopt er rapportering binnen het operationele systeem waar die beter verschoven zou worden naar een aparte rapporteringstool op een data markt met een BI tool?  
  • Zijn er gegevens die niet of weinig gestructureerd zijn, eventueel kan big data tooling een evidentere oplossing beiden dan klassieke ETL (Extraction, Transformation and Load) en relationele modellen?
  • Stel jezelf tenslotte de vraag of heel wat rapporteringsfuncties in je applicatie daar ook werkelijk thuishoren - vaak overstijgen ze het applicatie-niveau en kan rapportering beter buiten de applicatie onderbrengen

Data strategie

icoon_rol-strategie-roosData is zo'n belangrijk item geworden dat je best ook even nadenkt over je strategie daaromtrent, en je applicatie architectuur daarop inricht:

  • Welke inzichten wil je bereiken en welke data heb je daarvoor nodig?
  • Hoe ga je om met testdata? Ga je voor testdoeleinden reële data kopiëren, al dan niet deels anonimiseren en overzetten naar test,- en development omgevingen? Of ga je voor deze doeleinden eigen testdata genereren?
  • Heb je realtime data analyse nodig?  Of volstaat een periodieke rapportering?  
  • Ga je grote volumes aan data in batch verwerking afhandelen? Streaming data technieken kunnen de afhandeling makkelijker maken, of misschien is een lambda-architectuur met een combinatie van een klassieke én snelle data verwerking wel gepast?

Applicatie Modernisering: een stappenplan

Een juiste volgorde in de aanpak van legacy applicaties is cruciaal.  Door voorbereid tewerk te gaan heb je telkens een solide basis om gerichte actie op te ondernemen, en vermijd je lukraak verbeteringen aan te brengen. 
Je kan best in 5 grote stappen te werk gaan:

 

schema_stappenplan

 
 

Stap 1: Verzekeren van continuïteit

illustratie_stap1Start altijd bij het begin: stel jezelf de vraag of je alle nodige informatie en materiaal hebt om de applicatie verder te beheren - en neem de proef op de som. 
Heb je de nodige kennis rond de functionele werking én de technische opzet, kan je de applicatie bouwen en deployen? Breng eventuele onbekenden in kaart brengen en vul deze aan en zorg dat de basics goed zitten alvorens verder te gaan.

Broncode & architectuur

Stel jezelf de belangrijkste vragen:

  • heb je alle broncode van de applicatie?
  • en ook de nodige assets (scripts, datasets, beelden, ...)
  • zit de broncode in een SCM (source control management system - versioneringsysteem) dat wijzigingen traceert, meerdere versies naast elkaar ondersteunt in branching, e.d.?
  • heb je een goed zicht op alle interne en externe integraties en afhankelijkheden van de applicatie?

Onderneem zeker volgende acties:

  • identificeer eventuele gevoelige informatie die in de broncode bekend gemaakt wordt en voorkom dat dit mogelijk beveiligingsrisico in je nieuw vorm van versiebeheer terecht komt door deze te extraheren naar omgevingsvariabelen

  • stop de broncode in een modern SCM (bv: Bitbucket, Gitlab) of vorm bestaande VCS oplossingen zoals (CVS, Subversion of SVN, enz) om tot GIT repositories -  de historiek van een code base hoort net zo waardevol te zijn dan zijn toekomst.
  • kies een branching strategie (bv GitFlow, trunk based, mainline, enz) die parallelle ontwikkeling en support vlot ondersteunt.
  • bepaal een vast bericht formaat dat betekenisvolle historiek op levert in functie van nieuw aangedragen broncode, houdt de veranderingen klein en beschrijf ze duidelijk, idealiter vervoegd met een referentie in een ticketing systeem (bv JIRA, Trello, enz)
  • documenteer alle integraties en afhankelijkheden - componenten waar de werking van de applicatie op steunt
  • verifieer of je alle componenten bij elkaar hebt in het versioneringsysteem

Functionele kennis

Stel jezelf de volgende vragen:

  • ben je in staat om de correcte werking van de toepassing te valideren?  
  • ken je voor elke functionaliteit eventueel de verschillende flows die de applicatie ondersteunt?
  • heb je een opsomming van de business rules, en is voor elke case de verwachtte output bekend?

Onderneem zeker volgende acties:

  • documenteer test scenario's die je kan gebruiken ter validatie van de correcte werking - dit als baseline voor latere aanpassingen
  • vul onbekenden aan door concrete productie-cases te bekijken en de variantie te analyseren, reverse engineer logica door proefondervindelijk diverse cases aan te bieden, analyseer de broncode, enz...
  • bouw een testdata strategie op: kan en mag je met "echte" data uit productie aan de slag gaan, of bouw je best je eigen testdata set op?
  • bouw heldere documentatie op: breng actoren, business rules, use cases, end-to-end processen, informatie-modellen en applicatie functionaliteiten in kaart
  • genereer eventueel documentatie door tools die een database schema in kaart brengen, broncode analyseren, enz...
  • centraliseer alle documentatie op één centrale plaats waar ze ook vlot onderhouden kan worden
  • automatiseer een aantal belangrijke test scenario's zodat je met vertrouwen nieuwe versies van de software kan uitrollen zonder bestaande functionaliteiten te breken

Bouwstappen & deploybaar artefact

Stel jezelf de volgende vragen:

  • kan je effectief een build-from-source doen tot een werkende applicatie?
  • zijn de nodige stappen duidelijk omschreven?
  • zijn er obscure manuele stappen nodig?
  • is er nood aan installatie van veel specifieke afhankelijkheden?

Onderneem zeker volgende acties:

  • introduceer een (geautomatiseerd) build script (Maven, gradle, npm, enz) of vervang verouderde manieren (ANT, bash, manuele reeks van stappen) 
  • introduceer of scherp bestaande belangrijke informatie aan in de vorm van README.md file in de root van elke broncode repository.
  • mik op één enkel simpel cross-platform commando om de verschillende bouwstappen te doorlopen en tot een deploybaar artefact te komen door het gebruik van zinvolle standaardwaarden 
  • verlaag technische frictie en gebruik gebundelde build tools (bv: .mvnw is een gebundelde Maven wrapper waardoor je deze tool niet op het path van je machine geïnstalleerd dient te hebben)
  • voorzie integratie punten in de vorm van Docker containers zoals databases, datastores, statische code analyse tooling, monitoring & tracing tools, enz (kies hierbij niet voor de standaard poorten om conflicten met het host systeem te vermijden).
  • bouw de applicatie vanaf broncode tot een deploybaar artefact (JAR, WAR, docker container image m.b.v. JIB)

Omgevingen en deployment

Stel jezelf de volgende vragen:

  • ben je in staat om nieuwe versies van de applicatie te deployen en functioneel te krijgen?
  • heb je omgevingen buiten productie om de software op te valideren en dingen uit te proberen zonder risico te lopen?
  • is het verschil tussen verschillende omgevingen te injecteren via omgevingsvariabelen of is er per omgeving een ander deploybaar artefact nodig?
  • is alle nodige informatie over de infrastructuur (servers, usernames en passwords, ...) bekend om een volledig deployment te doen?

Onderneem zeker volgende acties:

  • documenteer alle nodige acties om een deployment uit te voeren en automatiseer ze waar mogelijk
  • zorg voor aparte omgevingen voor verschillende doeleindendevelopment, testing, business acceptance en productie.
  • extraheer de nodige variabelen die een omgeving definiëren naar omgevingsvariabelen. houdt hierbij extra rekening met gevoelige data zoals wachtwoorden.
  • deploy de applicatie effectief op alle omgevingen inclusief productie, zodat je zeker bent van de baseline waarvan je vertrekt

Stap 2: Beheersbaar maken

Je applicatie kunnen builden, deployen en valideren is alvast een start, maar garandeert nog geenszins een efficiënte verdere ontwikkeling. De volgende stap is om zowel de applicatie als de processen errond zo inrichten dat aanpassingen zeer vlot en precies kunnen worden gemaakt en uitgerold.

illustratie_stap2

Zolang geen vlotte CI/CD (Continuous Integration/Continuous Deployment) pipeline is, zijn verdere grote aanpassingen niet aangewezen omdat ze minstens inefficiënt en meestal ook weinig kwalitatief zullen kunnen gebeuren.

Daarnaast geeft een geautomatiseerde ontwikkelstraat en een vlot aanpasbare codebase ook vertrouwen aan een team om effectief wijzigingen aan te brengen.

Een beheersbare applicatie

  • Koppel je applicatie los van z'n infrastructuur en zorg dat die vlot in elke omgeving kan geplaatst worden - containerisatie is hier zeker een mogelijkheid - al start je met de volledige toepassing in één enkele container 
  • Maak je applicatie verder omgevingsonafhankelijk configureerbaar (breng parameters binnen vanuit de omgeving)
  • Maak je applicatie beheerbaar en traceerbaar maken - zorg dat fouten en problemen gelogd of duidelijk gemeld en opgevolgd worden
  • Overweeg rehosting en replatforming naar een cloud provider om vlot met infrastructuur en wijzigingen daaraan om te kunnen gaan - container images als deploybaar artefact geven je hier een stapje voor gezien elke cloud provider hier passende diensten voor aanlevert.
  • Vervang self-managed services zoals een applicatie-server, database, zoekmotor, e.d. door high-level managed services (bv: PaaS, managed database) om je te kunnen focussen op de applicatie zelf.

De juiste organisatie

  • Zet een performante CI/CD ontwikkelstraat op die zo geautomatiseerd en optimaal mogelijk de applicatie bouwt, test en deployed naar alle omgevingen
  • Automatiseer het bouwen, testen en deployen van de applicatie volledig
  • Breng een operationeel team aan de gang zodat je ontwikkelploeg volledig kan werken op de vernieuwing
  • Scheid duidelijk alle build en run activiteiten van elkaar af: de ontwikkelploeg werkt op build-omgevingen (typisch dev en test) en mensen met operationele rol beheren de run omgevingen (productie en acceptatie)

Stap 3: Het probleem isoleren

Als je aanpassingen aan een applicatie gaat doen is het belangrijk om te weten dat je dit kan vrij autonoom kan doen, zonder planningen en integraties in detail te moeten afspreken met elk ander systeem waarmee geïntegreerd wordt.

illustratie_stap3

Je wil de levenscyclus van je applicatie uiteraard zo onafhankelijk mogelijk kunnen bepalen, dus moet je de interne werking van je applicatie zo goed mogelijk gaan isoleren van de rest van je IT-landschap, zodat je met een gerust hart kan gaan refactoren en rearchitecten zonder impact op end-to-end processen en integraties met andere applicaties.

Je zal dus een duidelijk contract met de andere systemen moeten opstellen, waarin bepaald wordt wat je van elkaar mag verwachten. De meest beheersbare werkwijze hiervoor is om een API (Application Programming Interface) te definiëren. Zolang beide systemen deze respecteren kan je onafhankelijk van elkaar evolueren volgens eigen tijdslijn.

Integratie-punten als risico

In praktijk zal je legacy applicatie allicht nog niet voldoen aan dit ideaalbeeld door:

  • ongedocumenteerde of fragiele ad-hoc API's (bv: eigen protocollen die nauw verweven zijn met de data-structuren in je applicatie, enz...)
  • database integraties, die het database model als een gemeenschappelijk integratie-punt hanteren, wat het onmogelijk maakt om daar aanpassingen aan te doen zonder de integratie te breken
  • file integraties, die bestanden in een bepaalde locatie, structuur en vorm hanteren als integratie-punt

Beheerbare integraties

  • documenteer alle integratie-punten en API's zodat duidelijk is waar er mogelijke impact van en naar andere systemen kan zijn bij wijzigingen
  • voorzie bij voorkeur geautomatiseerde testen om de integriteit van deze punten af te toetsen bij wijzigingen
  • waar mogelijk kan je integraties ook afsnijden en herbouwen op een meer beheerbare manier (REST API, ...)

Stap 4: Architectuur verbeteren

Eens de applicatie vlot kan aangepast en door getest worden, zonder onverwachte neveneffecten voor andere systemen, kan je met een gerust hart de noodzakelijke architecturale aanpassingen doen. Dit is dan een "interne" oefening van de applicatie geworden, waarbij je die in een aantal behapbare stapjes gaat aanpassen richting de situatie zoals je die voor ogen hebt.

illustratie_stap4

Welke acties net nodig of nuttig zijn moet je echt voor elke specifieke situatie bekijken, maar de lijst van rearchitecting-ideeën kan alvast een goed begin zijn. Hoe ver je hier in gaat en welke acties welke prioriteit krijgen zal je ook moeten bepalen, in functie van urgentie van de problematiek, verwachtte meerwaarde en nodige investering.

 

Stap 5: Routine van onderhoud & evolutie opstarten

Eens de applicatie bijgewerkt begint te geraken, is het belangrijk dat je een routine maakt van onderhoud en evolutie. De investering die je op de codebase, kennis en procedures deed rendeert pas als je het eindresultaat onderhoudt.
Door op regelmatige basis nieuwe versies- zelfs met weinig wijzigingen - door de ontwikkelstraat te brengen én te releasen blijft de applicatie bekend terrein en het maken van aanpassingen een operationele realiteit.

illustratie_stap5

Enerzijds garandeert dat er een zekere parate kennis wordt onderhouden. Zelfs als er geen grote wijzigingen op de planning staan is het meer dan nuttig om op regelmatige basis te werken met de applicatie, ed codebase en het build-en-deploy proces. Het alternatief is verloren kennis en vertrouwen, en een moeilijke herstart op een moment dat het echt nodig is én er al weer een achterstand is opgebouwd.

Anderzijds incentiveert een routinematige release kalender ook om proactief onderhoud te doen, upgrades van libraries, depreciation en uiteindelijk uitfaseren van oude functionaliteiten en integratie-punten, enz...

 

Vermijden van nieuwe legacy

Digitale erosie is onvermijdelijk.  Ondanks enkele decennia historiek is software engineering een nog zeer volatiele discipline, waar amper industrie-consensus gevonden wordt rond technologieën, architecturen, best practices en oplossingspatronen, en waar deze ook nog eens in sneltempo blijven evolueren. Oplossingen die vandaag worden uitgetekend zijn op korte termijn niet meer de best beschikbare keuze en op langere termijn al snel verouderd.

Als je je software én je ontwikkelproces fit wil houden, zal je deze drie belangrijke factoren goed in de gaten moeten houden:

  1. kennis en support - ken je het systeem nog voldoende om impact in te schatten en wijzigingsplannen te maken die verder gaan dan een "quick fix"?
    • dit is de basis voor inschatten van impact en het maken van wijzigingsplannen - je kan niet werken met wat je niet begrijpt
    • zorg voor kennisborging: actief beheren van kennis, documenteren, opleiden, onderhouden, enz...
    • zorg voor het up-to-date houden van systemen, libraries, e.d. met gesupporteerde versies zodat je niet gaat achterlopen

  2. evolueerbaarheid - ben je in staat in vertrouwen aanpassingen en nieuwe integraties te blijven maken, alsof je nog in de bouwfase voor go-live zat?
    • hou technical debt op de radar houden en werk die effectief weg (door middel van refactorings, upgrades, migraties, ...)
    • hou een routine aan van (eventueel kleine) wijzigingen en deploys 

  3. efficiëntie - kan je uitbating én aanpassingen aan de applicatie op een operationeel én financieel te verantwoorden manier doen? 

    • stel jezelf de vraag: wat zouden we anders doen als we NU als opnieuw moesten beginnen, en hoe ver zitten we ondertussen van deze situatie af?

    • zijn er nieuwe tools, frameworks, platformen die nu betere keuze lijken?

    • automatiseer alles wat je kan - van het bouwen en deployen tot testen van software - automatisatie minimaliseert operationele kost en reduceert de kans op menselijke fouten

 

Je hebt ondertussen al gezien dat deze 3 criteria zonder actieve aanpak enkel maar kunnen dalen over de tijd. Regelmatig de situatie (her)evalueren en de nodige acties ondernemen is dus nodig - én houdt de kennis van het systeem warm in je team.

Uiteraard dient zich hier de realiteit aan dat een software-systeem dus niet enkel een investeringskost voor de bouw of configuratie heeft, en een operationele kost om het uit te baten, maar ook een concrete onderhoudsactiviteit vereist die verder gaat dan reactieve bugfixing en kleine wijzigingsaanvragen. Maak routine van onderhoud waarbij je je bestaande situatie regelmatig tegenover de huidige norm legt, en op de noodzakelijke punten bijbeent - daarmee hou je ineens je kennis op peil houdt en verifiëer je de onderhoudbaarheid van het systeem.

Misschien is de belangrijkste conclusie nog wel: zodra je stopt met actief beheer en optimalisatie van je software, zet de erosie in en ga je langzaam maar zeker het legacy pad op.

Net als  een wagen waar je geen regelmatig onderhoud en controle op uitvoert uiteindelijk ook wel zal stoppen met rijden, al kan dat een tijdje duren en kan je op voorhand het finale probleem niet exact voorspellen.

 

Conclusie

Legacy applicaties moderniseren is niet voor niets een steeds belangrijker wordende IT activiteit in een wereld waarin de levensduur van een typische applicatie in praktijk vaak veel langer blijkt dan bij aanvang verondersteld werd, waar legacy applicaties geïntegreerd zijn in een business én IT-landschap dat complexer is dan ooit, en waar een complete vervanging van dergelijke systemen onrealistisch complex, duur en risicovol geworden is.  

illustratie_conclusie

 

Stapsgewijs aanpassingen maken om je software, je team en je processen fit te houden, reduceert risico, spreidt budgettaire inspanningen over de tijd en zorgt ervoor dat je op elk moment het best in staat bent om je software vlot met een wijzigende business te laten mee-evolueren.

Boeken

Rond de aangehaalde onderwerpen zijn volgende boeken volgens ons zeker het lezen waard:

refactoring-book-cover

 

building-microservices-book-cover

 

continuous-delivery-book-cover

 

978-0134757599
Refactoring: Improving the Design of Existing Code
(2nd Edition)

978-1491950357
Building Microservices: Designing Fine-Grained Systems

978-0321601919
Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation

Martin Fowler weet als toonaangevende stem in onze industrie als geen ander de technieken rond refactoring vorm te geven

Sam Newman toonde al vroeg interesse in wat volgens hem een antwoord kon bieden op de problematiek die omtrent onbeheersbare monolitische applicaties kan ontstaan.

Voor velen nog een stap die te nemen valt, toch valt er veel te zeggen voor een omgeving waarin het vanzelfsprekend is dat er op elk moment, zelfs meerdere keren per dag deployed kan worden op een productie omgeving.

Application Modernization is niet voor niets een steeds belangrijker wordende IT activiteit in een wereld waarin de levensduur van een typische applicatie in praktijk vaak veel langer blijkt dan bij aanvang verondersteld werd, waar legacy applicaties geïntegreerd zijn in een business én IT-landschap dat complexer is dan ooit, en waar een complete vervanging van dergelijke systemen onrealistisch complex, duur en risicovol geworden is.  

Stapsgewijs aanpassingen maken om je software, je team en je processen fit te houden, reduceert risico, spreidt budgettaire inspanningen over de tijd en zorgt ervoor dat je op elk moment het best in staat bent om je software vlot met een wijzigende business te laten mee-evolueren.

New call-to-action