Net-Base Magasin

14.07.2026

Refaktorisering af legacy-kode i Delphi: risici mindske, vedligeholdbarhed øge, drift sikre

Voksede Delphi-applikationer er ofte forretningskritiske – men hver lille ændring bliver dyrere. Denne artikel viser, hvordan du refaktorerer Legacy-Code i Delphi uden at bringe driften i fare: med klar kortlægning, prioriterede tiltag, tests, data- og...

14.07.2026

Fra magasinets tema til projektpraksis

Passende service- og tekniske sider til artiklen

Video-Botschaft

Refaktorisering af legacy-kode i Delphi: risici mindske, vedligeholdbarhed øge, drift sikre

Kurze Einordnung, warum kontrolliertes Refactoring bei geschäftskritischen Delphi-Systemen Betriebssicherheit und Änderungsfähigkeit verbessert, ohne einen riskanten Rewrite zu starten.

Video mit KI erstellt

Transkript anzeigen

Hallo. Kurz ein Thema, das im Betrieb schnell teuer wird.

Der Beitrag heißt: „Legacy-Code in Delphi refactoren: Risiken senken, Wartbarkeit erhöhen, Betrieb sichern“. Wenn jede kleine Änderung ein potenzieller Ausfall ist, werden Releases langsam, und niemand fasst das System gern an.

Legacy heißt hier nicht nur „alt“. Es heißt: schwer erklärbar, stark verknüpft, und dadurch riskant.

Refactoren bedeutet: umbauen, ohne das Verhalten zu ändern. Also kein Rewrite, sondern ein kontrollierter Umbau am fahrenden System.

Wichtig für Admins und IT-Leitung ist die Reihenfolge: erst Bestandsaufnahme. Was ist geschäftskritisch?

Wo hängen Datenbank, Schnittstellen und Jobs dran? Dann kleine, priorisierte Schritte, abgesichert durch Tests und sauberes Logging, damit Fehler auffallen, bevor Nutzer sie melden.

Wenn Sie dazu Fragen haben, schauen wir es gern gemeinsam an.

Den, der driver en forretningskritisk Delphi-applikation, kender spændingsfeltet: Den kører stabilt, dækker kerneprocesser og er dybt integreret i databaser, grænseflader og arbejdsgange. Samtidig øges ændringsomkostningerne og risikoen med hver Release, fordi kompromiser, specialtilfælde og afhængigheder har ophobet sig gennem årene. Her tager Legacy-Code in Delphi refactoren fat: ikke som et ‚Rewrite‘-projekt, men som en kontrolleret ombygning af et kørende system – med målbare effekter på vedligeholdelse, Release-sikkerhed og drift.

I praksis mislykkes Refactoring sjældent på Delphi selv, men på manglende transparens: Hvad er fagligt kritisk? Hvor ligger teknisk gæld (altså strukturelle mangler, der gør senere ændringer dyrere)? Hvilke dele må berøres i vedligeholdelsesvinduer, hvilke ikke? Og hvordan forhindres det, at ‚oprydning‘ skaber nye fejl eller performance-problemer i produktion? Dette indlæg beskriver en praksisorienteret tilgang, der inddrager IT-ledelse og administration: fra statusopgørelse gennem arkitektur- og dataemner til tests, Release-proces og sikkerhedsspørgsmål.

Hvad betyder „Legacy“ i Delphi-projekter egentlig?

„Legacy“ bliver ofte ligestillet med „gammelt“. I virksomhedskontekst er legacy-kode dog primært kode, hvis ændringsrisiko er højt, og hvis opførsel kun delvist kan forklares. Det kan være en VCL-applikation (Visual Component Library, klassisk Windows-desktop-UI), men også en service, en scheduler eller et klient-server-system.

Typiske legacy-træk i Delphi-miljøer er:

  • Stærk kobling: UI, dataadgang og forretningslogik er blandet sammen; ændringer medfører sideeffekter.
  • Implizite regler: Forretningslogik ligger i events, globale variabler eller database-triggers, ikke i klare moduler.
  • Forældede dataadgangsmetoder: f.eks. BDE (Borland Database Engine) eller proprietære komponenter; manglende pooling-/timeout-strategier.
  • Uensartet fejlbehandling: Exceptions bliver slugt, meddelelser ender ikke i centralt logging.
  • Build- og Release-Fragilität: afhængigheder, stiproblemer, forskellige compiler-indstillinger, manuelle efterarbejder.
  • Manglende tests: Viden sidder i hoveder eller i erfarne brugeres klikforløb.

