Technische samenvatting
Kernpunten:

Het artikel geeft aan dat refactoring van een industriële applicatie zinvol is wanneer de kosten en onzekerheid van kleine wijzigingen sneller toenemen dan hun bedrijfswaarde. Essentieel is het onderscheid tussen het opschonen van de structuur en een technische wijziging die invloed heeft op het proces of de veiligheid.

  • Het refactoren van een oude applicatie raakt niet alleen de codekwaliteit, maar ook de continuïteit van de productie, de kosten en de verantwoordelijkheid.
  • Het risico neemt toe wanneer een wijziging gevolgen heeft voor signalen, toestanden, de volgorde van handelingen of de overgangsvoorwaarden van het proces.
  • Ogenschijnlijk technische wijzigingen kunnen invloed hebben op de start-, stop- en foutresetfuncties, en op de reactie bij spanningsuitval en verlies van communicatie.
  • Als de sequenties of reacties van beveiligingscircuits opnieuw moeten worden gevalideerd, is er geen sprake meer van gewoon codeonderhoud.
  • Veilige refactoring vereist dat de reikwijdte van de wijziging, de acceptatiecriteria en de risicobeoordeling voor het proces worden vastgesteld.

Waarom dit onderwerp vandaag relevant is

Refactoring van een oude industriële applicatie is allang geen kwestie meer van code-esthetiek of onderhoudsgemak. Tegenwoordig is het een beslissing over de continuïteit van de productie, de voorspelbaarheid van kosten en de omvang van de verantwoordelijkheid aan de kant van de systeemeigenaar. In veel fabrieken zijn besturingsapplicaties, hulpmiddelen voor operators en communicatielagen jarenlang ontwikkeld zonder één samenhangende architectuur, vaak rond apparaten, bibliotheken en integratiemechanismen waarvan de ondersteuning beperkt is of al is beëindigd. Zo’n situatie kan een tijdlang acceptabel lijken, maar slechts totdat elke volgende wijziging meer gaat kosten dan de functionaliteit die ermee moet worden geleverd. Dan is de vraag niet meer of de oude applicatie moet worden aangepakt, maar of de organisatie het gedrag ervan onder productieomstandigheden nog wel beheerst.

Het belang van dit onderwerp komt voort uit het feit dat technische schuld in industriële systemen zeer snel overgaat in operationele schuld. Als een applicatie moeilijk reproduceerbaar is, afhankelijk is van individuele personen, geen betrouwbare regressietests heeft of als de logica productiefuncties vermengt met functies voor veiligheid en diagnose, dan zal elk incident duurder uitpakken dan een vergelijkbaar probleem in een kantoorsysteem. Het gevolg is niet alleen stilstand. Daar komen de arbeidskosten van de technische dienst bij, het risico van onjuiste workarounds onder tijdsdruk, problemen om na een wijziging aan te tonen dat zorgvuldig is gehandeld, en de moeilijkheid om te onderscheiden wat al een bestaande storing was en wat het gevolg is van een ingreep door het projectteam. Voor een manager en product owner is het praktische criterium eenvoudig: als de tijd en onzekerheid rond de implementatie van kleine wijzigingen sneller toenemen dan hun bedrijfswaarde, dan is de applicatie in een toestand beland waarin de beslissing over refactoring bewust moet worden genomen en niet moet worden uitgesteld tot de eerste kritieke storing.

De meeste fouten ontstaan wanneer refactoring wordt behandeld als een modernisering “zonder invloed op het proces”, terwijl in werkelijkheid de manier verandert waarop het systeem beslissingen neemt. In de praktijk is een ogenschijnlijk kleine ingreep al voldoende: vervanging van een communicatiecomponent, herstructurering van de taakplanning, wijziging van de bufferlogica voor sensorgegevens of het opschonen van de opstartvolgorde na een herstart. Op papier zijn dat technische opruimwerkzaamheden. Op de werkvloer kunnen ze echter het moment van signaalafgifte veranderen, de volgorde waarin vergrendelingen worden vrijgegeven, de reactie bij verlies van communicatie of het gedrag van de applicatie na spanningsuitval. Juist hier gaat het onderwerp refactoring over in een praktische beoordeling van het wijzigingsrisico volgens ISO 12100: het gaat er niet om of de code “beter” is, maar of de machine, lijn of werkpost zich na de wijziging nog steeds voorspelbaar gedraagt in normale situaties, bij verstoringen en na een herstart.

