Développements logiciels

Les développements dit de logiciels sont ceux que l’on peut installer sur les ordinateurs personnels, sur une tablette ou un téléphone cellulaire. Chez Innovation Codotek nous développons du code qui est SOLID, qui est maintenable et testable, qui ne nécessite pas de documentation explicite et qui se base sur des modèles de conception connus. Au final, n’importe quel programmeur peut reprendre notre code et le comprendre facilement. Vous acheter nos services, on vous livre du code de qualité. Pas de boîte noire, pas de secrets!

Un code qui est SOLID

SOLID est un acronym qui désigne 5 concepts clefs de la programmation orientée objet.

  • S — Single responsibility principle
  • O — Open/closed principle
  • L — Liskov substitution principle
  • I — Interface segregation principle
  • D – Dependency inversion principle

Single responsibility principle

Le principe de la responsabilité unique spécifie que chaque module ou classe ne devrait faire qu’une seule chose. Le respect de ce critère apporte deux avantages bien importants.

Premièrement, comme chaque module ou classe ne fait qu’une chose, la complexité du logiciel est morcelée. Les sections de code simples sont alors facilement testables. En effet, il est primordial d’avoir une couverture de test qui suit le développement du logiciel. Notons, que la création d’un logiciel n’est pas linéaire. On écrit beaucoup de code que l’on modifie ou que l’on détruit par la suite. Les tests unitaires sont alors extrêmement utiles pour vérifier le code après chaque modification. On teste la présence de régression et l’on s’assure que les fonctionnalités de bases sont toujours présentes.

Deuxièmement, comme chaque partie est simple et ne fait qu’une chose, il est aussi facile de comprendre le code. On lit et relit très souvent notre code ou celui des autres. Un code qui s’auto-documente possède alors un très grand avantage. En effet, aucun texte ne peut rivaliser en terme de clarté avec un code bien écris qui se lit comme une histoire.

Open/closed principle

Le code doit être ouvert pour des extensions, mais fermé pour des modifications. Les modules ou classes de bases peuvent être améliorées ou précisées par d’autres classes qui les modifient. Cependant, il faut éviter que les changements ou les ajouts à ces classes nécessitent aussi des changements aux classes de bases ou à d’autres classes.

Plus simplement, il faut définir des interfaces de bases qui sont générales de façon à garder les classes indépendantes.

Liskov substitution principle

Le principe de substitution de Liskov signifie qu’une classe enfant peut remplacer son parent sans que le logiciel ne cesse de fonctionner.

La meilleure façon de respecter ce principe est d’éviter d’hériter d’une classe parent alors que la classe enfant n’est pas vraiment du même type. Par exemple, l’héritage de classe abusif contribue à une explosion de fonctions vides qui existent seulement parce que l’interface le demande.

Interface segregation principle

Le principe de ségrégation des interface déclare qu’il ne faut pas forcer des classes à implémenter des interfaces qu’ils n’utilisent pas. La façon la plus simple de reconnaître que l’on viole ce principe est de rester vigilent lorsque l’on ajoute des fonctions à des interfaces. Si une interface possède trop de fonctions, il faut vérifier si on ne peut pas séparer l’interface en des version plus petites et plus précises.

Dependency inversion principle

  1. Les modules de haut niveau ne devraient pas dépendre des modules de bas niveau. Les deux devrait dépendre d’abstraction.
  2. Les abstractions ne devraient pas dépendre des détails. Les détails devraient dépendre des abstractions.

Pour faire simple, le code devrait minimiser le couplage entre les classes. Une bonne façon de le vérifier est de toujours se demander quelles classes serait à modifier si on ajoutais des fonctionnalités du même type au logiciel. La réponse devrait toujours être une ou zéro.

Code qui est maintenable et testable

Tout code est modifié ou amélioré un jour ou l’autre. En fait, on passe autant de temps (sinon plus) à relire notre code qu’à en écrire des nouveaux. Pour cette raison, le système doit permettre une maintenance facile. La meilleure façon est de respecter les principes d’un code SOLID et de prendre autant de soin à rédiger le code qu’à construire un système de test.

On parle ici d’un ensemble de tests unitaires qui peuvent vérifier rapidement l’ensemble du système. Il ne faut pas oublier des tests systèmes et d’intégrations formalisés à faire à des moments précis.

Modèles de conception du code

L’utilisation de modèles de conception connus permet de réaliser des structures de codes efficaces respectant les principes SOLID. De sorte que d’autres codeurs peuvent facilement reconnaître le fonctionnement d’un système. On renforce ici les principes du code qui s’auto-documente et du code qui est maintenable et testable.

Essentiellement, il existe plusieurs types de modèles de conception qui s’appliquent à des situations bien différentes les unes des autres. Une bonne ressource pour bien comprendre les techniques qu’Innovation Codotek utilise se trouve ici.

Technique globale

Voici le processus de conception dans sa forme la plus simple.

  • On commence par évaluer comment ajouter du code en respectant l’architecture présentée.
  • La première version du code dans une classe donnée ou une fonction s’écrit alors sans égard à la clarté ou à la structure. À cette étape, on crée quelque chose de nouveau qui exige un effort assez considérable en soit. Polir immédiatement le code ou implémenter les modèles de conception dès le départ imposerait une difficulté supplémentaire qui limiterait la créativité et au final l’innovation.
  • Une fois le code écrit et fonctionnel, on crée une série de tests unitaires. Ces derniers couvrent l’ensemble des niveaux logiques, des fonctionnalités et finalement des cas limites et des erreurs possibles.
  • Par la suite, on peut modifier le code, le détruire, le reconstruire, le séparer en plusieurs classes tout en en s’appuyant sur les tests unitaires développés. Bref, on polit le code pour en faire ressortir les concepts de base de la programmation SOLID et pour s’assurer que le code s’auto-documente.
  • Une fois satisfait, on passe au problème suivant.

Code embarqué

Les codes embarqués pour FPGA ou pour microcontrôleurs ne sont, la plupart du temps, pas orientés objets. La réutilisation du code est alors plus difficile. Cette réalité ne fait pas en sorte que les principes de bases doivent être exclus. Le code doit être maintenable, il doit aussi évoluer avec toute sa chaîne de test unitaires et d’intégration. De la même façon, le code doit s’auto-documenter et être explicite.

Cependant, ce type de code apporte des difficultés supplémentaires qui peuvent venir de la limitation des langages et souvent, de la complexité accrue des développements.

Ainsi, l’ingénierie système réalisée en amont devient beaucoup plus importante. De la même façon, plus de temps doit être passé à faire des diagrammes UML pour bien planifier l’architecture. Il est effectivement plus facile de construire un code déstructuré dans un langage comme le Vérilog ou le C.

Dans le cas de la programmation de FPGA, une attention particulière doit être mise pour la réalisation des state machines et des diagrammes d’activités. Ces derniers sont très utiles pour bien guider les développements de code FPGA plus complexes.