Vigtigt: Legacy-kode er ikke automatisk „dårlig“. Ofte er den resultatet af tidspres, teknologicyklusser og pragmatiske beslutninger. Refactoring er så en investering i håndterbarhed – set fra drift, sikkerhed, compliance og forandringshastighed.

Refactoring vs. Rewrite: Hvad ændrer sig for drift og risiko

Et Rewrite (nyudvikling) lover en ren start, men medfører ofte lange parallelfaser, nye fejlkategorier og høje migrationsrisici. Refactoring derimod sigter mod inkrementel forbedring med kontinuerlig leveringskapacitet. For IT-drift og forretningsområder er det ofte den afgørende forskel: Systemet forbliver produktivt, og forbedringer leveres i overskuelige pakker.

Praktisk afgrænsning:

  • Refactoring: Strukturen forbedres, eksternt adfærd skal forblive den samme. Fokus: vedligeholdelse, testbarhed, stabilitet, ydeevne-reserver.
  • Restrukturierung/Modernisierung: yderligere målrettede adfærdsændringer, f.eks. nye grænseflader, ny database, nye platformsmål.
  • Rewrite: ny kodebase, typisk ny UI/arkitektur; kræver migration af data, processer, grænseflader – ofte „Big Bang“ eller en lang overgangsperiode.

For beslutningstagere er punktet centralt: Refactoring er ikke et mål i sig selv, men en løftestang til at reducere ændringsrisici. Det er direkte driftsrelevant, når applikationen påvirker 24/7-processer, produktionsnære forløb eller kundevendte portaler.

Legacy-Code in Delphi refactoren: Start mit einer belastbaren Bestandsaufnahme

Det første skridt er ikke et værktøj, men en fælles forståelse af risici og mål. Uden denne forståelse ender refactoring hurtigt i „vi rydder lige lidt op her“ – og netop det er i drift vanskeligt at retfærdiggøre.

1) Kritikalität und Betriebsrealität erfassen

Kortlæg hvilke dele der reelt er forretningskritiske: dagsafslutning, grænseflader til ERP/DMS/CRM, indsamling af produktionsdata, afregning, rettighedsstyring. Suppler med driftsparametre: vedligeholdelsesvinduer, rollback-muligheder, overvågning, datavolumen, latenskrav.

Nyttige spørgsmål:

  • Hvilke funktioner skal fortsætte ved delvise nedbrud (evne til degradering)?
  • Hvor findes „Single Points of Failure“ (f.eks. en central scheduler)?
  • Hvilke data er regulatorisk eller databeskyttelsesmæssigt følsomme?
  • Hvilke integrationer er mest fejludsatte (filimports, TCP/IP, SOAP/REST, messaging)?

2) Technische Schulden sichtbar machen – nicht nur Code-Style

I Delphi-projekter er teknisk gæld ofte arkitektonisk: globale tilstande, cykliske unit-afhængigheder, svært testbare dataadgange eller UI-events som „orkestrering“. Metri ker (f.eks. kompleksitet, unit-størrelse, afhængighedsgraf) hjælper, men er kun værdifulde, hvis de omsættes til konkrete tiltag.

Et praktisk anvendeligt skema er en 2×2-betragtning:

  • Ofte ændret & risikabelt: højeste prioritet for refactoring.
  • Ofte ændret & lav risiko: forbedr processer og tests, gennemfør mindre strukturelle tiltag.
  • Sjældent ændret & risikabelt: stabilisering/af sikring (tests, logging), ikke nødvendigvis „pynte på det“.
  • Sjældent ændret & lav risiko: bevidst lade ligge.

3) Abhängigkeiten inventarisieren: Daten, Schnittstellen, Laufzeit

For administration og projektansvarlige er det afgørende at kortlægge, hvad der hænger uden for koden: database-backends, ODBC/OLE DB, filshares, print- og PDF-flow, COM/ActiveX, Office-automation, Windows-services, planlagte tasks, certifikater, proxy-konfigurationer.

