Quelques enseignements essentiels après 20 ans en ingénierie logicielle

Lorsque j’ai commencé ma carrière en tant qu’ingénieur logiciel il y a vingt ans, je n’aurais jamais pu imaginer l’évolution incroyable que notre domaine allait connaître. L’industrie des technologies de l’information a constamment progressé dans des directions variées, de l’émergence des méthodologies agiles à l’essor du cloud computing, en passant des applications monolithiques aux architectures microservices, et parfois même un retour en arrière. Malgré ces changements permanents, j’ai découvert que certains principes fondamentaux ont su résister à l’épreuve du temps. Ces leçons sont aujourd’hui encore plus pertinentes dans un environnement de plus en plus complexe en ingénierie logicielle.Dans ce billet, je vais partager dix enseignements cruciaux que j’ai tirés au cours de mes 20 années de carrière. Ces principes m’ont aidé à naviguer dans de nombreux projets, à diriger des équipes, et à progresser professionnellement. J’espère qu’ils vous offriront des perspectives essentielles et un regard neuf sur notre métier. 1. Évitez l’optimisation prématurée On se souvient tous de la célèbre citation de Donald Knuth : « L’optimisation prématurée est la source de tous les maux (ou du moins la plupart) en programmation. » Au début de ma carrière, je suis tombé dans le piège de l’optimisation prématurée plus souvent que je ne voudrais l’admettre. J’ai passé des semaines à développer un système de gestion de documents pour des millions d’utilisateurs, pour ensuite découvrir que nous avions à peine un millier de visiteurs par mois. J’ai aussi mis en place des modèles d’accès aux données très sophistiqués pour prendre en charge plusieurs bases de données, alors que seules deux ou trois étaient réellement utilisées.Cela m’a enseigné une leçon importante : il est inutile de construire des abstractions complexes si vous n’allez pas les utiliser. Concentrez-vous sur l’écriture de code simple qui répond aux besoins actuels.L’optimisation prématurée peut mener à des solutions surdimensionnées, plus difficiles à maintenir et à comprendre. Suivre les principes  YAGNI (You Ain’t Gonna Need It) KISS (Keep It Simple, Stupid) DRY (Don’t Repeat Yourself)  dans cet ordre est crucial. Implémentez seulement ce qui est nécessaire au moment où vous en avez besoin.Garder le code simple et clair est essentiel. Quant à la répétition, elle est parfois inévitable dans certains cas, par exemple, lorsqu’une logique partagée est utilisée dans différents contextes. 2. Réfléchissez avant d’écrire du code En tant qu’ingénieurs, nous avons tendance à penser que tous les problèmes se résolvent avec du code. Pourtant, au fil des ans, j’ai appris que parfois la meilleure solution ne nécessite pas de code supplémentaire.Avant d’ajouter une nouvelle fonctionnalité, demandez-vous : « Est-ce vraiment nécessaire ? Peut-on résoudre ce problème sans ajouter du code ? » Chaque ligne de code que vous écrivez devient une responsabilité : elle devra être maintenue, testée, et potentiellement déboguée.N’oubliez pas que votre objectif est de résoudre des problèmes et de créer de la valeur, et non pas simplement de coder. Parfois, la solution la plus efficace et la plus simple consiste à écrire moins de code, voire pas du tout. Réfléchissez donc deux fois avant d’écrire une seule ligne ! 3. Adoptez de bonnes pratiques Tout au long de ma carrière, j’ai constaté qu’adhérer aux bonnes pratiques améliore la qualité du code, la productivité de l’équipe, et le taux de réussite des projets. Cependant, j’ai aussi appris qu’appliquer ces pratiques de manière aveugle, sans comprendre leur contexte, pouvait s’avérer contre-productif.Quand je parle de bonnes pratiques, je fais référence à : Clean Code : Suivez les principes du livre « Clean Code » de Robert C. Martin pour écrire un code plus lisible et maintenable. Toutefois, ne les appliquez pas aveuglément, certaines idées vieillissent mieux que d’autres. Les Design Patterns : Comprenez les modèles de conception et appliquez-les de manière adéquate. Ne les forcez pas là où ils ne sont pas nécessaires, sous peine de rendre votre projet inutilement complexe. Les principes SOLID : Ils permettent de rendre votre code plus modulaire et maintenable, mais, là encore, ne soyez pas trop rigide dans leur application. L’idée n’est pas de suivre ces pratiques de manière rigide, mais plutôt de comprendre quand et comment les utiliser de manière judicieuse. (Single Responsibility) Principe de responsabilité unique : Une classe ou un module ne doit avoir qu’une seule raison de changer, ce qui signifie qu’il ne doit avoir qu’un seul travail ou responsabilité. (Open-Closed) Principe d’ouverture-fermeture : Les entités logicielles doivent être ouvertes à l’extension mais fermées à la modification, permettant d’étendre leur comportement sans modifier le code existant. (Liskov Substitution) Principe de substitution de Liskov : Les objets d’une superclasse doivent pouvoir être remplacés par des objets d’une sous-classe sans affecter la validité du programme. (Interface Segregation) Principe de ségrégation des interfaces : Les clients ne doivent pas être obligés de dépendre d’interfaces qu’ils n’utilisent pas ; les interfaces doivent être spécifiques aux besoins des clients. (Dependency Inversion) Principe d’inversion des dépendances : Les modules de haut niveau ne doivent pas dépendre des modules de bas niveau ; les deux doivent dépendre d’abstractions plutôt que d’implémentations concrètes. 4. Simplifiez toujours plus « Faites les choses aussi simples que possible, mais pas plus simples. » Cette citation souvent attribuée à Albert Einstein m’a toujours guidé dans la conception logicielle.Lorsque vous construisez ou concevez un logiciel, ne le compliquez pas inutilement. Optez pour des solutions faciles à comprendre. Le monde du logiciel est déjà suffisamment complexe ; il n’est pas nécessaire d’ajouter davantage de complications.La simplicité a de nombreux avantages : Un code simple est plus facile à lire, à comprendre et à maintenir. Les systèmes simples comportent moins de points de défaillance. La simplicité permet un développement plus rapide et un débogage facilité.Bien entendu, il faut trouver un juste équilibre entre simplicité et fonctionnalité. Ne sacrifiez pas les fonctionnalités nécessaires sous prétexte de vouloir garder les choses trop simples. 5. Nommez correctement Phil Karlton a dit : « Il n’y a que deux choses vraiment difficiles en informatique : l’invalidation du cache et nommer les choses. » J’ai appris à quel point cela est vrai.Bien nommer les éléments dans votre code a un impact énorme. Cela réduit la charge cognitive…

