Net-Base Magasin

08.05.2026

Ryd op i klient-server-arkitekturer i Delphi: genvinde stabilitet, drift og grænseflader

Voksede Delphi-klient-server-systemer er ofte forretningskritiske – og samtidig vanskelige at vedligeholde. Artiklen viser praksisnært, hvordan du adskiller ansvar, stabiliserer dataadgang, moderniserer grænseflader og sikrer driften, uden en risikabel...

08.05.2026

Den, der vil rydde op i Client-Server-arkitekturer i Delphi, står sjældent over for et »dårligt« system. Ofte er der tale om robust forretningssoftware, der er udbygget over år, håndterer mange specialtilfælde og kører pålideligt i daglig brug. Problemet opstår ikke på grund af Delphi som platform, men på grund af sammenvoksede ansvarsområder: Clienten rummer pludselig datalogik, serveren er i praksis blot en database, og grænseflader er blevet suppleret ad hoc. Det slår tilbage, når nye sikkerhedskrav, databaseudskiftninger, VPN til hjemmearbejde, terminalserver-opsætninger eller integrationer med ERP, DMS eller portaler kommer til.

Denne artikel viser, hvordan I i praksis kan strukturere oprydningen af Delphi-Client-Server-landskaber: uden dogmatisk komplet genopbygning, men med klare mål for drift, administration, datakonsistens, grænseflader og vedligeholdelse. Fokus er på beslutninger, som IT-ledelse og tekniske projektansvarlige kan styre: arkitekturgrænser, rollout-strategier, logging, rettighedskoncepter, migrationsveje og typiske risikokilder.

Hvordan man kan se, at Client-Server-arkitekturen er „sammenvokset“

Tekniske gældsforpligtelser viser sig i driften som regel tidligere end i koden. Typiske signaler er mindre „dårlig kode“ og mere tilbagevendende friktion mellem client, database og infrastruktur:

  • Uklare ansvarsområder: Clienten ”ved” for meget om tabeller, triggere, lagrede procedurer eller endda stier til netværksdrev (shares).
  • Sværere releases: Hver lille ændring kræver client-rollout på mange arbejdspladser, ofte med manuelle trin.
  • Skøre dataadgange: Tilfældige deadlocks, inkonsistente transaktioner eller „fastlåste“ låse i spidsbelastninger.
  • Sikkerhed som eftertanke: Databaseadgange kører med for brede rettigheder; adgangskoder ligger i INI-filer; netværkssegmentering bryder funktioner.
  • Integration er uforholdsmæssigt dyrt: Et kundeportal eller en REST-API er svær at eftermontere, fordi forretningsregler er fordelt.
  • Svær fejlsøgning: Uden troværdig logging er det uklart, om fejl opstår i clienten, i netværket, i databasen eller i en grænseflade.

Hvis flere af disse punkter gør sig gældende, er »oprydning« ikke kosmetik, men en foranstaltning til driftsikkerhed. Målet er ikke perfektion, men et system, der forbliver pålideligt at ændre.

Client-Server i Delphi: Hvad der virkelig tæller i driften

I mange Delphi-landskaber forstås „Client-Server“ implicit som „clienten taler direkte med databasen“. Det kan fungere — så længe rammebetingelserne ikke ændrer sig. For virksomheder tæller dog andre egenskaber:

  • Skalérbarhed i daglig drift: ikke glansede benchmarks, men stabil ydeevne ved typiske belastningstoppe (månedsafslutning, vagtskifte, importkørsler).
  • Ændringsvenlighed: Tilpasninger uden kædereaktion af rollout, datamigration og oplæring.
  • Sikker drift: sporbare rettigheder, auditmuligheder, sikker håndtering af hemmeligheder (credentials), klare netværksgrænser.
  • Integrationsmulighed: definerede grænseflader i stedet for en „anden client“, der også binder sig direkte til tabeller.

Disse mål kan nås uden at „afløse“ Delphi. Det afgørende er, hvordan I trækker grænser: Hvad er UI, hvad er forretningslogik, hvad er dataadgang, og over hvilke grænseflader må andre systemer tilslutte?

Rydde op i klient-server-arkitekturer i Delphi: Målbillede frem for Big Bang

Et praktisk målbillede er sjældent et radikalt snit. Et inkrementelt forløb med en klar arkitekturramme har vist sig effektivt. Ofte implementeres det som en Layer-3-arkitektur: tre lag med klare ansvarsområder. „Layer“ betyder her: en defineret adskillelse af UI (præsentation), forretningslogik (regler/use-cases) og dataadgang (SQL, transaktioner, persistens). Det kan også struktureres inden for en Delphi-monolit, før I udskiller en egentlig service.

Trin 1: Gør arkitekturgrænserne synlige