Een goede toets voor de volwassenheid van de beslissing is nagaan of het team de grens kan aangeven tussen een wijziging in de interne structuur van de applicatie en een wijziging van een functie die van belang is voor het proces of de veiligheid. Als die grens niet kan worden beschreven op het niveau van signalen, toestanden en overgangsvoorwaarden, dan is het project risicovol, ongeacht de kwaliteit van de uitvoerder. In een industriële omgeving zijn vooral situaties gevoelig waarin de applicatie deelneemt aan de volgorde van starten, stoppen, foutreset, alarmbevestiging of samenwerkt met systemen voor energieafschakeling en vergrendelingen. Op dat moment gaat het niet meer alleen om de softwarearchitectuur, maar ook om beveiliging tegen onverwacht opstarten en om de vraag of de analyse ook de elektrische installatie, de besturingslogica en de afhankelijkheden tussen apparaten omvat. Dat is precies het punt waarop ogenschijnlijk lokale refactoring ophoudt een IT-taak te zijn en een technische wijziging wordt die een volledig besluitvormingsregime vereist.

De verwijzing naar normatieve eisen krijgt hier pas in dit stadium betekenis, omdat normen een ontwerpbeslissing niet vervangen, maar wel de reikwijdte ervan ordenen. Als een wijziging invloed kan hebben op de voorwaarden voor opstarten, stoppen, herstel van de werking na een verstoring of op beschermende maatregelen, dan moet die worden beoordeeld als een risicowijziging en niet als regulier codeonderhoud. Als de ingreep de logica raakt die samenwerkt met energieafschakeling, vergrendelingen of de volgorde voor veilige toegang, dan komt vanzelf ook het gebied van eisen rond beveiliging tegen onverwacht opstarten in beeld. Vanuit het oogpunt van verantwoordelijkheid is daarom niet zozeer de vraag “wel of niet refactoren” het belangrijkst, maar of de organisatie kan aantonen dat zij de grenzen van de wijziging kent, acceptatiecriteria heeft die zijn gebaseerd op het gedrag van het proces, en in staat is systeemopschoning te onderscheiden van een aanpassing die een volledige risicobeoordeling en afstemming met het ontwerp van de installatie en tests op locatie vereist.

Waar de kosten of het risico het vaakst toenemen

De grootste kostenstijging bij het refactoren van een oude industriële applicatie komt zelden voort uit de code zelf. De oorzaak is meestal een verkeerde kwalificatie van de wijziging: het team behandelt die als het opschonen van de programmastructuur, terwijl in werkelijkheid het gedrag van het systeem in de tijd verandert, de volgorde van handelingen wijzigt of de voorwaarden voor overgangen tussen toestanden worden aangepast. In een productieomgeving heeft zo’n vergissing directe gevolgen voor het project. De planning sluit dan niet meer aan op de werkelijke scope, tests worden opgezet voor IT-functionaliteit in plaats van voor het procesverloop, en de verantwoordelijkheid voor het resultaat vervaagt tussen technisch onderhoud, automatisering en de softwareleverancier. Het praktische criterium is hier eenvoudig: als na de wijziging de volgorde van opstarten, stoppen, hervatten na een verstoring of de reactie op signalen uit beveiligingscircuits opnieuw moet worden bevestigd, dan is er organisatorisch gezien geen sprake meer van “veilige refactoring”, maar van een wijziging die risico’s voor de productie kan veroorzaken en een andere goedkeuringsprocedure kan vereisen.