Her opstår refactoring-omkostninger ofte indirekte: En „lille“ ændring kan tvinge ny installer-logik, nye rettigheder eller nye firewall-regler. Disse sideeffekter bør tidligt dokumenteres i et teknisk kort.

Typische Problemzonen in Delphi-Legacy und wie man sie gezielt angeht

Refactoring bliver håndterbart, når det målrettes gentagne mønstre. Følgende områder er i praksis ofte de største risiko- og omkostningsfaktorer.

Monolithische Forms: Wenn die UI das System zusammenhält

Mange VCL-applikationer er historisk vokset ‚form-drevet‘: Formularen indlæser data, kontrollerer regler, skriver tilbage, udløser rapporter og opdaterer andre skærmbilleder. Det fungerer – indtil flere teams eller flere års ændringshistorik rammer det.

En operationelt afprøvet fremgangsmåde er at aflaste UI’en trinvis:

  • Use-case-nære services indføre: faglige operationer som klart navngivne metoder i stedet for event-kæder.
  • Indkapsle datatilgang: Queries/Transaktioner ikke i UI-events, men i dataadgangslag.
  • DTOs/modeller (enkle dataobjekter) bruge for at adskille formularens tilstand og database-tilstanden.

Målet er ikke ‚pattern-renhed‘, men bedre testbarhed og færre sideeffekter: En ændring i validering eller beregning bør ikke bringe hele UI-klikstrømmen i fare.

Datenzugriff modernisieren: BDE udskifte, FireDAC anvende konsekvent

Hvis BDE eller uensartede datakomponenter stadig er i brug, er refaktoreringen ofte samtidig en modernisering af driftsrisikoen. BDE er ikke kun gammel, men ofte vanskelig at drive: drivere, konfiguration, 32-bit-afhængigheder og manglende moderne sikkerhedsmekanismer.

BDE-udskiftning med native tilslutning (Delphis moderne dataadgangsbibliotek) er i mange scenarier en fornuftig standard, hvis man arbejder konsekvent: ensartede forbindelsesparametre, klare transaktionsgrænser, timeouts, pooling og ordentlig exception-håndtering. Typiske refaktoreringsforanstaltninger på dette område:

  • Standardisere forbindelsesstyring: central Factory/Provider i stedet for ‚hver formular har sin connection‘.
  • Gøre transaktioner eksplicitte: Begin/Commit/Rollback som del af use-case’et, ikke skjult i UI’en.
  • Brug parameteriserede forespørgsler konsekvent for at reducere SQL-injection-risici og problemer med specialtegn.
  • Definer timeouts og retries, så netværkslåse ikke fører til ‚frosne‘ skærmbilleder.

For IT-drift er det vigtigt, at nye forbindelsesstrategier afstemmes med database-driften (f.eks. maksimale forbindelser, pool-størrelser, deadlock-håndtering, vedligeholdelsesvinduer for skemaændringer).

Unit-afhængigheder og ‚globale tilstande‘ som hovedårsag til sideeffekter

Delphi-Units med store interface-sektioner, mange Uses-indgange og globale Singletons er typiske acceleratorer for sideeffekter. En lille ændring i en Unit udløser rebuild-kaskader eller bryder skjulte initialiseringsrækkefølger.

Pragmatiske skridt, som har vist sig i Legacy-projekter:

  • Fastlæg afhængighedsretninger: f.eks. UI → Application Services → Domain/Logik → Data Access → Infrastruktur.
  • Centralisere initialisering: klar opstartssekvens i stedet for unit-initialisering som skjult styring.
  • Reducér globale variabler: hold tilstand i objekter, afklar levetid og ejerskab.

Det betaler sig for stabiliteten: Hvis opstarten er deterministisk, er fejl efter opdateringer eller konfigurationsændringer lettere at håndtere.

Trådning og synkronisering: Stabilitet før ‚performance-optimering‘

Mange legacy-applikationer udvikler sig over tid til at køre sideløbende: baggrundsimporter, polling, kommunikation med enheder, parallel behandling. Uden klare regler opstår deadlocks, UI-hængere eller race conditions (adgangskonflikter ved samtidig udførelse).

