Axe fonctionnel / structurel
Définition : Description de l'axe
Cet axe permet de détailler les parties matérielles par les :
Diagrammes de blocs (bdd).
Diagrammes de blocs internes (ibd).
Diagrammes de paquetage (pkg).
Pour décrire la partie logicielle, on utilisera le diagramme :
De classes du langage UML (cd).
Décrivons la partie matériel :
Le diagramme de blocs (bdd)
Ce diagramme montre de quoi est composé le système : les matériels représentés sous forme de blocs, leurs ports de communication, les parties de chaque bloc intéressant à détailler.
Le diagramme de blocs internes ci-dessous met en évidence les liaisons internes entre blocs.
Le bloc carte d'interface est intéressant à détailler car c'est lui qui fait l'objet de la réalisation électronique.
On fera donc ensuite un diagramme de blocs internes pour ce bloc.
Ce diagramme est assez proche du diagramme de déploiement d'UML montré précédemment.
Le diagramme de blocs internes (ibd) de la carte d'interface
Conception de la carte d'interface
Nous avons à présent tous les éléments pour établir le schéma structurel de la carte d'interface.
Il ne faudra pas oublier de tenir compte des contraintes de dimension pour réaliser le routage de cette carte.
En effet, la carte Raspberry peut disposer de radiateurs qui sont assez hauts, et d'un boitier qui limitent les dimensions de la carte d'interface.
Choix des capteurs
Nous avons choisi les capteurs en fonction de leur prix ainsi que du bus de communication avec lequel ils fonctionnaient pour disposer d'une diversité de moyens de communication.
Le critère précision n'a pas été retenu car il s'agit simplement d'un système à usage pédagogique dédié à la programmation.
Diagramme de classe (cd)
Ce diagramme est essentiel pour structurer le programme informatique. Il appartient au langage UML.
Cependant, il peut être remplacé par un diagramme de blocs (bdd) dans lequel chaque bloc représente une classe.
Remarque : Structurer un programme informatique, quel défis !
Définir une organisation informatique sous forme de classes n'est pas facile, même lorsqu'on a de l'expérience.
Voici une méthode simple car elle est proche de notre mode de pensée naturelle :
Lister les objets dont on aura besoin. On distingue les objets généraux (qui peuvent s'utiliser dans d'autres contextes) et les objets métiers (qui sont spécifiques au système). Un objet peut correspondre à un matériel, bus de communication, gestion mémoire, etc).
Définir les caractéristiques et comportements principaux de chaque objet (attributs et méthodes).
Définir les classes décrivant chaque objet.
Définir les relations entre les classes (association, composition, agrégation, héritage).
Enfin, caractérisez chaque relation en indiquant les directions, cardinalité, rôle.
La structure informatique de l'application est née. Il ne reste plus qu'à coder.
Vous vous apercevrez peut-être qu'il faudra affiner le modèle car :
Vous avez oublié un objet donc la classe le représentant.
Une classe se révèle inutile finalement.
Les relations finales entre les classes ont changé car vous avez acquis une idée plus précise en fin de développement.
Bon ! maintenant, il faut se lancer !
Définition des classes
Si nous résumons, notre application :
Communique avec des périphériques (capteurs, écran, LED, bouton, client, serveur, SGBD), chacun ayant sa manière de communiquer (RS232C, I2C, SPI, GPIO).
Les données recueillies sont affichées à intervalle régulier sur l'IHM de l'application.
Les objets périphériques "capteurs" fonctionnent en tant que thread. Ainsi, chaque objet "capteur" s'exécute indépendamment.
Les mesures acquises sont stockées dans une mémoire partagée (entre les objets de l'application). Ainsi l'objet IHM pourra à sa fréquence propre lire les valeurs et les afficher.
Voilà qui nous permet d'imaginer une organisation informatique sous forme de classes :
Notre classe de gestion de l'objet IHM (
CIhmAppFormQtCpp
). Elle se contente de gérer l'IHM et les interactions avec les autres objets (création, destruction, communication).La classe de gestion du segment de mémoire partagé (
CSharedMemory
).Nos classes périphériques :
CClientTcp
,CServeurTcp
,CBdd
,CLed
,CBoutonPoussoir
,CPeriphRs232
,CCapteur_Spi_TC72
,CCapteur_I2C_SHT20
,CAff_i2c_GroveLcdRgb
.Nos classes de gestion des communications :
CGpio
,CRs232c
,CSpi
,CI2c
.
Le choix a été fait de considérer que la classe IHM (CIhmAppFormQtCpp
) est composée des classes périphériques. Pour rappel, cela signifie que la classe est responsable de la création des objets (instanciation) mais aussi de leur destruction. Cela justifie l'utilisation de relation de composition (losange noir).
On admettra également que les périphériques sont composés d'un moyen de communication. Chaque périphérique est responsable de la création du sous objet de communication et de sa destruction, SAUF pour les objets communiquant par le bus I2C. Cela justifie l'utilisation de relation de composition (losange noir).
La classe I2C étant une classe singleton, seul UN objet sera responsable de la création de l'unique objet CI2c (le premier) et seul UN objet (ce ne sera pas forcément le même) procédera à sa destruction (le dernier utilisateur du sous objet CI2c). Le choix de relation entre les classes "capteurs I2C" et la classe CI2c
est une agrégation (losange blanc).
Fort de cette analyse succincte, notre diagramme de classe prend donc la forme suivante :
Ce diagramme apparaît comme par miracle !
Il est effectivement le résultat de l'expérience du développeur et bien sûr n'est pas forcément la seule solution.
De plus, il a été affiné au fur et à mesure de la réalisation.