Een tweede typisch gebied waar de kosten oplopen, is een ontwerpbeslissing die wordt genomen zonder volledig beeld van de onderlinge afhankelijkheden. Oude industriële applicaties zijn vaak verweven met de configuratie van de besturing, actuatoren, visualisatie, data-archivering en bedieningsprocedures. In de documentatie lijkt dit één systeem, maar in de praktijk gaat het om lagen die jarenlang door verschillende teams zijn ontwikkeld. Refactoring die de leesbaarheid van de code moet verbeteren of verder onderhoud moet vergemakkelijken, kan ongemerkt de betekenis veranderen van vertragingen, vergrendelingsvoorwaarden, standaardwaarden na een herstart of de manier waarop een communicatiefout wordt afgehandeld. Het gevolg is dan niet alleen een technische correctie, maar ook de kost van stilstand, extra proeven op locatie en discussies over de vraag of het gebrek al eerder bestond of door de wijziging is ontstaan. Daarom is het zinvol om vóór de beslissing niet alleen de omvang van de aanpassing te beoordelen, maar ook het aantal en de kriticiteit van de raakvlakken: hoeveel signalen, recepten, bedrijfsmodi en operationele workarounds zijn afhankelijk van het codefragment dat moet worden herbouwd. Hoe meer van zulke raakvlakken er zijn, hoe minder zinvol refactoring “er even bij” is.

In de praktijk zijn vooral projecten kostbaar waarbij het team de werkelijke eisen pas tijdens de inbedrijfstelling ontdekt. Een typisch voorbeeld is de herbouw van een sequentiemodule die volgens de beschrijving “hetzelfde doet, alleen netter”. Na implementatie blijkt echter dat de vorige versie niet-gedocumenteerde gedragingen bevatte die onvolkomenheden van de installatie compenseerden: een korte signaalhandhaving, tolerantie voor een vertraagde sensor, een specifieke volgorde voor het resetten van een alarm of een voorwaarde waarvan de servicetoegang afhangt. In de code zag dat eruit als een fout of technische schuld, maar voor het proces was het een stabiliserend element. Als refactoring zulke mechanismen verwijdert zonder hun functie te herkennen, ontstaan de kosten direct: het aantal interventies na de opstart neemt toe, de acceptatietijd loopt op en de logica moet onder druk van de bedrijfsvoering worden hersteld. Daarom moet de zin van refactoring ook worden beoordeeld op basis van de mogelijkheid om het gedrag van het huidige systeem te reproduceren. Als de organisatie geen gebeurtenissenregistratie, betrouwbare beschrijvingen van bedrijfsmodi en op het werkelijke proces gebaseerde testscenario’s heeft, moet eerst die basis voor beoordeling worden opgebouwd en pas daarna een beslissing over herbouw worden genomen.

Dit loopt rechtstreeks over in een praktische risicobeoordeling van de wijziging volgens ISO 12100 wanneer de aanpassing invloed heeft op beveiligingsfuncties, sequenties voor veilige toegang, de aansturing van bewegende actuatoren of het gedrag van de installatie bij spanningsuitval en spanningsherstel. Binnen zo’n scope beperkt de kost van een fout zich niet tot programmeercorrecties, omdat ook de verantwoordelijkheid voor het vrijgeven van de wijziging voor gebruik aan de orde komt. Als de applicatie samenwerkt met hydraulische systemen, pneumatische systemen of oplossingen zoals tweehandsbediening, wordt de grens tussen refactoring en een technische wijziging nog smaller en moet worden nagegaan of de ontwerpuitgangspunten van de beschermingsmaatregelen niet zijn aangetast. Juist hier is het terecht om terug te grijpen op gestructureerde methoden voor risicobeoordeling, waaronder de benadering die in de praktijk wordt toegepast op basis van ISO/TR 14121-2, en bij hydraulische systemen ook op de ontwerpeisen die worden geordend door NEN-EN-ISO ISO 4413. Het gaat niet om formalisme om het formalisme, maar om een eenvoudig beslisprincipe: als de wijziging invloed kan hebben op de veiligheid van het proces of van de bediening, dan moeten de kosten ervan worden berekend inclusief validatie, tests op locatie en het verantwoordelijkheidsregime, en niet uitsluitend op basis van de werktijd van de programmeur.

