Le premier réflexe, quand un projet Pascal grossit, consiste à le découper en unités. Cette habitude, héritée des débuts du langage, produit souvent l'effet inverse de celui recherché : plus le projet est fragmenté, plus les dépendances deviennent difficiles à suivre. La taille du code n'est pas le vrai problème ; c'est la direction des liens entre ses parties qui détermine si un projet reste maîtrisable.
Unités, includes et la question de la compilation séparée
Pascal historique repose sur deux mécanismes distincts. L'include textuel insère un fichier source avant compilation ; il ne crée aucune frontière et propage les déclarations dans l'unité hôte. Les unités, apparues avec Turbo Pascal puis standardisées, introduisent au contraire une séparation en partie interface et partie implémentation. Seule l'interface est visible des unités clientes.
Ce second mécanisme reste le socle de toute organisation sérieuse. Il permet de recompiler une unité sans toucher à ses clientes tant que l'interface ne change pas. L'include, lui, garde son utilité pour des fragments de configuration ou des définitions conditionnelles, mais il devient ingérable dès qu'il porte de la logique.
Découper par dépendances plutôt que par fichiers
La règle structurante consiste à faire pointer les dépendances dans un seul sens. Une unité de bas niveau, qui manipule des types et des utilitaires, ne doit rien connaître des unités qui l'utilisent. Les couches applicatives dépendent des couches basses, jamais l'inverse. Un graphe orienté sans cycle est l'objectif ; un cycle entre unités se traduit par des erreurs de compilation ou, pire, par des contournements fragiles.
En pratique, trois familles d'unités reviennent souvent : les types partagés, les services sans état, et les unités d'orchestration. Cette répartition n'a rien d'obligatoire, mais elle aide à repérer les dépendances croisées avant qu'elles ne s'installent.
Organisation des répertoires et des chemins de recherche
Le compilateur ne connaît que les chemins qu'on lui indique. Une arborescence stable, où chaque unité vit dans un répertoire correspondant à son rôle, simplifie la maintenance. Les fichiers de projet des environnements courants permettent de déclarer ces chemins une fois pour toutes, ce qui évite les configurations divergentes entre postes.
- Séparer les sources des interfaces publiques et des implémentations internes.
- Regrouper les unités par domaine fonctionnel plutôt que par type de fichier.
- Garder les unités tierces dans un répertoire distinct, jamais modifié localement.
Documentation des interfaces et discipline de version
La partie interface d'une unité constitue son contrat. La commenter, en indiquant les préconditions et les effets de bord, coûte peu et évite les mauvaises surprises lors des évolutions. Un changement d'interface devrait être traité comme un changement d'API : répercuté consciemment chez les clientes, pas subi.
Cette discipline ne remplace pas les tests, mais elle réduit la surface d'incompréhension. Elle a toutefois ses limites : sur un projet de quelques milliers de lignes mené par une seule personne, une organisation très formelle peut alourdir le travail sans bénéfice proportionné. Le degré de structuration doit suivre la taille de l'équipe et la durée de vie attendue du code.