Det er et problem for drift og support, fordi det ofte frembringer »ikke-reproducerbare« fejl. Refaktorering bør her sigte mod standarder:

  • Klar ansvarsfordeling for tråde/opgaver og en defineret nedlukning (så opdateringer/afslutning ikke hænger).
  • Logning per worker med korrelations-id, for at kunne følge forløb.
  • Minimer synkronisering og kapsl UI-adgang strengt (UI-tråd-regel).

Hvis du vil gå i dyBDEn, kan det give mening at placere et internt link til et indlæg om robuste mønstre med TThread og Synchronize, fordi emnet ved legacy-refaktorering ofte er flaskehalsen for stabilitet.

Arkitekturens målbild: Layering som værktøj, ikke som dogme

Et praktisk mål for mange Delphi-bestandsløsninger er en klar lagstruktur (ofte forstået som „3-lags“): Præsentation (UI), forretningslogik (Use Cases/Services) og dataadgang (Repositories/DAO). Det vigtige er driftsperspektivet: Layering forenkler tests, opdateringer og senere udkobling af grænseflader.

Konkrete fordele for virksomheder:

  • Eftermontere grænseflader (f.eks. REST-API), uden at UI-logik skal kopieres.
  • Delmodernisering: Databaseskifte eller BDE-Ablosung mit nativer Anbindung-omstilling kan samles i ét lag.
  • Vedligeholdelse: Fejl kan afgrænses hurtigere, fordi ansvarsfordelingen i koden er klarere.

Et realistisk målbillede tager højde for, at legacy-systemer sjældent bliver „rene“. Afgørende er, at retningen er rigtig, og at nye ændringer ikke opløser strukturen igen.

Teststrategi for Delphi-refaktorering: Hvordan du fryser adfærden, før du ombygger

Refaktorering uden tests er en risiko i forretningskritiske systemer. Samtidig er komplet testautomatisering ofte ikke realistisk på kort sigt. Det centrale budskab er derfor: test målrettet, hvor risikoen og forandringspresset er højest.

Golden Master og regression: Praktisk for legacy

En „Golden Master“ er en reference til den aktuelle adfærd: input og forventede output fastholdes for at opdage afvigelser efter ændringer. Det egner sig til rapporter, beregninger, eksporter, import-pipelines eller svar fra grænseflader.

Vigtigt for driften: Golden-Master-tests reducerer risikoen for, at sideeffekter først viser sig efter rollout – og de understøtter hurtige hotfix-beslutninger, fordi afvigelsen er konkret målbar.

Integrationstests omkring database og grænseflader

Mange fejl opstår ikke i ren forretningslogik, men ved systemgrænser: transaktioner, Encoding (f.eks. Unicode), tidsstempler, decimaltegn, rettigheder, netværksforstyrrelser. Integrationstests bør derfor som minimum dække følgende punkter:

  • Transaktionsadfærd ved fejl (Rollback, delopdateringer, låsninger).
  • Encoding ved import/eksport (CSV, XML, JSON), især ved specialtegn.
  • Performance-profiler for typiske datamængder, for at opdage gradvise forringelser.

Manuelle testtilfælde forbliver – men strukturerede

Hvor automatisering (endnu) mangler, hjælper strukturerede manuelle testplaner, der er koblet til releases. Set fra administrationssiden er det relevant, at testtilfælde også indeholder driftsaspekter: installations-/opdateringssti, rettigheder, konfiguration, logging/monitorering, printer/PDF, netværksstier.

Data og migration: Refaktorering besluttes ofte ud fra skemaet

I Delphi-systemer er databasestrukturer vokset over år. Refactoring støder ofte sammen med „historiske“ tabeller, dobbelte felter eller fagligt overbelastede kolonner. Det kritiske punkt: skemaændringer påvirker drift, Backup/Restore, replikation, reporting og grænseflader.

Gør skemaændringer planbare

En gennemprøvet tilgang er klart versionsstyrede databasemigrationer: Hver ændring i skemaet dokumenteres som et reproducerbart trin, inklusive rollback-strategi. Selv hvis migrationer først udføres manuelt, er disciplinen afgørende: ingen „vi ændrer hurtigt i produktion“.

For releasesikkerhed bør du fastlægge:

  • Downtime-Bedarf: Er online-migration mulig, eller er der behov for et vedligeholdelsesvindue?
  • Rückfallstrategie: Datakompatibilitet ved rollback, Backups før migration, genstartplan.
  • Kompatibilitätsphase: Applikationen skal kunne køre i en overgangsperiode med både gammelt og nyt skema (fx ekstra kolonner, Views).