Hoe pak je dit in de praktijk aan

In de praktijk wordt de zin van refactoring van een oude industriële applicatie niet beoordeeld op de technologische aantrekkelijkheid van de wijziging, maar op de vraag of het mogelijk is om tegelijk het operationele risico te verlagen en de regie over de implementatie te behouden. Voor de manager en de product owner betekent dit een eenvoudige verschuiving van perspectief: de vraag is niet of het de moeite loont om de code “op te schonen”, maar of de huidige staat van de applicatie het onderhoud, testen, oplossen van storingen of het doorvoeren van volgende wijzigingen conform de eisen daadwerkelijk belemmert. Als het antwoord daarop ja is, heeft refactoring zin, maar alleen in een omvang die los van de productie kan worden uitgevoerd en op basis van meetbare effecten kan worden afgerekend. Een goed besliscriterium is hier de vergelijking van twee kostenposten: de kosten van het laten voortbestaan van de applicatie in de huidige staat, inclusief stilstand, diagnosetijd, afhankelijkheid van individuele personen en het risico van een foutieve wijziging, en de kosten van een gecontroleerde herbouw inclusief tests, validatie en inbedrijfstelling. Zonder zo’n vergelijking loopt het project meestal uit de hand, omdat het team het opschonen van de code financiert uit een budget dat voor functionaliteit bedoeld is, terwijl de verantwoordelijkheid voor de gevolgen op de installatie onduidelijk blijft.

Daarom zou de eerste beslissing niet “we herschrijven” of “we laten het staan” moeten zijn, maar het afbakenen van de wijziging. In een volwassen aanpak wordt het deel dat uitsluitend de softwarestructuur betreft, gescheiden van het deel dat invloed heeft op de proceslogica, opstart- en stopsequenties, bedrijfsmodi, communicatie met aandrijvingen en het gedrag na een verstoring van de voeding. Dat onderscheid heeft directe gevolgen voor kosten en organisatie. Een wijziging die beperkt blijft tot de laag waarin de code wordt geordend, kan in een kortere cyclus worden uitgevoerd en met minder betrokkenheid van de technische dienst. Een wijziging die het gedrag van de machine of lijn raakt, vereist daarentegen een testplan op de installatie, een servicevenster, een rollbackprocedure en een eenduidige aanwijzing van wie de vrijgave voor ingebruikname goedkeurt. Daarbij is het zinvol om niet alleen de tijd voor de programmeerwerkzaamheden te meten, maar ook de tijd die nodig is om het systeem na een mislukte poging te herstellen, het aantal gebieden dat onder regressietests valt en de tijd die nodig is om een afwijking na de opstart te diagnosticeren. Dat zijn indicatoren die laten zien of refactoring het projectrisico daadwerkelijk verlaagt, en niet alleen het werkcomfort van het ontwikkelteam verbetert.

Een praktisch voorbeeld is typerend voor oudere besturingsapplicaties: de code bevat veelvuldig gekopieerde fragmenten voor bewegingsvergrendelingen, alarmafhandeling en overgangen tussen handmatige en automatische modus. Het team wil die uniformeren, omdat de huidige opzet verdere ontwikkeling belemmert en tot verschillen tussen werkplekken leidt. Zo’n beslissing is pas zinvol nadat is gecontroleerd of die uniformering de voorwaarden waaronder een actuator toestemming krijgt om te bewegen niet verandert, en of na een herstart van de controller geen andere volgorde voor het herstellen van de toestand ontstaat. Als de applicatie ook kleppen, aandrijvingen of systemen met opgeslagen energie aanstuurt, kan zelfs een ogenschijnlijk “interne” refactoring overgaan in het domein van de risicobeoordeling van de wijziging en een analyse van de beveiliging tegen onverwacht opstarten vereisen. In zo’n geval bestaat een verstandige werkwijze uit gefaseerde refactoring: eerst het gedrag reproduceren in een testomgeving, daarna modules afscheiden zonder de logica te wijzigen, en vervolgens verificatie op de installatie met een voorbereid terugvalscenario. Dat beperkt de operationele verantwoordelijkheid en maakt het mogelijk de implementatie te stoppen voordat het probleem gevolgen heeft voor de productie.