Før I ombygger, skal I vide, hvor kobling opstår. Typiske grænseoverskridelser i Delphi-klienter er:

  • UI-hændelser (knapklik) indeholder SQL eller direkte tabeladgang.
  • Forretningsregler er spredt: delvist i klienten, delvist i triggere, delvist i rapporter eller importskripter.
  • Databaseforbindelser åbnes overalt „ved siden af“, med forskellige parametre.

Målet er en overskuelig kerne: få indgangspunkt i forretningsfunktioner og en central dataadgang, der håndterer forbindelser, transaktioner og fejlbehandling konsekvent.

Trin 2: Definér „kontrakter“ – også uden services

Mange teams tror, at grænseflader først opstår med REST. I virkeligheden har I først brug for interne kontrakter: Hvilke funktioner findes, hvilke parametre overleveres, hvilke fejlkoder er tilladte, hvilke transaktioner hører sammen? Disse kontrakter kan i første omgang eksistere som klart definerede moduler/byggeklodser i Delphi-projektet. Senere kan de forholdsvis rent overføres til en REST-server eller en Windows- henholdsvis Windows- og Linux-services.

Stabiliser dataadgangen: FireDAC, transaktioner og klar forbindelsesstrategi

Dataadgangen er i klient-server-opsætninger ofte det største løft for stabilitet. To emner dominerer: konsistente forbindelser og klare transaktionsgrænser. I Delphi-miljøer er BDE-udskiftning med native tilslutning (dataadgangsbibliotek med drivere og forbindelsepooling) ofte moderniseringsankeret, især hvis stadig BDE (Borland Database Engine, et ældre dataadgangslag) er i brug.

BDE-udskiftning: Mere end et driverbytte

En BDE-udskiftning undervurderes, hvis man ser den som en „udskiftning af komponenter“. I praksis berører den:

  • SQL-dialekt og parametrisering: Forskellige databaser og drivere reagerer forskelligt på datoformater, NULL-håndtering, sortering og tegnsæt.
  • Transaktionsadfærd: Autocommit, isoleringsniveauer (regler for, hvor strengt låsning/læsning håndteres) og genopretning efter fejl.
  • Ydelse og låsning: Nogle ældre logikker stoler ubevidst på implicitte låsemekanismer.

Operationelt er en teststrategi vigtig, som ikke kun „klikker gennem“ skærmbilleder, men simulerer typiske bogførings- og importforløb under belastning.

Transaktioner: Mindre magi, flere regler

I mange etablerede Delphi-klienter opstår transaktioner tilfældigt: Et skærmbillede gemmer poster i flere tabeller, men fejltilfælde rulles ikke konsekvent tilbage. Det fører til delvise tilstande, som senere ‚manuelt ryddes op‘. Bedre er et konsistent mønster:

  • Transaktion per faglig handling (f.eks. ‚opret ordre‘, ‚bogfør varemodtagelse‘), ikke per SQL-Statement.
  • Klare fejlforløb: Ved valideringsfejl ingen halvfærdig datatilstand, men kontrolleret afbrydelse.
  • Idempotens ved import: Gentagen indlæsning uden dobbelte bogføringer.

For IT-drift og support er det særligt vigtigt: Når en operation fejler, skal den fejle på en sporbart måde – med logposter, korrelerbare ID’er og en entydig fejlmeddelelsesklasse (fx tilladelsesfejl, datakonflikt, teknisk fejl).

Udtræk forretningslogik fra klienten – uden at ødelægge betjeningen

Mange Delphi-klienter er historisk vokset som ‚UI-centrerede‘: Forløbet ligger i formularer, valideringer i OnChange-Events, sideeffekter i OnExit. Det er ofte hurtigt og direkte set fra brugerens perspektiv – men set fra et arkitektursynspunkt svært at teste og udvide.

Use-Cases i stedet for formularlogik

Et praktisk anvendeligt mellemliggende skridt er at samle dem i faglige Use-Cases: Et Use-Case indkapsler en proces (f.eks. ‚frigive faktura‘) inklusive valideringer, beregninger, dataadgang og logføring. UI’en kalder den og viser resultaterne i stedet for selv at implementere reglerne. Fordel: Senere kan den samme Use-Case blive anvendt via en REST-API, for eksempel til et portal eller en importtjeneste.

Centraliser reglerne: Validering, nummerserier, tilstandsmodeller

Typiske kandidater til centralisering er:

  • Valideringsregler (obligatoriske felter, værdigrænser, plausibilitetskontroller)
  • Nummerserier (bilag, partier, transaktioner) med konfliktforebyggelse
  • Tilstandsmodeller (udkast → kontrolleret → frigivet → bogført) med tilladte overgange
  • Rettighedstjek tæt på forretningsoperationen, ikke kun i UI’en