Undervurder ikke datakvalitet og oprydning

Et Refactoring afdækker ofte dataproblemer, som tidligere „blev båret med“: ugyldige værdier, inkonsistenser, manglende fremmednøgler. Her er det vigtigt at træffe faglige beslutninger om, hvad der er korrekt. Teknisk bør applikationen fremover validere mere konsekvent og logge fejl efterviseligt i stedet for stille at korrigere dem.

Eftermontere grænseflader uden at destabilisere Legacy-Systemet

Mange virksomheder refactorer Delphi-Bestände, fordi nye krav kræver integrationer: portaler, BI, mobile processer, partnertilslutninger. Den hyppigste fejl er at fodre grænseflader direkte fra UI-logik eller „et eller andet sted i koden“. Det er bedre at placere grænseflader i et konsolideret service-lag, som allerede opstår under Refactoring.

Når en REST-API (Representational State Transfer, almindelig Web-API über HTTP/JSON) eftermonteres, er følgende aspekter særligt vigtige set fra drift- og sikkerhedssynspunkt:

  • AuthN/AuthZ: Adskil autentifikation og autorisation; f.eks. Tokens, SAML 2.0 i forbindelse med virksomheders SSO, klare rollemodeller.
  • Rate Limits und Timeouts: så eksterne kald ikke blokerer backenden.
  • Versionierung: Definér API-versioner for at undgå at bryde klienter ved hver ændring.
  • Observability: strukturerede Logs, korrelations-ID’er, metrikker (fejlrater, latenser).

Et internt link til et dybdegående indlæg om eftermontering af en REST-API for Bestandssoftware kan passe godt her, fordi grænseflader i moderniseringsprojekter sjældent er et „Add-on“, men snarere et selvstændigt driftsprodukt.

Sikkerhed og Compliance: Refactoring som mulighed for at lukke sikkerhedshuller

