Fra magasinets tema til projektpraksis
Passende service- og tekniske sider til artiklen
I mange IT-afdelinger er udgangspunktet ens: En stabil, procesnær Delphi-desktopapplikation understøtter kritiske processer, mens nye krav trækker i retning af web, portaler, mobil brug og integration med cloud-tjenester. Samtidig er C# i mange virksomheder etableret, når det gælder services, web-API’er og identitetsintegration. Det centrale spørgsmål er derfor ikke længere „Delphi eller C#?“, men: C# und Delphi in einer gemeinsamen Architektur kombineres, så drift, vedligehold, datahåndtering og sikkerhed forbliver håndterbare.
Denne artikel beskriver praksisegnede arkitekturprincipper, som har vist sig i virksomhedsmiljøer, hvor ikke alt kan eller bør bygges om. Fokus er på klare ansvarsfordelinger mellem desktop-klienten, services, data og grænseflader – og på, hvordan I planlægger moderniseringstrin med lav risiko uden at udsætte de løbende processer for fare.
Hvorfor blandede stacks i virksomheder er normale
Voksede digitale virksomhedsløsninger opstår sjældent fra bunden. Delphi-applikationer er ofte blevet udbygget over mange år, tæt på forretningsprocesserne, med omfattende datalogik og indgående viden om specialtilfælde. Parallelle krav er opstået: selvbetjeningsportaler, automatiserede dataudvekslinger, tilslutning af DMS/CRM/ERP, multitenancy, øget auditmulighed eller single sign-on.
C# tilbyder i denne kontekst ofte fordele for web- og serviceøkosystemer: bredt hostingudvalg, standardiseret middleware, god integration med identitetsudbydere og etablerede mønstre for web-API’er. Delphi forbliver til gengæld stærk, når det gælder performante Windows-desktopklienter, langvarigt vedligeholdte VCL-applikationer eller specifikke multiplatform-klienter (fx via FMX).
Blandingen er derfor ikke et „særsyn“, men et realistisk svar på investeringsbeskyttelse og moderniseringstryk. Det afgørende er, at den fælles drift ikke bliver et permanent byggeprojekt.
Arkitekturprincip: klare lag frem for sproggrænser
Når to sprog mødes, er fristelsen stor til at organisere adskillelsen langs teknologiens linjer („Alt Delphi er Legacy, alt C# er nyt“). Teknisk kan det ofte fungere kortsigtet, men på lang sigt fører det til friktion: dobbelte forretningsregler, uklare ansvarsområder og vanskeligt reproducerbare fejl.
I stedet har en faglig lagdeling vist sig effektiv, ofte realiseret som en Layer-3 arkitektur: Præsentation (UI), Domæne (forretningslogik) og Infrastruktur (dataadgang, eksterne systemer). Pointen er mindre lærebogsmodellen end den konkrete effekt i hverdagen: beslutninger om data, valideringer og workflows træffes ét sted og eksponeres via stabile grænseflader.
I en blandet arkitektur betyder det i praksis: Delphi kan fortsat levere en UI-del (eller bestemte workflows), mens C# Services kan kapsle en faglig domænelag — eller omvendt. Det vigtige er, at kanten mellem lagene er teknisk ren og testbar.
C# og Delphi i en fælles arkitektur: tre velafprøvede integrationsmønstre
Der er ikke én „rigtig“ måde at koble Delphi og C# sammen på. Gode beslutninger tager udgangspunkt i drift, sikkerhedskrav, latenstid, datamængde og release‑cyklusser. I praksis har der dannet sig tre mønstre.
1) Serviceorientering over HTTP/REST som standardkobling
For drift og videreudvikling er en kobling via REST-APIs (HTTP-baserede grænseflader) ofte mest robust. Delphi-klienter kalder C#- eller Delphi-services; C#-portaler anvender de samme endepunkter. Denne løsrevne kobling gør releases mere planlægbare: Et klient‑update er ikke nødvendigt, hvis API’en forbliver bagudkompatibel.
Vigtigt er en professionel udformning: timeouts, retries, idempotens (gentagelige requests uden sideeffekter), klare fejlkoder og en versioneringsstrategi. For administration og drift er følgende også afgørende: ensartede logs, sporbare request‑IDs og velmålte svartider.
2) Fælles database: kun med klare spilleregler
Fælles databaseadgang fra Delphi og C# kan virke tillokkende, fordi det er hurtigt i starten. På længere sigt er det dog risikabelt, hvis begge verdener skriver direkte til samme tabelsæt. Årsagen: forretningsregler forskydes ind i triggers, stored procedures eller et eller andet sted i klienten. Det gør fejlanalyse og audits vanskeligere.
Hvis en fælles database er uundgåelig (f.eks. i overgangsperioder), hjælper klare regler:
- Centraliser skriveadgang: et system er „System of Record“ for bestemte entiteter.
- Definér kontrakter: views eller APIs som et stabilt læselag i stedet for direkte tabeladgang.
- Planlæg migrationsvinduer: udrul databaseændringer altid bagudkompatibelt (f.eks. nye kolonner først som valgfrie).
Teknisk er databasen dermed en infrastrukturkomponent, ikke integrationsbussen.
3) Messaging/Events til asynkrone processer
For løst koblede forløb (f.eks. importkørsler, notifikationer, efterbehandling, integrationsjobs) er en asynkron model fornuftig: Ét system publicerer events, et andet behandler dem. Det reducerer direkte afhængigheder og stabiliserer belastningstoppe.
For IT-ledelse og administratorer er følgende vigtigt: monitoring (queue-længder), dead‑letter‑koncepter (mislykkede beskeder), genstartadfærd og klar faglig idempotens. Events er ikke en erstatning for ordentlig stamdatahåndtering, men et godt værktøj til robuste processkæder.
Datakontrakter og kompatibilitet: den undervurderede kerne
Uanset integrationsmønsteret afgør kvaliteten af datakontrakterne stabiliteten. En datakontrakt er den bindende beskrivelse af felter, typer, obligatorisk/valgfri og semantik. I REST-APIs er det typisk JSON; vigtigt er ikke „JSON i sig selv“, men disciplinen i håndteringen af ændringer.
Gennemprøvede regler, der mærkbart forenkler driften:
- Udvid frem for at bryde: tilføj nye felter, lever fortsat de gamle i første omgang.
- Dokumentér feltsemantik: ikke kun „string“, men f.eks. ISO-dato, tidszone, tilladte tilstande.
- Håndtér enum‑værdier tolerant: klienter skal kunne håndtere ukendte værdier (fremadkompatibilitet).
- Brug API-versionering med omtanke: ikke hvert release behøver en ny version; men breaking changes skal klart indkapsles.
Disse punkter er særligt vigtige, når Delphi-desktop-klienter ikke kan opdateres så ofte som web‑services.
Autentificering og autorisation: en fælles sikkerhedsmodel
Blandede arkitekturer fejler sjældent på „teknik“, oftere på inkonsistent sikkerhed. For virksomheder er det afgørende: Hvem må hvad? Hvordan bliver det kontrolleret? Hvordan bliver det auditeret? En fælles model undgår dobbelt brugeradministration og modstridende roller.
I praksis fører det til et centralt identitetslag: for eksempel via SAML 2.0 (fødereret Single Sign-on, ofte i Enterprise-miljøer) eller OpenID Connect (OAuth2-baseret, ofte til moderne Web-APIs). C#-Services lader sig som regel koble direkte til en identitetsudbyder; Delphi-Clients kan hente Tokens og sende dem med ved API-kald. Vigtigt er, at også desktopapplikationer ikke får „særlige rettigheder“ via databaseadgang.
Centralt for administratorer:
- Token-levetider og Refresh-strategi (så Clients kører stabilt og alligevel er sikre)
- Service-til-service-autentificering for intern kommunikation (f.eks. mTLS eller signerede Tokens)
- Least Privilege: roller og rettigheder ikke defineres for groft
- Audit-Logs: sikkerhedsrelevante handlinger logges så de kan efterprøves
Driftskoncepter: Windows- og Linux-Services, IIS og processer i det daglige
En arkitektur er kun „god“ i virksomheden, hvis den er driftbar: opdateringer kan planlægges, fejl kan lokaliseres, belastning kan kontrolleres. I blandede landskaber er de hyppigste driftsvarianter:
- Windows- og Linux-Services: velegnet til baggrundsjobs, integrationskørsler, worker; godt integrerbart i klassiske Windows-serverdriftsmodeller.
- Windows- og Linux-Services/Daemon: fornuftigt til containeriserede eller VM-baserede driftsmodeller; ofte stabil i kontinuerlig drift, god automatisering over systemd.
- Microsoft IIS: etableret hosting for Web-Anwendungen og Reverse-Proxy-scenarier i Windows-centrerede miljøer.
Vigtigt er, at Delphi- og C#-komponenter opfylder lignende driftstandarder: konsistente Health-Endpoints (livstegn), definerede Timeouts, begrænset ressourceforbrug, samt en klar Deployment- og Rollback-procedure. Det reducerer „teknologispecifikke“ særbehandlinger.
Logging, Tracing und Metriken: et fælles Observability-Niveau
Især ved to teknologistacks er gennemgående diagnosekæder afgørende. Et typisk problem: Delphi-Clienten rapporterer „Fehler beim Speichern“, C#-Service har et Timeout, databasen rapporterer Locks – uden fælles sammenhæng.
I praksis har følgende vist sig effektivt:
- Korrelations-IDs pr. Request (Client → API → DB), så Logs kan sammenføres.
- Struktureret Logging (Nøgle/Værdi i stedet for rene tekstlinjer), for at kunne filtrere senere.
- Metrikker for latenser, fejlrater, kø-længder og ressourceforbrug.
- Fejlklassifikation: Business-fejl (Validering) adskilt fra tekniske fejl (Timeout, Netzwerk).
Disse grundlæggende ting sparer i praksis mere tid end enhver diskussion om „det rigtige sprog“.
Dataadgang og migration: BDE-udskiftning, FireDAC og moderne databaser
I Delphi-installationer spiller dataadgang historisk en stor rolle. Hvor gamle adgangsveje som Borland Database Engine (BDE) stadig er i brug, opstår ekstra pres: operativsystemopdateringer, 64‑bit-overgange, drivertilgængelighed, sikkerhedskrav. En BDE-Ablösung er i så fald ikke kun modernisering, men risikoreduktion.
Typisk er overgangen til en BDE-Ablösung mit nativer Anbindung (et moderne dataadgangslag i Delphi), kombineret med en database, der er operationelt håndterbar (fx PostgreSQL, SQL Server, MariaDB). For en fælles Delphi/C#-arkitektur er to aspekter vigtige:
- Transaktionsgrænser: Hvem starter/committerer transaktioner, og hvordan reguleres parallelle skriveoperationer?
- Locking- und Isolation-Strategie: så desktop-workflows og services ikke blokerer hinanden.
Ved migrationer viser en trinvis plan sig at være effektiv: først modernisere driver- og adgangslag, derefter konsolidere datamodellen, og til sidst stabilisere integrationsgrænsefladerne. Dermed bliver fejlkilder isolerbare, og rollbacks realistiske.
Release-håndtering: forskellige opdateringscyklusser forenes
Et tilbagevendende spændingsfelt er opdateringsfrekvensen: webservices kan udrulles oftere, desktop-klienter ofte sjældnere (udrulningsvinduer, brugerkommunikation, paketering). En fælles arkitektur skal tage højde for denne asymmetri.
Praktiske konsekvenser:
- API-bagudkompatibilitet er påkrævet, ikke valgfrit.
- Feature Flags (funktionelle skifteknapper) hjælper med at aktivere nye funktioner kontrolleret på serversiden.
- Skema-migrationer skal køre i faser: udvid først databasen, så tjenesten kan bruge de nye felter, og til slut opdateres klienten.
- Klar udfasning: Gamle endpoints eller felter fjernes kun efter en defineret periode.
Især i regulerede omgivelser er det vigtigt at fastlægge disse regler skriftligt som arkitekturprincipper, så beslutninger ikke genopfindes projekt-for-projekt.
Typiske faldgruber og hvordan man systematisk undgår dem
Set fra driftssiden er de hyppigste problemer i blandede Delphi/C#-landskaber vel forudsigelige. Hvis man adresserer dem tidligt, falder de langsigtede omkostninger mærkbart.
Faldgrube 1: dobbelt forretningslogik
Når Delphi-klient og C#-service implementerer de samme regler forskelligt, opstår „spøgelsesfejl“: En proces virker i UI’et, men fejler ved API-importen. Modgift: centralisere regler i domænelaget (service) eller tildele dem klart fagligt, inklusive entydige valideringssvar.
Faldgrube 2: UI-workarounds i stedet for rene grænseflader
„Lige at skrive et felt i databasen“ virker i det enkelte tilfælde harmløst, men skaber skyggegrænseflader uden logging, autentificering og versionering. Bedre: konsekvent gå gennem definerede endpoints, selvom det i starten kræver mere disciplin.
Faldgrube 3: uklare ansvarsfordelinger i driften
Hvis det ikke er klart, hvilket team er ansvarlig for hvilken service, hvilket log og hvilke driftsparametre, ender fejlsøgning i ping-pong. Praktisk hjælper et servicediagram (hvilken tjeneste, hvilke afhængigheder, hvilke porte, hvilke interne SLA’er) og ensartede runbooks for hyppige fejl.
Faldgrube 4: manglende sikkerhedskonsistens
Et portal med SSO, men en desktop-klient med lokale administrator-konti er i mange revisioner et problem. Et fælles identitets- og rollemodel reducerer risiko og supportindsats.
Beslutningshjælp: Hvad forbliver i Delphi, hvad flyttes til C#?
Den fornuftige fordeling afhænger mindre af ideologi end af procesnærhed og driftskrav. Som vejledning fra arkitektur- og driftsperspektivet:
- Delphi er ofte velegnet til: eksisterende Windows-desktop-klienter (VCL), meget reaktionssnævre UI-workflows, scenarier med offline-tilstand, og langvarig vedligeholdelse af etablerede brugerflader.
- C# er ofte velegnet til: centrale REST-API’er, integrationsservices til ERP/DMS/CRM, identitetsnære komponenter, portaler og backend-processer med høj ændringsfrekvens.
- Beslut bevidst: Datelogik og validering bør ikke ligge „i klienten“, hvis der findes flere frontends (Desktop, Portal, Importjobs).
Vigtigt: Målet er ikke „alt til C#“, men en robust totalarkitektur, hvor moderniseringstrin kan planlægges, og hvor forretningsprocesserne kører stabilt.
Moderniseringssti: Trinvis fra applikation til system
I praksis er en fælles arkitektur ofte en overgang, men en lang. En realistisk moderniseringssti undgår storprojekter med høj risiko og arbejder med målbare mellemmål:
- Stabiliser grænseflader: indfør REST-API’en som en faglig afgrænsning, selvom ikke alt internt er „pænt“ endnu.
- Moderniser datatilgang: BDE-Ablösung, drivere, 64‑Bit-understøttelse, klare transaktioner.
- Centraliser identitet: SSO og rollemodel for alle adgangsveje.
- Ensartet drift: Logging/Monitoring/Health, klare Deployments, reproducerbare miljøer.
- Afkobling af faglige moduler: flyt særligt ændringsintensive dele til Services, og slank UI’en trinvis.
Rækkefølgen er ikke dogmatisk, men den reducerer typisk afhængigheder: uden stabile grænseflader og et driftkoncept bliver enhver yderligere ændring dyrere.
Konklusion: Integration er en arkitekturopgave, ikke et sprogspørgsmål
En bæredygtig kombination af Delphi og C# opstår ikke gennem „brobiblioteker“, men gennem klare faglige kante, rene datakontrakter og et driftkoncept, der tager Monitoring, Security og Release-Management alvorligt. Når C# og Delphi i en fælles arkitektur bevidst spiller sammen langs ansvarsområder, vinder virksomheder først og fremmest ét: Modernisering uden procesbrud. Delphi kan fortsat bære stabile Desktop-Workflows pålideligt, mens C#-Services stiller Integration, Web-APIs og Portale til rådighed som centrale platformfunktioner.
Hvis I vil modernisere en eksisterende Delphi-landskab trinvis eller koble C#-Services pænt på, er et Arkitektur-Review med fokus på Schnittstellen, Daten, Betrieb und Sicherheit den hurtigste vej til belastbare beslutninger. Mere om det i direkte dialog:
I det faglige miljø spiller også Delphi modernisering og REST-API for bestående software en vigtig rolle, når integrationer, dataflows og videreudvikling skal fungere gnidningsløst sammen.
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.