Pas in dit stadium is een normatieve verwijzing nodig, omdat normen een technische beslissing niet vervangen, maar wel ordenen wanneer een wijziging ophoudt uitsluitend programmeerwerk te zijn. Als refactoring invloed heeft op beschermingsmaatregelen, voorwaarden voor veilige toegang, energieafschakeling of het gedrag van systemen na stilstand en herstart, valt dit vanzelf binnen de praktische beoordeling van wijzigingsrisico’s, op een gestructureerde manier uitgevoerd, ook met gebruik van de benadering die bekend is uit ISO/TR 14121-2. Wanneer er risico op onverwacht opstarten ontstaat, moet niet alleen de code zelf worden gecontroleerd, maar ook de logica voor het afschakelen en herstellen van energie, wat rechtstreeks leidt naar vraagstukken die met ISO 14118 worden geassocieerd. Als de applicatie bovendien gekoppeld is aan hydrauliek of pneumatiek, mag de beoordeling de ontwerpuitgangspunten van die systemen niet buiten beschouwing laten, omdat een foutieve besturingssequentie hun veilige werking kan aantasten, ongeacht of het programma zelf correct is; in dat geval is het ook gerechtvaardigd om terug te grijpen op eisen die het ontwerp van hydraulische systemen structureren. In de praktijk betekent dit één ding: niet de elegantie van de oplossing bepaalt de omvang van de refactoring, maar de grens van de verantwoordelijkheid voor het veilige gedrag van de installatie na de wijziging.

Waar u bij de implementatie op moet letten

De implementatie van refactoring van een oude industriële applicatie is het moment waarop zelfs een juiste architectuurbeslissing kan uitgroeien tot een operationeel probleem. De zin van het hele traject houdt op waar de wijziging de code wel verbetert, maar de voorspelbaarheid van de installatie verslechtert of de verantwoordelijkheid van het team uitbreidt tot buiten wat is vastgesteld en goedgekeurd. De meest voorkomende fout is de implementatie te behandelen als een gewone publicatie van een nieuwe versie. In een productieomgeving telt niet alleen of de applicatie werkt, maar ook of na de wijziging alle overgangstoestanden zich identiek gedragen: opstart na spanningsuitval, herstart van communicatie, herstel van recepten, afhandeling van alarmen, vergrendelingen en handmatige modi. Het praktische criterium is eenvoudig: als het team niet eenduidig kan beschrijven welke gedragingen na de implementatie ongewijzigd moeten blijven, dan zijn de voorwaarden voor een veilige inbedrijfstelling er nog niet.

In de fase waarin over implementatie wordt besloten, moet een technisch omkeerbare wijziging worden onderscheiden van een wijziging die na ingebruikname een nieuwe uitgangssituatie creëert en terugkeer bemoeilijkt. Dat heeft directe gevolgen voor kosten en planning. Een refactoring die gelijktijdige updates vereist van controllers, visualisatie, de dataserver en interfaces naar bovenliggende systemen, is niet langer één afzonderlijke programmeertaak; het wordt een gecoördineerde productiewijziging met meerdere faalpunten. Daarom is het verstandig om vóór implementatie een acceptatiecriterium te hanteren dat niet is gebaseerd op de verklaring “de tests zijn geslaagd”, maar op het vermogen om de wijziging gecontroleerd terug te draaien binnen een voor het proces aanvaardbare tijd. Als er geen betrouwbare rollbackprocedure is, is er ook geen basis om te stellen dat het risico beheerst is. In de praktijk is het beter om niet de abstracte “kwaliteit van de implementatie” te meten, maar indicatoren zoals de tijd die nodig is om de vorige versie te herstellen, het aantal interfaces dat van de wijziging afhankelijk is en het aantal functies waarvan de correcte werking op de installatie kan worden bevestigd zonder in de productie in te grijpen.