Legacy betyder ofte: sikkerhedsantagelser er ældre end nutidens trusselbillede. Ved Refactoring bør du mindst undersøge, om systemet skal opdateres på følgende områder:

  • Credentials und Secrets: ingen adgangskoder i INI-filer eller i koden; sikker opbevaring og rotation.
  • Transportverschlüsselung: TLS for grænseflader, ordentlig certifikatstyring.
  • Least Privilege: databasebrugere og filrettigheder så minimale som muligt; adskilte roller for læsning/skrivning/administration.
  • Revisionssporbarhed: gennemsigtige ændringer i kritiske data (Hvem? Hvad? Hvornår?), uden at logdata skaber databeskyttelsesproblemer.
  • For IT-ledelsen er det en central forretningsmæssig fordel: Refaktorering reducerer ikke kun vedligeholdelsesomkostninger, men kan også mindske sikkerheds- og revisionsrisici, når det gennemføres struktureret.

    Release- og driftsproces: Uden en pålidelig pipeline bliver Refaktorering dyrt

    Mange Delphi-legacy-projekter lider mindre af koden end af processen: Builds varierer mellem arbejdspladser, Releases er manuelle, fejl kan ikke spores klart. Refaktorering bør derfor altid også stabilisere leveringsprocessen.

    Build-reproducerbarhed og konfigurationsstyring

    Set fra administrationens og revisionssynspunkt er det vigtigt, at et Release er reproducerbart: samme kilder, samme Compiler-/Library-Versionen, samme afhængigheder. Det inkluderer klart adskilte konfigurationer for udvikling, test og produktion (fx databaseendepunkter, Logging-Level, Feature-Flags).

    Logning, overvågning og supportmulighed

    „Der er sket noget“ er ikke nok i drift. Refaktorering er en god lejlighed til at indføre ensartet logning: strukturerede logposter, entydige fejlkoder, kontekst (bruger, mandant, ordre, grænseflade) og klar adskillelse mellem tekniske fejl og faglige valideringer.

    For 24/7-nære processer er der desuden fornuft i:

    • Health Checks (fx databaseforbindelse, kø-opbygning, hukommelsesforbrug),
    • Alarmering efter alvorlighedsgrad,
    • Runbooks til genstart og typiske forstyrrelser.

    En praksisnær Refaktorering-køreplan i 6 trin

    For at Refaktorering ikke går i stå i dagligdriften hjælper en klar køreplan, der er kompatibel med Release-Zyklen. En afprøvet fremgangsmåde:

    1. Udarbejde risiko- og ændringskort (moduler, grænseflader, data, drift).
    2. Etablere sikkerhedsnet: Logging-Standard, første Regressions-/Golden-Master-Tests for kritiske forløb.
    3. Indføre arkitektoniske skillelinjer: Service-Schicht og Data-Access-Kapselung som »ny normalitet« for ændringer.
    4. Refaktorere Hotspots: de moduler, der ofte ændres og forårsager nedbrud (brug fejlstatistik og Change-Historie).
    5. Konsolidere Datenzugriff: FireDAC/Transaktionen/Timeouts ensrette, måle ydeevne, kontrollere Deadlocks.
    6. Åbne Modernisierungspfade: Schnittstellen (REST), Plattformthemen (Unicode/64-Bit), gradvis UI-modernisering, hvor det giver mening.

    Kernen er rækkefølgen: først transparens og sikring, så strukturtiltag, og derefter større ombygninger. Så forbliver løsningen leveringsdygtig og driftsstabil.

    Hvornår Refaktorering ikke er nok: tegn på en større modernisering

    Der er situationer, hvor ren Refaktorering ikke fjerner flaskehalsen. Typiske tegn:

    • Teknologiske blindgyder: ikke længere understøttede databasedrivere, komponenter der ikke kan patches, hårde 32-Bit-afhængigheder.
    • Arkitektur passer ikke længere: fx applikationen skal køre som et service-landskab, men alt er UI-centreret.
    • Skalering og tilgængelighed: krav til mandantfunktionalitet, høj tilgængelighed eller fjernadgang kan kun opfyldes med strukturelle ændringer.
    • Sikkerhedskrav: Authentifizierung/SSO, Audit, Verschlüsselung kan ikke eftermonteres uden større ombygning.

    Selv i disse tilfælde er refaktorering ofte en fornuftig komponent: Det skaber orden, så man målrettet kan udkoble dele i stedet for at udskifte hele systemet på én gang.

    Konklusion: Refaktorering som teknisk ansvar i den løbende drift

    At refaktorere legacy-kode i Delphi er først og fremmest et spørgsmål om prioritering, risikostyring og driftsnærhed. Hvis I starter med en solid statusopgørelse, sikrer hotspots, konsoliderer dataadgangslogik og arkitekturgrænser samt målretter tests og logging mod kritiske stier, bliver „oprydning“ et styrbart moderniseringsprojekt. Resultatet er ikke kun bedre læsbar kode, men et system, som kan drives mere pålideligt, ændres mere sikkert og integreres enklere.

    Hvis I ønsker at stabilisere eller modernisere jeres Delphi-bestandsløsning struktureret, afklarer vi gerne sammen udgangssituationen, risici og en realistisk refaktoreringsplan:

    I det faglige miljø spiller også Delphi Modernisering og Delphi Refaktorering en vigtig rolle, når integrationer, datastrømme og videreudvikling skal fungere sammen pålideligt.

    Drøft projekt eller moderniseringsforløb med Net-Base.

    Næste trin

    Når emnet bliver til et reelt projekt, bør arkitektur, eksisterende systemer og drift tidligt vurderes samlet.

    Vi støtter ikke kun ved enkeltspørsmål, men også når kildekodeudsnit, legacy-komponenter eller portalidéer skal udvikles til et robust virksomhedsprojekt.

    • Eksisterende tilstand, målbillede og tekniske risici vurderes samlet.
    • REST, dataadgang, portaler og udrulning bliver ikke udskudt som efterfølgende opgaver.
    • De ser tidligt, hvilken vej der er økonomisk og driftsmæssigt bæredygtig.

    Del indlæg

    Del dette indlæg direkte

    LinkedIn, X, XING, Facebook, WhatsApp og e-mail er straks tilgængelige. Til Instagram forbereder vi link og kort tekst.

    E-mail

    Instagram åbner i en ny fane. Linket og kortteksten kopieres på forhånd til udklipsholderen.