Især ved rettigheder er det afgørende: Hvis regler kun ligger i klienten, er de svære at holde konsistente for grænseflader, automatiseringer eller senere portaler.

Blive integrationsklar: REST-API som kontrolleret adgang, ikke som ‚anden vej‘

Mange virksomheder har brug for integration: data til BI, tilslutning til ERP/DMS/CRM, automatisering af import/export eller et kundeportal. Den typiske fejl er at bygge en REST-API ‚ved siden af‘, som går direkte på tabellerne, fordi det går hurtigt. Det skaber to sandheder: klientlogik og API-logik divergerer, og datakonsistens bliver et tilfælde.

REST som facade for stabile Use-Cases

En REST-API (HTTP-baseret grænseflade, typisk JSON) bør tilbyde faglige operationer, ikke spejle tabeller. Eksempler er: ‚opret ordre‘, ‚forespørg status‘, ‚upload dokument til sag‘. API’en kalder de samme Use-Cases, som klienten også bruger. Derved reducerer man dobbelte regler og etablerer klar governance: eksterne systemer får kontrolleret adgang, der kan versioneres og sikres.

Sikkerhed og drift af en API

Fra et B2B-perspektiv er det mindre endpunkterne, der er interessante, og mere driften og sikkerheden:

  • Autentificering: f.eks. token-baserede metoder; i virksomhedsmiljøer ofte tilslutning til centrale identiteter (SAML 2.0 er en udbredt standard for Single Sign-on).
  • Autorisation: Rettigheder per operation, ikke kun „må bruge API’en“.
  • Ratebegrænsninger og beskyttelse mod misbrug: vigtigt ved partneradgange.
  • Versionering: planlagte ændringer uden stille brud.

Hvis I allerede planlægger en modernisering af grænseflader, er det værd at kigge på en struktureret tilgang til eftermontering af en REST-API i eksisterende software: Det gør prioritering lettere og reducerer driftsrisici.

Deployment og opdaterbarhed: Den stille omkostningsdriver

Mange Delphi-systemer fejler ikke på funktionalitet, men på rollout-processer. „Client-Server“ betyder i praksis: mange arbejdspladser, forskellige rettigheder, til tider Terminalservere eller Citrix, samt fjernlokationer med VPN. Et velordnet system har et defineret opdateringsforløb.

Standardisere: Konfiguration, versioner, miljøer

Typiske tiltag, der virker med det samme i driften:

  • Hent konfigurationen fra binærpakken: separate konfigurationsfiler eller centrale konfigurationskilder, så opdateringer ikke overskriver indstillinger.
  • Miljøprofiler: test, staging, produktion med klart adskilte database- og serviceendpoints.
  • Automatiseret installation: reproducerbar, også for Terminalserver-images.

Vigtigt: Selv når klienten „kun“ er et skrivebordsprogram, drager I fordel af release-disciplin som ved servertjenester: versionering med changelog, rollback-muligheder og definerede migrationsskridt.

Databasemigrationer: planlagt frem for risikabelt

Ved enhver strukturel ændring af tabeller, indekser eller views skal det være klart: hvilken version af applikationen forventer hvilket skema? En ryddelig tilgang anvender:

  • Versionerede migrationsskripter pr. release
  • Bagudkompatible overgangsfaser, når client-rollout ikke kan ske samtidig
  • Tydelige backout-strategier (backup, gendannelse, definerede nedetidsvinduer)

Det er ikke et mål i sig selv: uden denne disciplin bliver arkitekturforbedringer i dagligdagen „for farlige“ og bliver liggende.

Logging, overvågning og fejlsøgning: Uden telemetri ingen stabilitet

„Det sker sjældent, men når det gør, står alt stille“ er et advarselssignal. Voksede client-server-systemer har ofte utilstrækkelig logging, især på tværs af systemgrænser. For driftsteams er det afgørende, at en fejl kan rekonstrueres både tidsmæssigt og fagligt.

Hvad der i praksis bør logges

  • Korrelation: en transaktions-ID, der binder klient, service og databaseoperationer sammen
  • Kontekst: bruger, lejer, maskine/placering, version, berørt operation
  • Tekniske detaljer: database-fejlkoder, timeout-oplysninger, genforsøg
  • Sikkerhedsrelevant: mislykkede loginforsøg, brud på rettigheder, afvigende opkaldsmønstre

Vigtigt er adskillelsen mellem tekniske logfiler og faglige protokoller. En faglig protokol (f.eks. „Bilag frigivet af bruger X“) er ofte auditrelevant; tekniske logfiler tjener til fejlanalyse og bør være beskyttede og roterede.

Netværk, sikkerhed og rettigheder: Fra „kører i LAN“ til „kører i virksomheden“

