Te vaak wordt bij modernisatie van softwareapplicaties niet goed gekeken naar de technische staat van de huidige applicatie. Techneuten vinden al snel dat het helemaal opnieuw moet, terwijl de business geen geld wil verspillen aan technische mooimakerij. Een analyse van de ‘technical debt’ helpt dan om de discussie op het juiste niveau te voeren.
Met het groeiend aantal softwareapplicaties in organisaties, groeit ook het aantal applicaties dat al langer meegaat. Er kunnen diverse redenen zijn om te besluiten een bestaande applicatie te moderniseren. Soms is de directe aanleiding een verouderd of niet meer ondersteund onderliggend platform. Andere applicaties kunnen niet meer voldoende mee in de veranderende behoeften. De keuze voor een strategie voor modernisering hangt in grote mate van af van wat de aanleiding is.
Een strategie kan gericht zijn op een volledig nieuw ontwerp, een zogenaamd grand re-design, maar ook op een puur technische migratie met zoveel mogelijk hergebruik van bestaande investeringen. Grand re-design is een relatief dure oplossing, zonder garantie op succes. Daarentegen brengt het behoud van bestaande investeringen meestal met zich mee dat veel van de bestaande problemen ook worden behouden. Het is daarom belangrijk eerst een goed beeld te hebben van de huidige staat van de applicatie en welke problemen precies opgelost moeten worden door het modernisatieproject.
Technical debt
Technical debt is een metafoor die helpt om over de gevolgen van technische problemen te praten zonder te verzanden in de technische details. Technical debt treedt op als er, al dan niet bewust, voor een oplossing wordt gekozen die op de korte termijn voordelig is (of lijkt) en gelijktijdig op de langere termijn extra kosten met zich meebrengt. Deze technical debt kan worden vergeleken met financiële schuld in de zin dat er kosten naar de toekomst worden doorgeschoven. Zolang de kortetermijnoplossing niet wordt omgezet in een structurele oplossing brengt dit diverse, vaak verborgen kosten met zich mee. Relatief eenvoudige aanpassingen blijken ineens veel meer tijd te kosten, er treden onverwacht veel fouten op en nieuwe ontwikkelaars hebben meer tijd nodig om zich de applicatie eigen te maken. Deze verborgen kosten kunnen worden gezien als de rente die men betaalt voor het hebben van de schuld. Om de schuld in te lossen moet de kortetermijnoplossing worden omgezet in een structurele oplossing.
Technical debt is evenals een financiële schuld niet per definitie slecht. Er zijn situaties waarin bijvoorbeeld een deadline belangrijk genoeg is om een schuld te accepteren als die deadline daardoor kan worden gehaald. Net als bij een financiële schuld kun je afwegen of de totale kosten van de schuld, de rente plus de aflossing, opwegen tegen de baten van het halen van de deadline. De randvoorwaarde is dan wel dat de lasten van de nieuwe schuld, in combinatie met die van eventueel eerder opgedane schuld, gedragen kunnen worden. Op dezelfde manier kan ervoor worden gekozen een al bestaande schuld voor langere tijd te laten bestaan. Bijvoorbeeld omdat het een onderdeel betreft waar relatief weinig onderhoud op wordt gepleegd en waarvoor de rente dus laag is ten opzichte van de kosten voor het aflossen. Het is belangrijk dat deze keuze bewust en weloverwogen gemaakt wordt.
Behoud van technical debt bij applicatiemodernisatie
Technical debt kan zich op verschillende niveaus bevinden. Hierbij valt te denken aan onduidelijke namen voor variabelen, gedupliceerde code, het niet voldoen aan codeerstandaarden, onoverzichtelijke codestructuren, een slecht genormaliseerd datamodel of het niet volgen van een passende applicatiearchitectuur. Afhankelijk van het type en de hoeveelheid technical debt dat aanwezig is zijn verschillende strategieën tot applicatiemodernisatie meer of minder geschikt om deze technical debt aan te pakken.
Bij een sterk geautomatiseerde modernisatie is er een grote kans dat veel van de bestaande technical debt behouden blijft. Tools die bijvoorbeeld code vertalen van de ene naar de andere programmeertaal, laten doorgaans de structuur in de basis ongewijzigd. Hier geldt dan ook het principe ‘garbage in, garbage out’. De kans is zelfs groot dat er nieuwe problemen bijkomen. De code voldoet bijvoorbeeld niet aan de gangbare standaarden voor het doelplatform. Daardoor kunnen ontwikkelaars die ervaring hebben met het doelplatform de code moeilijk lezen. Het resultaat is vergelijkbaar met een Google-translate vertaling van het Nederlands naar het Engels; het is voor een Engelstalig persoon met enige moeite wel min of meer te begrijpen, maar het lijkt niet op iets wat een ‘native speaker’ zelf geschreven zou hebben. Ook de voordelen van de nieuwe omgeving worden doorgaans niet optimaal benut. Na de migratie kunnen de nieuwe mogelijkheden van het doelplatform wel alsnog worden gebruikt. Veel moderne ontwikkelomgevingen beschikken over tools die kunnen helpen om een deel van de technical debt na de migratie alsnog weg te werken.
Een andere veel toegepaste strategie is het één-op-één herbouwen van de bestaande applicatie in nieuwe technologie. Meestal moet dit, bij ontbreken van een up-to-date functioneel ontwerp, gedaan worden op basis van alleen de broncode. Bij deze strategie is het wel mogelijk een groot deel van de technical debt op code en soms zelfs architectuurniveau weg te werken. Ook kunnen de specifieke voordelen van het nieuwe platform beter benut worden. Net als bij gebruik van een migratietool is er bij één-op-één herbouw wel nog steeds een reëel risico dat technical debt uit de oude code doorsijpelt naar de nieuwe code. Ontwikkelaars moeten ‘aannemen’ dat het huidige gedrag dat zij aflezen uit de code ook het gewenste gedrag is. Vooral als er al veel technical debt is, is het lezen van de oude code erg lastig waardoor het moeilijk is de bedoeling te ontrafelen. Slecht onderhouden code heeft bijvoorbeeld vaak ‘bijzonder’ gedrag in situaties die in de praktijk nooit voorkomen. Als dit gedrag één-op-één herbouwd wordt 'omdat dat de opdracht was', dan leidt dit weer tot onnodig complexe code. In veel gevallen is het bijzondere gedrag echter helemaal niet het gewenste gedrag, maar een gevolg van eerder opgelopen technical debt. In het ergste geval worden bugs bewust opnieuw ingebouwd of worden complete features, die al enige tijd niet meer gebruikt werden, toch opnieuw gebouwd.
Voorkom verrassingen achteraf
Een technical debt is zoals gezegd niet per definitie slecht. Het is daarom ook niet per definitie slecht dat (een deel van) de bestaande technical debt na een modernisatieproject nog steeds terug te vinden is in de nieuwe applicatie. Het is natuurlijk wel prettig als dat een weloverwogen keuze is. Het komt helaas te vaak voor dat de resterende technical debt als een vervelende verassing achteraf komt, omdat verondersteld werd dat met de modernisatie ‘alle problemen zouden worden opgelost’.
Om een goede keuze te maken voor de modernisatieaanpak, is het belangrijk eerst een duidelijk beeld te hebben van wat er precies gemoderniseerd moet worden. Daarom is het raadzaam eerst goed in kaart te brengen welke technical debt er in de huidige applicatie aanwezig is. Vervolgens kan besloten worden welk deel daarvan als onderdeel van de modernisatie aangepakt moet worden. De te kiezen strategie, variërend van ‘grand re-design’ tot ‘geautomatiseerde conversie’ kan daar dan op worden afgestemd. Resterende technical debt kan alsnog kort na het modernisatieproject worden opgepakt of, zoals men gewend was, uitgesteld worden tot ‘een geschikt moment in de toekomst’.