Back home

Het moderniseren van oude systemen neemt eerst de compatibiliteitsladder

Het echt nuttige deel van Copilot is om de omgeving, de ingang, de test en de grens laag voor laag eruit te halen.

Moderniseer eerst het oude systeem en bouw de compatibiliteitsladder

De eerste keer dat ik twintig jaar geleden een Java-project opende, was het eerste wat ik zag niet de codegeur, maar de ouderdomsgeur. De build.xml is er nog steeds, maar de pom.xml is er niet; de directorystructuur is ouderwets, de testingang is ook ouderwets, en zelfs “of het een uitvoerbaar product kan herbouwen” moet opnieuw worden bevestigd. De meest voorkomende fout in dit stadium is om je te concentreren op klassen en methoden en te negeren dat wat de modernisering werkelijk blokkeert de omgeving en de toegang zijn.

Het eerste dat u moet doen bij het moderniseren van oude systemen is het bouwen van een compatibiliteitsladder. De basis van de ladder heeft meestal maar één ding: het oude systeem stabiel laten draaien binnen de oude regels, en het liefst dienen als tijdcapsule. Docker, oude JDK, oude buildtools, oude testopdrachten, deze dingen zien er grof uit, maar ze zijn zeer effectief. Zolang deze basis niet overeind staat, zal elke volgende verandering nieuwe ruis met zich meebrengen: of het nu de code is die kapot is, of de JVM, het beeld, de architectuur en de plug-ins die kapot zijn, is onmogelijk te zeggen.

Toen was het de beurt om de brug te kiezen. Het doel van de bridge is heel specifiek: het ene uiteinde is verbonden met de oude broncode en het andere uiteinde is verbonden met de nieuwe machine. Dit project viel uiteindelijk ten prooi aan Java 8 en Gradle 7.6, die bleven vasthouden aan de beperkingen van beide kanten: Java 17 is niet langer bereid de broncode van Java 1.5 te compileren, en Java 6 kan niet in de oorspronkelijke omgeving van ARM64 terechtkomen. Als de brug verkeerd is, zal de modernisering vastlopen in de gereedschapsketen; als de brug goed is, zullen volgende migraties stap voor stap vooruit kunnen gaan.

Het nuttigste hier is om het grote model het organiseren en vertalen te laten doen. Het kan helpen om Ant-logica naar Gradle te vertalen, mappen terug te brengen naar de oude lay-out en die repetitieve en mechanische configuraties te verwijderen. Wijs de broncodemap bijvoorbeeld expliciet naar het oude pad en voeg een aangepaste taak toe om de oude main()-test uit te voeren:

java {
    sourceCompatibility = JavaVersion.VERSION_1_5
    targetCompatibility = JavaVersion.VERSION_1_5
}
sourceSets {
    main {
        java {
            srcDirs = ['java']
        }
    }
}
tasks.register('runLegacyTest', JavaExec) {
    mainClass.set(project.findProperty('mainClass'))
    classpath = sourceSets.main.runtimeClasspath
}

De betekenis van deze configuratie is om de regels van de oude wereld expliciet te maken. Het lastigste aan oude projecten is vaak niet het gebrek aan vaardigheden, maar dat vermogen zit verborgen in gewoonten. De test wordt uitgevoerd via de main()-invoer, de broncode wordt in de oude map geplaatst en de build wordt geschreven uitgaande van het pad uit het Ant-tijdperk. Copilot kan hier tijd besparen, maar het bespaart vertaaltijd en geen oordeelstijd.

De oordeelstijd kan niet worden uitbesteed. Gradle 8 ziet er nieuwer uit, Java 17 ziet er moderner uit en direct omhoog springen ziet er ook schoner uit, maar deze opties voldoen mogelijk niet tegelijkertijd aan de beperkingen van oude broncode en oude tests. De grootste angst bij de modernisering is om gereedschapsupgrades als vooruitgang te beschouwen en het uitvoeren van opdrachten als inzicht in het systeem. Zolang een project de operationele basislijn niet heeft bereikt, wordt groen testen niet als een overwinning beschouwd; het kan voorlopig alleen worden beschouwd als het niet bereiken van het blootliggende oppervlak.

De aanpak waar ik meer op vertrouw is om het probleem eerst in vier niveaus op te delen: of het kan worden uitgevoerd, of het kan worden bewerkt, of het kan worden getest en of het kan worden gewijzigd. Het eerste niveau is om de scène te reproduceren, het tweede niveau is om de brug te bepalen, het derde niveau is om te bepalen wat de oude test heeft bespaard, en het vierde niveau is de echte refactoring. Copilot is vooral handig op de eerste twee niveaus. Het is geschikt voor fysiek werk door het volgen van logboeken en mapstructuren, en voor het samenvoegen van gefragmenteerde aanwijzingen tot een leesbare kaart. Op het vierde niveau zou het model alleen verantwoordelijk moeten zijn voor transport en aanwijzingen, en moeten mensen erop vertrouwen dat mensen beslissingen nemen.

Het meest waardevolle resultaat van de modernisering van het oude systeem is het omzetten van een aantal dingen die ‘zouden moeten werken’ in ‘dingen die echt werken en we weten waarom ze werken’. Zodra deze compatibiliteitsladder eenmaal is vastgesteld, zal de daaropvolgende ontmanteling een ritme hebben en zullen de veranderingen grenzen hebben. Copiloot is op dit moment als een assistent aan de frontlinie, die een zaklamp vasthoudt om te kijken naar de leeftijd, ingang en afhankelijkheden. Wat werkelijk de richting bepaalt, is het oordeel over de geschiedenis van het oude systeem.