Mange Delphi-klient-server-systemer blev designet på tidspunkter, hvor „i LAN“ blev anset for betroet. I dag gælder: segmentering, Zero-Trust-tilgange, VPN, MFA og restriktive firewallregler er standard. At rydde op i arkitekturen er derfor også sikkerhedsarbejde.

Databasetilgange: princippet om mindst mulige rettigheder

En almindelig gammel tilstand er en databasebruger med vidtrækkende rettigheder, som alle klienter bruger. Bedre er:

  • Rollebaserede rettigheder pr. funktionsområde
  • Separate adgange for klient, services, batch-jobs
  • Ingen admin-rettigheder i produktionsadgange til daglige operationer

Dermed begrænses konsekvenser af fejl, og revisioner bliver markant mere håndterbare. Samtidig øges transparens og diagnoseevne, fordi rettighedsfejl ikke længere opstår „tilfældigt“.

Hemmeligheder og konfiguration: Væk fra klartekst-adgangskoder

Adgangsoplysninger i INI-filer eller i Registry er klassikere. Afhængigt af miljøet kan centrale secret-stores, krypteret konfiguration eller i det mindste driftskoncept med restriktive filrettigheder komme på tale. Vigtigt er: Løsningen skal forblive administrerbar. Sikkerhed, der omgås i dagligdagen, er ikke sikkerhed.

Trinvis modernisering: Hvor begynder man, når alt virker vigtigt?

Prioritering afgør, om oprydningen stopper efter to måneder eller giver målbar lettelse. En rækkefølge, som først adresserer driftssikkerhed og derefter medfører strukturforbedringer, har vist sig effektiv.

En pragmatisk moderniseringsplan

  1. Stabilisere transaktions- og fejladfærd: mindre datakorruption, færre „manuelle reparationer“.
  2. Centraliseret dataadgang: ensartet forbindelseskonfiguration, timeouts, retries, logging.
  3. Saml use-cases: træk kritiske kerneprocesser ud af UI’en.
  4. Definere grænseflade mod omverdenen: REST-API eller service-facade til integration, uden direkte tabeladgang.
  5. Professionaliser deployment: reproducerbare opdateringer, versionsstyrede DB-migrationer.
  6. Security-hardening: rettigheder, secrets, netværksgrænser, auditmuligheder.

Denne rækkefølge er ikke dogmatisk, men den sikrer, at tidlige skridt mærkes straks i driften, og at senere skridt bliver lettere.

Typiske faldgruber set fra projektperspektiv – og hvordan man undgår dem

Ved oprydning mislykkes projekter sjældent på grund af teknikken, men på grund af rammebetingelser. Nogle faldgruber optræder særligt ofte:

„Ved siden af“-ombygning uden kvalitetsnet

Når arkitekturforslag kører parallelt med funktionelle ændringer, mangler der ofte et sikkerhedsnet. Mindst nødvendigt er: reproducerbare testdata, definerede smoke-tests for kerneprocesser og en release-proces, der ser rollback ikke som et nederlag, men som et driftsværktøj.

To datamodeller samtidig

Den, der bygger nye moduler, men lader gamle skærmbilleder fortsat få direkte adgang til tabeller, får hurtigt inkonsistente regler. Bedre: definer klare overgangsregler. Enten forbliver et område foreløbigt „gammelt“ og moderniseres ikke parallelt, eller det ledes konsekvent gennem det nye lag.

Integration uden Governance

Så snart partnere eller interne systemer tilsluttes, opstår der afhængigheder. Uden versionering, kontrakttests og en defineret udfasningsstrategi bliver enhver ændring en afstemningssløjfe. Det er mindre et udviklerproblem end et arkitektur- og driftsproblem.

Konklusion: Oprydning betyder at gøre drift og forandring håndterbare igen

Når I rydder op i Client-Server-arkitekturer i Delphi, handler det ikke om „modernisering for moderniseringens skyld“. Det handler om at strukturere en forretningskritisk digital virksomhedsløsning, så drift, sikkerhed og videreudvikling forbliver planbare. De mest effektive greb er som regel uspektakulære: klare lag, konsistent dataadgang, rene transaktionsgrænser, robust logging og en grænsefladestrategi, der ikke duplikerer reglerne.

Det afgørende er fremgangsmåden: inkrementel, med et målbild og en prioritering, der først skaber stabilitet. Så kan I modernisere et voksent Delphi-landskab uden at sætte den daglige drift på spil – og uden at blive presset ind i en risikabel komplet nystart.

Hvis I pragmatisk vil vurdere de næste skridt for jeres arkitektur, databaseadgange og grænseflader, så kontakt os:

I fagligt regi spiller også Delphi Modernisering en vigtig rolle, når integrationer, dataflows og videreudvikling skal fungere sammen på en struktureret måde.

Drøft projekt eller moderniseringsprojekt med Net-Base.

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 med det samme.

E-mail

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