1. Modularité
1. Modularité (selon B.Meyer)
Le mot MODULE est un des mots les plus employés en programmation moderne. Nous allons expliquer ici ce que l'on demande, à une méthode de construction modulaire de logiciels, de posséder comme propriétés, puis nous verrons comment dans certaines extensions de Pascal sur micro-ordinateur (Pascal, Delphi), cette notion de module se trouve implantée. B.Meyer est l’un des principaux auteurs avec G.Booch qui ont le plus travaillé sur cette notion. Le premier a implanté ses idées dans le langage orienté objet " Eiffel ", le second a utilisé la modularité du langage Ada pour introduire le concept d’objet qui a été la base de méthodes de conception orientées objet : OOD, HOOD,UML...
Nous nous appuyons ici sur les concepts énoncés par B.Meyer fondés sur 5 critères et 6 principes relativement à une méthodologie d’analyse de type modulaire. Une démarche (et donc le logiciel construit qui en découle) est dite modulaire si elle respecte au moins les concepts ci-après.
1.2 Critères principaux de modularité
Les 5 pricinpes retenus :
- La décomposabilité modulaire
- La composition modulaire
- La continuité modulaire
- La compréhension modulaire
- La protection modulaire
La décomposabilité modulaire :
capacité de décomposer un problème en sous-problèmes, semblable à la méthode structurée descendante. Réalisation de ce critère en Pascal :
La hiérarchie descendante des procédures et des fonctions.
La composition modulaire :
capacité de recombinaison et de réagencement de modules écrits, semblable à la partie ascendante de la programmation structurée. Réalisation de ce critère en Pascal :
N'existe pas en Pascal standard, toutefois la notion d'UNIT en Pascal UCSD(dont le Turbo Pascal est un descendant) et de Library en sont deux implantations partielles.
La continuité modulaire :
capacité à réduire l’impact de changements dans les spécifications à un minimum de modules liés entre eux, et mieux à un seul module. |
Réalisation de ce critère en Pascal :
Partiellement ; le cas
particulier des constantes symboliques en Pascal standard, au paragraphe
const,
montre l’intérêt de ce critère.
Exemple : const
n=10 ;
|
La compréhension modulaire :
capacité à l’interprétation par un programmeur du fonctionnement d’un module ou d’un ensemble de modules liés, sans avoir à connaître tout le logiciel. |
Réalisation de ce critère en Pascal :
Partiellement à la charge du programmeur en écrivant des procédures et des fonctions qui s’appellent le moins possible. Chaque procédure ou fonction doit être dédiée à une tâche autonome. |
Plus
efficace dans la version UCSD grâce à la notion d’UNIT.
La protection modulaire :
capacité à limiter les effets produits par des incidents lors de l’exécution à un nombre minimal de modules liés entre eux, mieux à un seul module. |
Réalisation de ce critère en Pascal :
Correcte en Pascal grâce au contrôle des types et des bornes des paramètres d'entrées ou de sorties d'une procédure ou d'une fonction. Les variables locales permettent de restreindre la portée d’un incident. |
Les pointeurs en Pascal :
Attention
le type pointeur met fortement en défaut ce critère, car
sa gestion mémoire est de bas niveau et donc confiée au programmeur
; les pointeurs ne respectent même pas la notion de variable locale!
En général le passage par adresse met en défaut le principe de protection modulaire. |
1.3 Préceptes minimaux de construction modulaire
Etant débutants,
nous utiliserons quatre des six préceptes énoncés
par B.Meyer. Ils sont essentiels et sont adoptés par tous ceux qui
pratiquent des méthodes de programmation modulaire :
Précepte 1 : Interface de données minimale
Un module fixé doit ne communiquer qu’avec un nombre " minimum " d’autres modules du logiciel. L’objectif est de minimiser le nombre d'interconnexions entre les modules. Le graphe établissant les liaisons entre les modules est noté " graphe de dépendance ". Il doit être le moins maillé possible. La situation est semblable à celle que nous avons rencontré lors de la description des différentes topologies des réseaux d’ordinateurs : les liaisons les plus simples sont les liaisons en étoile, les plus complexes (donc ici déconseillées) sont les liaisons totalement maillées. |
L'intérêt de ce précepte est de garantir un meilleur respect des critères de continuité et de protection modulaire. Les effets d'une modification du code source ou d'une erreur durant l'exécution dans un module peuvent se propager à un nombre plus ou moins important de modules en suivant le graphe de liaison. Un débutant optera pour une architecture de liaison simple, ce qui induira une construction contraignante du logiciel. L’optimum est défini par le programmeur avec l’habitude de la programmation.
Le graphe de dépendance des procédures et des fonctions sera arborescent ou en étoile. |
Précepte 2 : Couplage minimal
Lorsque deux modules communiquent entre eux, l’échange d’information doit être minimal. Ce précepte ne fait pas double emploi avec le précédent. Il s'agit de minimiser la taille des interconnexions entre modules et non leur nombre comme dans le précepte précédent. |
Réalisation de ce précept en Pascal :
En général, nous avons aussi un couplage fort lorsqu'on introduit toutes les variables comme globales (donc à éviter, ce qui se produit au stade du débutant). D'autre part la notion de visibilité dans les blocs imbriqués et la portée des variables Pascal donne accès à des données qui ne sont pas toutes utiles au niveau le plus bas. |
Précepte 3 : Interfaces explicites
Lorsque deux modules M1 et M2 communiquent, l’échange d’information doit être lisible explicitement dans l’un des deux ou dans les deux modules. |
Réalisation de ce précept en Pascal :
L’utilisation des données globales ou de la notion de visibilité nuit aussi à ce principe. Le risque de battre en brèche le précepte des interfaces explicites est alors de conduire à des accès de données injustifiés (problème classique des effets de bord, où l’on utilise implicitement dans un bloc une donnée visible mais non déclarée dans ce bloc). |
Précepte 4 : Information publique et privée
Toute information dans un module doit être répartie en deux catégories : l’information privée et l’information publique. |
Ce précepte permet
de modifier la partie privée sans que les clients (modules utilisant
ce module) aient à supporter un quelconque problème à
cause de modifications ou de changements. Plus la partie publique est petite,
plus on a de chances que des changements n'aient que peu d'effet sur les
clients du module.
Réalisation
de ce précept en Pascal :
Le Pascal standard ne permet absolument pas de respecter ce principe dans le cadre général. L'UCSD avec la notion d'UNIT contient une approche partielle mais utile de ce principe. Les prémisses de cette approche existent malgré tout dans les notions de variables et de procédures locales à une procédure. |
Enfin et pour mémoire
nous citerons l’existence du précepte d’ouverture-fermeture et du
précepte d’unités linguistiques.
2.
La modularité par les UNIT en Pascal UCSD
Rappelons que le Turbo Pascal de Borland et les versions de compilateurs libres gratuits comme FreePascal compiler, Obéron etc... présentes sur Internet fonctionnant sur les micro-ordinateurs type PC, ainsi que le Think Pascal de Symantec fonctionnant sur les MacIntosh d’Apple, sont tous une extension du Pascal UCSD. Il est donc possible sur du matériel courant d’utiliser la notion d’UNIT simulant le concept de module.
Cet élément
représente une unité compilable séparément
de tout programme et stockable en bibliothèque. Une Unit comporte
une partie " public " et une partie " privé ". Elle implante donc
l’idée de module et étend la notion de bloc (procédure
ou fonction) en Pascal.
Syntaxe :
Exemple
:
Unit Truc; |
2.1 Partie " public " d’une UNIT : " Interface "
Correspond exactement
à la partie publique du module représenté par la UNIT.
Cette partie décrit les en-têtes des procédures et
des fonctions publiques utilisables par les clients. Les clients peuvent
être soit d’autres procédures Pascal, des programmes Pascal
ou d’autres Unit. La clause Uses XXX dans un programme Pascal, permet d’indiquer
la référence à la Unit XXX et autorise l’accès
aux procédures et fonctions publiques de l’interface dans tout le
programme.
Syntaxe :
Exemple
:
Unit Truc ; |
2.2 Partie " privée " d’une UNIT : " Implementation "
Correspond à la partie privée du module représenté par la UNIT. Cette partie intimement liée à l’interface, contient le code interne du module. Elle contient deux sortes d’éléments : les déclarations complètes des procédures et des fonctions privées ainsi que les structures de données privées. Elle contient aussi les déclarations complètes des fonctions et procédures publiques dont les en-têtes sont présentes dans l’interface.
Syntaxe :
Exemple
:
Unit Truc ; |
2.3 Partie initialisation d’une UNIT
Il est possible d'initialiser des variables et d'exécuter des instructions au lancement de l'UNIT. Elles correspondent à des instructions classiques Pascal sur des données publiques ou privées de la Unit (initialisation de tableaux, mise à zéro de divers indicateurs, chargement de fichiers etc...):