4.3.modularité



Plan du chapitre:

Introduction

1. Modularité

     
    1.1 Notion de module

    1.2 Critères principaux de modularité
      La décomposabilité modulaire
      La composition modulaire
      La continuité modulaire
      La compréhension modulaire
      La protection modulaire

    1.3 Préceptes minimaux de construction modulaire
      Interface de données minimale
      Couplage minimal
      Interfaces explicites
      Information publique et privée

2. La modularité par les unit en pascal UCSD
     
    2.1 Partie " public " d’une UNIT : " Interface "
    2.2 Partie " privée " d’une UNIT : " Implementation "
    2.3 Partie initialisation d’une UNIT



  1. Modularité (selon B.Meyer)
 

1.1 Notion de module

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 :
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 ;
....
for i :=1 to n do ....
...
if T1 < n then ....

Il suffit de changer la ligne const n=10 pour modifier automatiquement les instructions où intervient la constante n, sans avoir à les réécrire toutes. Cette pratique en Pascal est très utile en particulier lorsqu’il s’agit de compenser le défaut dans la continuité modulaire, apporté par la notion de tableau statique dont les bornes doivent être connues à l’avance.
 
 

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.

  Réalisation de ce précept en Pascal :
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;
    <partie public>
    <partie privée>
    <initialisation>
    end.

     

    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 ;
    interface
    Uses Machin, Chose;
    const
      a=10;
      x='a';
    Type
      amoi=12..36;
    var
      x,y:integer;
      z:amoi;
    implementation

    end.


     

    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 ;
    interface
    Uses Machin, Chose;
    const
      a=10;
      x='a';
    Type
      amoi=12..36;
    var
      x,y:integer;
      z:amoi;
    procedure P1(x:real;var u:integer);
    procedure P2(u,v:char;var x,y,t:amoi);
    function F(x:real):boolean;

    implementation

    procedure P1(x:real;var u:integer);
    begin
    < corps de procédure>
    end;

    procedure P2(u,v:char;var x,y,t:amoi);
    begin
    < corps de procédure>
    end;

    function F(x:real):boolean;
    begin
    < corps de fonction>
    end;

    end.


     

    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...):