En route vers Embedded World 2021 : épisode 4
Note de l'éditeur : Dans l'Épisode 1 de cette série de cinq blogs précédant le salon Embedded World 2021, nous avons présenté cet événement. Dans l'Épisode 2, Randall s'est replongé dans le langage de programmation C. L'Épisode 3 a expliqué comment l'utilisation de la programmation orientée objets permet de réduire la complexité. Cet Épisode 4 se concentre sur la mesure fondamentale de toute bonne conception, à savoir sa capacité à être reconfigurée à mesure que les exigences changent, et ce, sans avoir à réimplémenter les blocs fonctionnels. Dans le dernier article, l'Épisode 5, l'espace toujours plus important requis par les systèmes d'exploitation est remis en cause et la décomposition du système est brièvement abordée avant l'allocution d'ouverture de Randall au salon Embedded World 2021.
Jusqu'ici, j'ai abordé l'évolution des logiciels jusqu'à leur état actuel, c'est-à-dire orientés objets, et j'ai expliqué en quoi la programmation orientée objets était comparable à l'électronique. Réfléchir avec un état d'esprit orienté objets permet de créer des modèles de substitution des choses du monde réel (c.-à-d. des objets). J'ai également parlé des attributs de la programmation orientée objets (OOP) et des méthodes pour évaluer la qualité de ces modèles, mais je n'ai pas parlé des méthodes pour établir ces modèles. Cela concerne la façon de décomposer un système en modules et en blocs fonctionnels utiles. Il s'agit d'un domaine de la méthodologie de conception qui a été abordé dans des ouvrages au début des années 1970, dont quelques-uns refont surface aujourd'hui.
Le moyen le plus populaire de diviser un système est certainement par fonction. Cela consiste à répertorier toutes les fonctions requises dans un système en tant que blocs fonctionnels et à désigner des développeurs chargés d'implémenter ces blocs. Il s'avère qu'il ne s'agit pas du meilleur moyen de concevoir un système. Il comporte de nombreux pièges qui entraînent un manque de flexibilité et du travail supplémentaire pour les développeurs. Un système conçu par décomposition fonctionnelle est viable, mais il existe un meilleur moyen. Il est vrai que cet autre moyen est à la fois complexe et plus difficile à mettre en place. Il nécessite plus de temps au début, mais ensuite le développement se fait de manière plus fluide et génère un système capable de s'adapter plus facilement aux changements.
David L. Parnas, source : Wikipédia (https://en.wikipedia.org/wiki/David_Parnas)
David Parnas, de l'Université Carnegie-Mellon, a écrit plusieurs articles sur la conception et la modularité des systèmes en 1971. Ces articles ont aidé à établir les notions de couplage et de cohésion que j'ai mentionnées dans mon précédent article de blog. L'un de ces articles s'intitulait « Information Distribution Aspects of Design Methodology » (aspects de la méthodologie de conception liés à la distribution des informations) et a été rédigé en février 1971. Il s'agit d'un court article, mais très détaillé, qui décrit ce qu'est une méthodologie de conception. Il explique que le progrès dans une conception est marqué par les décisions qui éliminent certaines possibilités quant à la structure du système. Il dit qu'en éliminant des possibilités, on établit une logique pour les décisions ultérieures, et il fournit des exemples pour appuyer ses arguments. Ces méthodologies créent chacune une convergence vers une solution.
Il a identifié trois approches :
1. Obtenir de « bonnes » considérations externes
2. Réduire l'intervalle entre le lancement et l'achèvement d'un projet
3. Obtenir un système facilement modifiable
L'approche 1 est liée à une approche « du sommet à la base ». L'approche 2 génère des choix effectués à propos de la modularisation qui ne tiennent peut-être pas compte de l'impact sur l'utilisation finale du produit, mais permet aux développeurs de se lancer plus vite dans le développement. L'approche 3 identifie les facteurs les moins susceptibles de changer, en utilisant les informations les plus générales en premier.
Il affirme qu'une approche du sommet à la base peut générer des systèmes plus difficiles à modifier plus tard, simplement du fait que les critères de décision favorisent les facteurs externes plutôt que ceux qui donnent lieu à des changements. Il conclut cette section de son article en disant que l'ordre des décisions prises dans ces approches est incohérent et qu'il est donc impossible de toutes les satisfaire simultanément. Cette position est reprise dans son article suivant, que je vais présenter. Mais je souhaite d'abord conclure mes commentaires sur son premier article.
Je trouve intéressantes ses descriptions des bons programmeurs. Il déclare qu'un bon programmeur exploite les informations utilisables à sa disposition. Il continue en disant qu'un bon programmeur doit faire preuve d'ingéniosité et peut utiliser des informations qui ne sont pas documentées, et que cette approche signifie qu'un changement dans un bloc nécessite des changements dans les autres. Il s'agit de l'idée de « connascence » que j'ai mentionnée dans ma dernière publication et qui est incohérente avec l'approche 3. Il ressort de ce premier article que le masquage d'informations est une bonne chose, ce qui signifie que les concepteurs de système doivent partager les informations de conception sur la base du besoin de savoir, comme le dit David Parnas.
David Parnas a poursuivi avec l'écriture d'un autre article intitulé « On the Criterion to Be Used in Decomposing Systems into Modules » (critère à utiliser dans la décomposition des systèmes en modules) en août 1971. Cet article a acquis une grande notoriété et connaît aujourd'hui une sorte de renaissance. C'est dans cet article qu'il explique la conception de systèmes basée sur la probabilité de changements, c.-à-d. l'approche 3 de son précédent article.
Son objectif était d'améliorer la flexibilité et l'intelligibilité des systèmes tout en réduisant leur temps de développement total, et il a utilisé des exemples pour montrer qu'on pouvait réussir à le faire. En modularisant le code sur la base du masquage d'informations, on modularise un système sur la base de la gestion des changements. Les changements sont isolés et se limitent à certains modules seulement, ce qui signifie qu'il est plus facile d'opérer des changements et des reconfigurations du système lorsque les exigences changent. Que l'on utilise la décomposition fonctionnelle ou la décomposition des changements, un système peut fonctionner, mais en garantissant une cohésion élevée sur la base du maintien des informations cachées, un système est rendu plus flexible, plus intelligible, et développé plus rapidement.
Prenez par exemple le cas d'un élément bien connu sur une structure donnée qui est stocké en mémoire. Si un système est décomposé fonctionnellement, un module ou tous les modules peuvent fonctionner dessus. Si la structure est modifiée, tous les modules qui y accèdent doivent l'être aussi. Cependant, si cette structure est gérée par un module chargé de fournir l'accès, la structure peut être modifiée sans qu'il ne soit nécessaire de modifier tous les modules qui ont besoin d'y accéder. Dans cette méthodologie, le concepteur identifie dès le début les éléments susceptibles d'être modifiés. Chaque méthodologie produit la même fonctionnalité, mais c'est la modularité qui est différente. David Parnas pense qu'une modularité basée sur les changements est plus efficace pour révéler les décisions de conception qu'une modularité basée sur les fonctions, et qu'elle permet donc à un système d'être plus facilement compréhensible.
La modularisation basée sur le masquage d'informations n'est pas sans risques. David Parnas souligne que les systèmes conçus de cette façon peuvent être inefficaces, mais fait remarquer qu'il devient plus important de masquer certaines informations à mesure qu'un système se développe. Je parlerai des risques dans ma prochaine publication.
D'un point de vue plus fondamental, pour améliorer la réutilisation d'une fonctionnalité, l'interface associée à cette fonctionnalité doit révéler le moins d'informations possible. Pour reprendre une citation d'Albert Einstein, « Tout doit être aussi simple que possible, mais pas plus simple. » Dans notre cas, nous devons remplacer « tout » par « l'interface ». Cette tâche convient très bien à un ingénieur de système embarqué. L'ingénieur de système embarqué est formé à de nombreuses techniques, ce qui lui permet de travailler à n'importe quel niveau d'une conception par rapport à une personne non qualifiée. Les conceptions d'un ingénieur doivent être aussi simples à utiliser que possible si elles sont destinées à être utilisées par le plus grand nombre d'utilisateurs (c.-à-d. les clients).
Source : https://rightingsoftware.org/
Comme je l'ai mentionné plus haut, le travail de David Parnas connaît une sorte de renaissance. J'invite tous ceux qui souhaitent en savoir plus à lire les articles de David Parnas, ainsi que le livre intitulé « Righting Software » de Juval Löwy.
Juval Löwy attribue à David Parnas son approche, qui consiste à créer l'architecture d'un système en le décomposant en tenant compte de la volatilité des changements potentiels, et à encapsuler ces changements potentiels dans des blocs fonctionnels. Le comportement requis du système est alors implémenté en tant qu'interaction entre ces blocs fonctionnels. Une conception réussie comporte le plus petit ensemble de blocs fonctionnels capable de répondre à tous les cas d'utilisation. C'est facile à dire.
Juval Löwy explique qu'il faut créer cet ensemble en connaissant les principaux cas d'utilisation. Il ajoute que ces cas ne sont jamais très nombreux, de l'ordre de 1 à 3, ce qui entraîne généralement moins d'une douzaine de composants. Le nombre de compositions et d'interactions de 12 éléments est énorme. Je pense à la variété de chansons qui peuvent être composées à partir de 12 notes sur un instrument de musique. Il y a la séquence des notes et leur rythme, alors je pense qu'il a raison.
Il poursuit en disant qu'un humain d'il y a 200 000 ans n'avait pas un cas d'utilisation différent de celui que nous avons aujourd'hui. Ce cas d'utilisation, c'est la survie, et l'architecture qui a permis cela par la chasse et la cueillette est la même (c.-à-d. qu'elle utilise les mêmes composants) que celle qui permet aujourd'hui à un ingénieur logiciel de gagner sa vie. Il soutient qu'un éléphant et une souris ont la même architecture, mais que les différences résident dans leur conception détaillée. Voilà un argument convaincant.
Pour résumer, la mesure fondamentale d'une bonne conception est sa capacité à être reconfigurée à mesure que les exigences changent, et ce, sans avoir à réimplémenter les blocs fonctionnels. Une décomposition réussie satisfait toutes les exigences : passées, futures, connues et inconnues. Il s'agit d'un vaste sujet qui vaut la peine d'être étudié.
Dans ma dernière publication, comme je l'ai mentionné, je décrirai un problème que nous avons créé en permettant à davantage de personnes d'utiliser les fonctionnalités que nous avons développées, mais j'expliquerai aussi que c'est le prix à payer pour accéder à de plus vastes marchés.

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum