Quiconque souhaite rationaliser des architectures client-serveur dans Delphi se retrouve rarement face à un « mauvais » système. Il s’agit souvent d’un logiciel métier robuste, étendu sur plusieurs années, couvrant de nombreux cas particuliers et fonctionnant de manière fiable au quotidien. Le problème ne vient pas de Delphi en tant que plateforme, mais de responsabilités devenues confuses : le client contient soudainement de la logique de données, le « serveur » n’est en fait qu’une base de données, et des interfaces ont été ajoutées de façon ad hoc. Cela se manifeste lorsque de nouvelles exigences de sécurité, un changement de base de données, le télétravail via VPN, des configurations de terminal server ou des intégrations avec des ERP, DMS ou portails surviennent.
Ce texte montre comment nettoyer de manière structurée des paysages client-serveur Delphi en pratique : sans reconstruction dogmatique complète, mais avec des objectifs clairs pour l’exploitation, l’administration, la cohérence des données, la capacité d’intégration et la maintenabilité. L’accent est mis sur des décisions que la direction informatique et les responsables techniques de projet peuvent piloter : délimitations architecturales, stratégies de déploiement, journalisation, concepts de droits, parcours de migration et sources de risques typiques.
Comment reconnaître qu’une architecture client-serveur est « embrouillée »
La dette technique se manifeste en exploitation souvent avant d’apparaître dans le code source. Les signaux typiques ne sont pas tant du « mauvais code » que des points de friction récurrents entre le client, la base de données et l’infrastructure :
- Responsabilités floues : le client « connaît » trop de choses sur les tables, les triggers, les stored procedures ou même les chemins de fichiers sur des shares.
- Releases difficiles : chaque petite modification nécessite un déploiement client sur de nombreux postes, souvent avec des étapes manuelles.
- Accès aux données fragiles : interblocages aléatoires (deadlocks), transactions incohérentes ou verrous qui restent bloqués en période de pointe.
- Sécurité en second plan : les accès à la base de données s’exécutent avec des droits trop larges ; des mots de passe sont stockés dans des fichiers INI ; la segmentation réseau casse des fonctions.
- L’intégration coûte de manière disproportionnée : un portail client ou une REST-API est difficile à adapter a posteriori, car les règles métier sont dispersées.
- Recherche d’erreurs difficile : sans journalisation fiable, il est impossible de déterminer si les erreurs proviennent du client, du réseau, de la base de données ou d’une interface.
Lorsque plusieurs de ces points se vérifient, « nettoyer » n’est pas de la cosmétique, mais une mesure pour la sécurité d’exploitation. L’objectif n’est pas la perfection, mais un système qui reste modifiable de manière fiable.
Client-Server dans Delphi : ce qui compte réellement en exploitation
Dans de nombreuses architectures Delphi, « client‑serveur » est implicitement compris comme « le client parle directement à la base de données ». Cela peut fonctionner — tant que les conditions-cadre ne changent pas. Pour les entreprises, d’autres propriétés sont cependant décisives :
- Scalabilité au quotidien : pas des benchmarks de vitrine, mais des performances stables lors des pics de charge typiques (clôture mensuelle, changements de poste, traitements d’import).
- Capacité d’évolution : adaptations sans réaction en chaîne impliquant déploiement, migration de données et formation.
- Exploitation sécurisée : droits traçables, auditabilité, gestion propre des secrets (identifiants), délimitations réseau claires.
- Capacité d’intégration : interfaces définies plutôt qu’un « second client » qui se greffe lui aussi directement sur les tables.
Ces objectifs peuvent être atteints sans « remplacer » Delphi. Ce qui compte, c’est la manière dont vous tracez les frontières : qu’est‑ce qui relève de l’UI, qu’est‑ce qui relève de la logique métier, qu’est‑ce qui relève de l’accès aux données, et par quelles interfaces d’autres systèmes peuvent se connecter ?
Réorganiser les architectures client‑serveur dans Delphi : vision cible plutôt que Big Bang
Une vision cible applicable en pratique est rarement une coupure radicale. Une approche incrémentale avec un cadre d’architecture clair a fait ses preuves. On la met souvent en œuvre comme une architecture Layer-3 : trois couches avec des responsabilités définies. « Layer » signifie ici : une séparation définie entre l’UI (présentation), la logique métier (règles / cas d’utilisation) et l’accès aux données (SQL, transactions, persistance). Cela peut être structuré au sein d’un monolithe Delphi avant d’extraire un véritable service.
Étape 1 : rendre visibles les frontières d’architecture
Avant de refactoriser, vous devez savoir où le couplage se produit. Les violations typiques de frontières dans les clients Delphi sont :
- Les événements UI (clic de bouton) contiennent du SQL ou des accès directs aux tables.
- Les règles métier sont réparties : parfois dans le client, parfois dans des triggers, parfois dans des rapports ou des scripts d’import.
- Les connexions à la base de données sont ouvertes un peu partout « en passant », avec des paramètres différents.
L’objectif est un noyau maîtrisable : peu de points d’entrée vers les fonctions métier et un accès aux données centralisé qui gère de manière cohérente les connexions, les transactions et la gestion des erreurs.
Étape 2 : définir des « contrats » – même sans services
Beaucoup d’équipes pensent que les interfaces n’apparaissent qu’avec REST. En réalité, vous avez d’abord besoin de contrats internes : quelles fonctions existent, quels paramètres sont passés, quels codes d’erreur sont autorisés, quelles transactions appartiennent ensemble ? Ces contrats peuvent d’abord exister comme des modules/éléments clairement définis dans le projet Delphi. Ils peuvent ensuite être transférés relativement proprement vers un serveur REST ou vers des services Windows et Windows- et Linux-Services.
Stabiliser l’accès aux données : FireDAC, transactions et stratégie de connexion claire
L’accès aux données est souvent le levier principal de stabilité dans les architectures client‑serveur. Deux sujets dominent : des connexions cohérentes et des limites de transaction propres. Dans les environnements Delphi, une BDE‑Ablösung avec connexion native (bibliothèque d’accès aux données avec pilotes et pool de connexions) est fréquemment l’ancre de modernisation, en particulier si BDE (Borland Database Engine, une couche d’accès aux données plus ancienne) est encore en service.
BDE‑Ablösung : plus qu’un simple changement de pilote
Un remplacement de BDE est sous‑estimé si on le regarde comme un « échange de composants ». En pratique, il touche :
- Dialecte SQL et paramétrisation : différentes bases et pilotes réagissent différemment aux formats de date, au traitement des NULL, au tri et aux jeux de caractères.
- Comportement des transactions : autocommit, niveaux d’isolation (règles sur la sévérité des verrous/lectures) et récupération d’erreurs.
- Performance et verrous : certaines logiques héritées comptent inconsciemment sur des mécanismes de verrouillage implicites.
Sur le plan opérationnel, un concept de test est nécessaire qui ne se contente pas de « cliquer » à travers les écrans, mais qui simule sous charge les enchaînements typiques de saisie et d’import.
Transactions: moins de magie, plus de règles
Dans de nombreux clients Delphi hérités, les transactions apparaissent de manière accidentelle : un écran enregistre plusieurs tables, mais les cas d’erreur ne sont pas correctement annulés. Cela conduit à des états partiels qui doivent ensuite être « corrigés manuellement ». Mieux vaut appliquer un modèle cohérent :
- Une transaction par opération métier (par ex. « créer un ordre », « enregistrer une réception de marchandises »), et non par instruction SQL.
- Des chemins d’erreur clairs : en cas d’erreur de validation, pas d’état à moitié constitué, mais un abandon contrôlé.
- Idempotence pour les imports : pouvoir rejouer un import sans générer d’écritures en double.
Pour l’exploitation et le support IT, l’essentiel est le suivant : lorsqu’une opération échoue, elle doit échouer de manière traçable – avec des entrées de journal, des IDs corrélables et une classe de message d’erreur clairement identifiable (par ex. autorisation, conflit de données, erreur technique).
Extraire la logique métier du client — sans compromettre l’utilisation
Beaucoup de clients Delphi ont évolué historiquement de manière « centrée UI » : le déroulement est imbriqué dans les formulaires, les validations dans des OnChange-Events, les effets de bord dans OnExit. Cela peut sembler rapide et direct pour l’utilisateur, mais d’un point de vue architectural c’est difficile à tester et à faire évoluer.
Cas d’utilisation plutôt que logique de formulaire
Une étape pragmatique consiste à regrouper les fonctionnalités en cas d’utilisation métier : un cas d’utilisation encapsule une opération (par ex. « valider une facture ») incluant validations, calculs, accès aux données et journalisation. L’UI l’invoque et affiche les résultats, au lieu d’implémenter elle‑même les règles. Avantage : le même cas d’utilisation pourra plus tard être exploité via une API REST, par exemple pour un portail ou un service d’import.
Centraliser les règles : validation, séries de numéros, modèles d’état
Les candidats typiques à la centralisation sont :
- Règles de validation (champs obligatoires, plages de valeurs, vérifications de plausibilité)
- Séries de numéros (pièces, lots, opérations) avec prévention des conflits
- Modèles d’état (brouillon → vérifié → approuvé → comptabilisé) avec transitions autorisées
- Contrôles d’autorisation proches de l’opération métier, pas seulement dans l’UI
Sur les autorisations en particulier, c’est déterminant : si les règles résident uniquement dans le client, elles sont difficiles à maintenir de façon cohérente pour les interfaces, les automatisations ou de futurs portails.
Devenir interopérable : API REST comme accès contrôlé, pas comme « voie secondaire »
Beaucoup d’entreprises ont besoin d’intégration : données pour la BI, connexion à ERP/DMS/CRM, automatisation des imports/exports ou un portail client. L’erreur typique est de construire une API REST « à côté » qui accède directement aux tables parce que c’est rapide. Cela produit deux vérités : la logique client et la logique API divergent, et la cohérence des données devient aléatoire.
REST comme façade devant des cas d’utilisation stables
Une API REST (interface HTTP, le plus souvent JSON) devrait exposer des opérations métier, pas refléter des tables. Exemples : « créer une commande », « interroger le statut », « téléverser un document sur une opération ». L’API appelle les mêmes cas d’utilisation que le client. Vous réduisez ainsi les règles dupliquées et établissez une gouvernance claire : les systèmes externes disposent d’un accès contrôlé, versionnable et sécurisable.
Sécurité et exploitation d’une API
Du point de vue B2B, ce ne sont pas tant les endpoints qui importent, mais l’exploitation et la sécurisation :
- Authentification : par ex. des procédés basés sur des jetons ; en milieu d’entreprise, souvent intégration à des identités centrales (SAML 2.0 est une norme répandue pour le Single Sign-on).
- Autorisation : droits par opération, pas seulement « peut utiliser l’API ».
- Limites de taux et protection contre les abus : importantes pour les accès partenaires.
Si vous planifiez déjà une modernisation d’interface, il vaut la peine d’examiner une approche structurée pour ajouter une API REST à un logiciel existant : cela facilite la priorisation et réduit les risques opérationnels.
Déploiement et capacité de mise à jour : le facteur de coût caché
Beaucoup de systèmes Delphi échouent non pas à cause de la fonctionnalité, mais à cause des processus de déploiement. « client-serveur » signifie en pratique : de nombreux postes de travail, des droits différents, parfois des serveurs de terminaux ou Citrix, ainsi que des sites distants via VPN. Un système bien organisé dispose d’une procédure de mise à jour définie.
Standardiser : configuration, versions, environnements
Mesures typiques qui ont un effet immédiat en exploitation :
- Extraire la configuration du paquet binaire : fichiers de configuration séparés ou sources de configuration centralisées, afin que les mises à jour n’écrasent pas les paramètres.
- Profils d’environnement : test, staging, production avec des points de terminaison de base de données et de services clairement séparés.
- Installation automatisée : reproductible, y compris pour des images de serveurs de terminaux.
Important : même si le client est « seulement » un programme de bureau, vous bénéficiez d’une discipline de release comparable à celle des services serveurs : versionnage avec journal des modifications, options de rollback et étapes de migration définies.
Migrations de base de données : planifiables plutôt que risquées
Pour toute modification structurelle des tables, index ou vues, il doit être clair : quelle version de l’application attend quel schéma ? Une approche soignée utilise :
- Scripts de migration versionnés par release
- Phases de transition rétrocompatibles, lorsque le déploiement client ne peut pas être simultané
- Stratégies de backout claires (sauvegarde, restauration, fenêtres de downtime définies)
Ce n’est pas une fin en soi : sans cette discipline, les améliorations d’architecture sont jugées « trop risquées » dans l’exploitation quotidienne et ne sont pas mises en œuvre.
Journalisation, supervision et diagnostic : pas de stabilité sans télémétrie
« Cela arrive rarement, mais quand ça arrive, tout s’arrête » est un signal d’alerte. Les systèmes client-serveur hérités ont souvent une journalisation insuffisante, surtout à travers les frontières des systèmes. Pour les équipes d’exploitation, il est essentiel qu’un incident puisse être reconstitué dans le temps et sur le plan fonctionnel.
Ce qui devrait être journalisé en pratique
- Corrélation : un identifiant de corrélation qui relie le client, le service et les opérations sur la base de données
- Contexte : utilisateur, tenant, machine/emplacement, version, opération concernée
- Détails techniques : codes d’erreur de la base de données, informations de timeout, tentatives de reprise
- Aspects liés à la sécurité : échecs d’authentification, violations de droits, modèles d’appels suspects
Il est important de séparer les logs techniques et les protocoles métier. Un protocole métier (p. ex. « Document approuvé par l’utilisateur X ») est souvent pertinent pour l’audit ; les logs techniques servent à l’analyse des erreurs et doivent être protégés et pivotés en conséquence.
Réseau, sécurité et droits : de « fonctionne sur le LAN » à « fonctionne dans l’entreprise »
Beaucoup de systèmes client-serveur Delphi ont été conçus à une époque où « sur le LAN » équivalait à « digne de confiance ». Aujourd’hui : segmentation, approches Zero Trust, VPN, MFA et règles de pare-feu restrictives sont la norme. Assainir l’architecture relève donc aussi du travail de sécurité.
Droits sur la base de données : principe du moindre privilège
État ancien fréquent : un utilisateur de base de données aux droits étendus utilisé par tous les clients. Mieux vaut :
- Droits basés sur les rôles par domaine fonctionnel
- Accès séparés pour le client, les services, les jobs batch
- Pas de droits admin sur les accès de production pour les opérations courantes
Cela limite l’étendue des erreurs et rend les audits nettement plus simples. En parallèle, la transparence et la capacité de diagnostic augmentent, car les erreurs liées aux droits n’apparaissent plus de façon « aléatoire ».
Secrets et configuration : abandonner les mots de passe en clair
Les identifiants dans des fichiers INI ou dans le registre sont un classique. Selon l’environnement, des secret stores centraux, une configuration chiffrée ou au minimum des concepts d’exploitation avec des droits de fichier restrictifs sont envisageables. L’essentiel : la solution doit rester administrable. Une sécurité qui est contournée au quotidien n’en est pas une.
Modernisation progressive : par où commencer quand tout semble important ?
La priorisation détermine si le travail d’assainissement s’arrête au bout de deux mois ou s’il apporte un allègement mesurable. Une séquence éprouvée consiste à traiter d’abord la sécurité opérationnelle, puis à engager les améliorations structurelles.
Feuille de route pragmatique pour la modernisation
- Stabiliser le comportement des transactions et des erreurs : moins de corruption des données, moins de « réparations manuelles ».
- Accès centralisé aux données : configuration de connexion unifiée, timeouts, retries, journalisation.
- Regrouper les cas d’usage : extraire les opérations cœur critiques de l’UI.
- Définir une interface externe : API REST ou façade de service pour l’intégration, sans accès direct aux tables.
- Professionnaliser le déploiement : mises à jour reproductibles, migrations de base de données versionnées.
- Renforcement de la sécurité : droits, secrets, limites réseau, capacité d’audit.
Cette séquence n’est pas dogmatique, mais elle garantit que les premières étapes sont immédiatement perceptibles en exploitation et que les étapes suivantes sont plus faciles à engager.
Pièges typiques du point de vue des projets — et comment les éviter
Lors des opérations d’assainissement, les projets échouent rarement sur la technique ; ce sont les contraintes périphériques qui posent problème. Certains pièges reviennent fréquemment :
Refonte « en parallèle » sans filet qualité
Lorsque des mesures d’architecture sont menées en parallèle avec des évolutions fonctionnelles, il manque souvent un filet de sécurité. Sont au minimum nécessaires : des jeux de test reproductibles, des smoke tests définis pour les processus clés, et un processus de release qui considère le rollback non pas comme une défaite, mais comme un outil d’exploitation.
Deux modèles de données simultanés
Qui construit de nouveaux modules tout en laissant les anciennes vues accéder directement aux tables se heurte rapidement à des règles incohérentes. Mieux vaut définir des règles de transition claires. Soit une zone reste « ancienne » temporairement et n’est pas modernisée en parallèle, soit elle est systématiquement exposée via la nouvelle couche.
Integration sans gouvernance
Dès que des partenaires ou des systèmes internes sont connectés, des dépendances apparaissent. Sans gestion des versions, tests de contrat et stratégie de dépréciation définie, chaque modification devient une boucle de coordination. Ce n’est pas tant un problème de développeurs que d’architecture et d’exploitation.
Conclusion : Remettre de l’ordre signifie rendre à nouveau maîtrisables l’exploitation et le changement
Lorsque vous remettez de l’ordre dans des architectures client-serveur dans Delphi, il ne s’agit pas de « moderniser pour la modernisation ». Il s’agit de structurer une solution numérique d’entreprise critique pour l’activité de façon à ce que l’exploitation, la sécurité et l’évolution restent planifiables. Les leviers les plus efficaces sont généralement peu spectaculaires : couches clairement définies, accès aux données cohérent, limites de transaction nettes, journalisation robuste et une stratégie d’interfaces qui ne duplique pas les règles.
Le point décisif est la démarche : incrémentale, avec une vision cible et une priorisation qui crée d’abord de la stabilité. Ainsi, vous pouvez moderniser un paysage Delphi existant sans mettre en péril les opérations quotidiennes — et sans être contraint d’engager une refonte complète risquée.
Si vous souhaitez évaluer de manière pragmatique les prochaines étapes pour votre architecture, vos accès aux bases de données et vos interfaces, parlez-nous :
Dans le domaine technique, la Delphi Modernisation joue également un rôle important lorsque les intégrations, les flux de données et l’évolution doivent bien s’articuler.
Discuter d’un projet ou d’un plan de modernisation avec Net-Base.