Onyx Solution – Une Mini-Formation sur l’Architecture Logiciel

Onyx Solution https://github.com/YannVasseur35/Onyx Onyx Solution Une solution Microsoft .net 7.0 / C# permettant l’apprentissage de concepts de software design, d’architecture, de clean code, de tests… Permet de partir sur de bonnes bases pour un petit/moyen projet, basé sur quelques années d’expériences dans le software design. Onyx est une pierre précieuse de couleur noire. J’ai donnée ce nom à ce projet d’apprentissage car il est court, facilement identifiable, abstrait, et j’aime bien donner des « noms de code » à un projet. On va prendre comme exemple une application de météo (qui est d’ailleurs l’exemple par défaut d’une application .net web) on aura donc Une API qui expose des données une base de données SQLite avec EntityFramwork (code first) Une clean architecture avec de nombreux tests + code coverage CI/CD avec une pipeline AzureDevops Introduction On a tous commencé par écrire un seul projet c# et tout mettre dedans, sans vraiment rien structurer. Alors oui, ça marche et honnêtement vu les ambitions de cette app méteo c’est ce que l’on devrait faire. Et puis comme tout bon projet, il évolue, en quelques années tout un tas de nouvelles fonctionnalités se sont ajoutés, plusieurs devs sont passés dessus, avec du code plus ou moins clair. De plus avec le temps, l’infrastructure a changé, on a fait évoluer la base de données, certain services sont directement sur le cloud et on a du faire face à de la montée en charge. On a du « scaler » l’application, recoder des parties, ajouter du cache etc…Et bien entendu rien n’est testé automatiquement. Bref la vie d’une application dans pas mal de boite en France et ailleurs dans le monde. Je développe avec .net depuis plus de 20 ans. Et j’ai vu un certain nombre d’application (un bon paquet à vrai dire) finir dans ce que l’on appelle un « monolith legacy », très très dure à maintenir. Ces applications existent encore à l’heure ou j’écris ces lignes. Parfois on en est au deuxième projet de « refonte ». Un cas typique est celui du projet ou l’on retrouve toute la logique métier dans les procédures SQL. Car c’est ce qui faisait vraiment gagner en pref à l’époque (et encore aujourd’hui). Mais seule la personne en charge de ces procédures stockées, souvent indéchiffrable et intestable, est en mesure de travailler dessus. Autre cas bancale, on a de la logique métier dans les pages web. Du coup on se retrouve à gérer à plusieurs endroits, du code qui fait plus ou moins la meme chose, au risque qu’un jour il ne fasse plus la même chose ! Heureusement aujourd’hui on a énormement plus de techniques, d’outils et de services qui permettent d’appréhender les projets autrement. Les entreprises comprennent les enjeux et les risques de garder trop longtemps du code legacy en production et s’engagent dans de gigantesque chantier de « renovation » voir même de ré-écriture complète. J’ai moi aussi contribuer à ces erreurs et je contribue aussi à leurs résolutions. Ce projet tente modestement de répondre à certaines problématiques couramment vues en entreprise. Je ne prétends pas tout résoudre mais apporter quelques réponses à des questions que moi même je me suis posé. Et à vrai dire, le meilleurs moyen d’y répondre pour moi est de tenter de le faire comprendre à quelqu’un d’autre. J’ai donc entrepris ce projet Onyx. Progression Vous avez deux façons de voir les choses : la rapide. Restez sur la branche master, la plus à jour et dernière en date. Vous avez tout le code source et tous les tests. Regardez le code et inspirez-en vous, prennez ce qui vous intéresse. l’apprentissage. Ce sera plus lent, mais j’explique tous les concepts pas à pas. On démarre gentillement et on progresse par étape (step). C’est une sorte de TP (travaux pratique) qu’on faisait à l’école. Pour suivre ce TP il faudra « naviguer » avec Git de branche en branche. C’est simple, toutes les branches s’appellent ‘step’ suvit d’un numéro. Chaque step aura sa propre doc (ex: step2.md). Suffit de s’y référer pour comprendre ce qu’y a été fait à chaque étape. Sommaire Step1 : Structure de solution Step2 : Premier endpoint Api Step3 : Test endpoint Api Rest Step4 : Application Service et Tests Step5 : DataService et Tests Step6 : Mapping et Tests Step7 : ORM (Entity Framework) et Tests Step8 : Entity Framework Step9 : Finalisation de la chaine de données Step10 : Code Coverage Step11 : CRUD : Implémentation et Tests Step12 : Tests d’intégration Step13 : CI/CD AzureDevops Pipeline Step14 : Pipeline avec Code Coverage Git Repo : https://dev.azure.com/ReactorLab/_git/Onyx Vous devrez connaitre quelques commandes git de base très simple pour « naviguer » dans les branches de ce repo. Pour changer de branche : git checkout step1 Si vous avez fait des modifications et que vous souhaitez changer de branche, git va vous obliger à faire un commit ou à vous débarraser de ces changements. Comme vous ne contribuez pas au projet, débarrassez vous de vos changements avec la commande stash, puis faites votre checkout git stash git checkout step2 Documentations Annexes Vous trouverez des informations complémentaires sur différents concept d’architecture ici (en anglais): Main Architecture Hexagonal Architecture DDD CQRS AND ES SOLID Tout est dans le répertoire docs.