Bonjour,
Dans le cadre d’une application professionnelle, j’essaye de concevoir une application orientée objet en C++14 dans la mesure du possible.
Ayant plus l’habitude d’un C procédural ou C objet très limité, je voudrais vérifier que je ne peux pas mieux faire dans la conception de l’application actuelle.
En gros c’est une application qui collecte via différents capteurs des données sur une carte électronique embarquée et envoie régulièrement les données par MQTT sur un serveur distant.
Résultant j’ai une classe principale avec une boucle infinie qui s’occupe de gérer la séquence principale et de faire dialoguer au maximum les composants entre eux (en gros récolter les données des capteurs, les injecter dans des variables pour ensuite les sauvegarder ou les envoyer avec au milieu des opérations sur le matériel).
Cependant l’application est configurée par un gros fichier XML. Résultat j’ai une classe importante qui lit ce fichier pour ensuite remplir des structures de données exploitables. Cette classe peut générer des objets lui même à partir de ces éléments, et la classe principale peut aussi récupérer ces données pour les injecter dans d’autres objets (globalement presque tous les objets du logiciels sont liés à ces paramètres, mais la quasi totalité n’attendent qu’une structure de donnée dans leur constructeur pour les utiliser). Le but est de circoncire l’usage de cette classe qu’à ces deux endroits. Mais je ne sais pas s’il y a mieux pour gérer la problématique de la configuration.
Ensuite, et je pense que c’est mon principal soucis, j’ai globalement deux classes en accès global. L’un lié au matériel (qui possède les accès vers les GPIO, les LEDs ou les lignes séries), l’autre au MQTT. En effet, le matériel ou le MQTT peuvent servir à récupérer des informations utiles d’une part, mais surtout à en envoyer d’autres comme des erreurs ou des données. Si j’essaye d’utiliser au maximum la classe principale pour gérer cela, ce n’est pas toujours possible.
Je sens que c’est un peu bancal comme idée mais j’ai beau chercher (sur Internet ou dans mon cerveau), je ne parviens pas à une meilleure conception pour éviter ces appels.
Pour que ce soit plus clair, je vais donner le niveau d’abstraction de ces objets.
La classe "Matériel" initialise le matériel et "le découvre". En gros il possède plusieurs map qui fait le lien entre une fonction et une instance du matériel. Suivant le type de matériel, les objets clients peuvent manipuler le matériel à travers celui-ci quand c’est simple (genre si je veux allumer la LED des erreurs, le client appelle une méthode du genre Hardware::setGPIO(LED_ERROR, true), LED_ERROR étant un nombre énuméré. Le client ne sait pas ce qu’est la classe Led en l’occurrence et ne sait d’eux que les énumérations liées à leur fonction pour savoir laquelle utiliser.
La classe MQTT gère la connexion / déconnexion / souscription / reconnection / envoie d’un message. Après un thread interne se charge d’envoyer les données quand la connexion est établie ou de sauvegarder les données en attendant si ce n’est pas le cas. Globalement les clients n’utilisent que la fonction pour envoyer un nouveau message (en gros un topic de destination + un message).
Voilà, je connais les principes SOLID, les design pattern et tout mais c’est souvent assez abstrait et si cela peut mettre en évidence un défaut de conception, cela n’apporte pas forcément une solution simple pour y remédier. En l’occurrence je sens que mon architecture est améliorable mais j’ignore comment. Si vous avez des idées, je suis preneur.
Merci.