Een goed voorbeeld is een situatie waarin refactoring de afhandeling van uitzonderingen en foutmeldingen ordent, maar tegelijk de volgorde van initialisatie na een systeemrestart verandert. Op de testopstelling ziet alles er correct uit, omdat de apparaten direct beschikbaar zijn en het proces niet onder belasting draait. In de fabriek kan dezelfde code de sequentie echter op een ander moment starten dan voorheen, wat leidt tot verlies van synchronisatie met aandrijvingen, een onjuiste interpretatie van gereedsignalen of het stilvallen van een materiaalbatch in een tussenstatus. Zo’n incident hoeft geen storing in technische zin te zijn, maar veroorzaakt wel kosten door stilstand, afkeur, heropstart en extra verantwoordelijkheid bij de beslissing om het proces te hervatten. Juist hier gaat het onderwerp refactoring over in de praktische beoordeling van wijzigingsrisico’s: niet wanneer de wijziging groot is, maar wanneer de gevolgen ervan niet tot de softwarelaag kunnen worden beperkt.

De grens van de verantwoordelijkheid wordt nog duidelijker waar de applicatie invloed heeft op beveiligingsfuncties, de logica voor vrijgave van beweging, ontlastingssequenties, stilzetten en herstart na een verstoring. In zo’n geval volstaat een vergelijking van codeversies of een functionele test door de integrator niet meer. Dan is een gestructureerde beoordeling nodig of de wijziging het risiconiveau wijzigt en of de uitgangspunten voor veilig gebruik van de machine of installatie intact blijven. Dat is het natuurlijke moment om over te gaan naar risicobeoordeling volgens ISO 12100 en naar praktijken die worden toegepast bij de beoordeling van wijzigingsrisico’s; in complexere gevallen kan ook de methodische benadering uit ISO/TR 14121-2 behulpzaam zijn. Als de applicatie hydraulische of pneumatische systemen aanstuurt, moet bovendien worden nagegaan of de nieuwe logica de voorwaarden voor veilige energiebeheersing en de volgorde van bewegingen niet verandert; dan zijn ook de ontwerpeisen voor deze systemen van belang, en niet alleen de juistheid van het programma zelf. Voor het projectteam betekent dit één ding: een implementatie kan pas als voorbereid worden beschouwd wanneer de technische, operationele en conformiteitsverantwoordelijkheden vóór ingebruikname zijn benoemd, en niet pas na het eerste incident.

Refactoring van een oude industriële applicatie – wanneer is dat zinvol en hoe voer je dat uit zonder risico voor de productie?

Het is zinvol wanneer de kosten en onzekerheid van het doorvoeren van kleine wijzigingen sneller toenemen dan hun zakelijke waarde. Dat is een signaal dat de technische schuld de continuïteit van de productie en de operationele kosten begint te beïnvloeden.

Wanneer de wijziging van invloed is op signalen, toestanden, overgangsvoorwaarden of sequenties voor starten, stoppen en hervatten van de werking. Dan gaat het niet langer uitsluitend om de architectuur, maar om een technische wijziging die een risicobeoordeling vereist.

Meestal op plaatsen waar het gedrag van het systeem in de tijd verandert: de taakplanning, de volgorde van handelingen, de bufferlogica, de reactie na een verbindingsverlies of na een stroomuitval. Zelfs een kleine ingreep kan dan de voorspelbaarheid van de werking van de machine of lijn veranderen.

Er moet duidelijk onderscheid worden gemaakt tussen een wijziging in de structuur van de applicatie en een wijziging van een functie die essentieel is voor het proces of de veiligheid. De acceptatiecriteria moeten zijn gebaseerd op het procesgedrag en de tests moeten ook normale toestanden, storingssituaties en herstarten omvatten.

Wanneer de ingreep betrekking heeft op de logica voor opstarten, stoppen, foutreset, vergrendelingen, energieafschakeling of veilige toegang. In dergelijke gevallen moet de wijziging worden behandeld als een wijziging van het risico en niet als regulier codeonderhoud.

Delen: LinkedIn Facebook