Review 'building maintainable applications'
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Fred 2020-12-14 20:34:39 +01:00
parent c8237667fe
commit 7ff40c4167
3 changed files with 15 additions and 11 deletions

View File

@ -24,15 +24,20 @@ Django se présente comme un "link:https://www.djangoproject.com/[Framework Web
Mis côte à côte, l'application de ces principes permet une meilleure stabilité du projet à moyen et long terme. Tout pour plaire à n'importe quel directeur IT.
*Dans la première partie*, nous verrons comment configurer l'environnement, comment installer Django de manière isolée et comment démarrer un nouveau projet. Nous verrons comment gérer correctement les dépendances, les versions et comment appliquer et suivre un score de qualité de notre code. Nous verrons aussi que la configuration proposée par défaut par le framework n'est pas idéale dans la majorité des cas.
*Dans la première partie*, nous verrons comment partir d'un environnement sain, comment le configurer correctement, comment installer Django de manière isolée et comment démarrer un nouveau projet.
Nous verrons rapidement comment gérer les dépendances, les versions et comment appliquer et suivre un score de qualité de notre code.
Nous verrons aussi que la configuration proposée par défaut par le framework n'est pas idéale dans la majorité des cas.
Pour cela, nous présenterons différents outils, la rédaction de tests unitaires et d'intégration pour limiter les régressions, les règles de nomenclature et de contrôle du contenu, comment partir d'un squelette plus complet, ainsi que les bonnes étapes à suivre pour arriver à un déploiement rapide et fonctionnel avec peu d'efforts.
A la fin de cette partie, vous disposerez d'un code propre et d'un projet fonctionnel (mais encore inutile, parce qu'encore vide).
*Dans la deuxième partie*, nous détaillerons précisément les étapes de déploiement, avec la description et la configuration de l'infrastructure, des exemples concrets de mise à disposition sur deux distributions principales (Debian et CentOS), sur une _*Plateform as a Service*_, ainsi que l'utilisation de Docker et Docker-Compose.
Nous aborderons également la supervision et la mise à jour d'une application existante, en respectant les bonnes pratiques d'administration système.
*Dans la troisième partie*, nous aborderons les grands principes de modélisation, en suivant les lignes de conduites du cadre de travail. Nous aborderons les concepts clés qui permettent à une application de rester maintenable, les formulaires, leurs validations, comment gérer les données en entrée, les migrations de données et l'administration.
*Dans la troisième partie*, nous aborderons les grands principes de modélisation, en suivant les lignes de conduites du cadre de travail.
Nous aborderons les concepts clés qui permettent à une application de rester maintenable, les formulaires, leurs validations, comment gérer les données en entrée, les migrations de données et l'administration.
*Dans la quatrième partie*, nous mettrons ces concepts en pratique en présentant le développement de deux "vraies" applications: définition des tables, gestion des utilisateurs, ... et mise à disposition!

View File

@ -1,6 +1,5 @@
== Construire des applications maintenables
include::maintainable-applications/12-factors.adoc[]
include::maintainable-applications/maintainable-applications.adoc[]

View File

@ -1,6 +1,6 @@
=== Construire des applications maintenables
=== Bonnes pratiques
Pour cette section, je me base d'un résumé de l'ebook **Building Maintenable Software** disponible chez link:++O'Reilly++[http://shop.oreilly.com/product/0636920049555.do].
Pour cette section, nous nous basons sur un résumé de l'ebook **Building Maintenable Software** disponible chez http://shop.oreilly.com/product/0636920049555.do[O'Reilly].
Ce livre répartit un ensemble de conseils parmi quatre niveaux de composants:
@ -9,10 +9,12 @@ Ce livre répartit un ensemble de conseils parmi quatre niveaux de composants:
* Les composants
* Et des conseils plus généraux.
Ces conseils sont valables pour n'importe quel langage.
==== Au niveau des méthodes et fonctions
* *Gardez vos méthodes/fonctions courtes*. Pas plus de 15 lignes, en comptant les commentaires. Des exceptions sont possibles, mais dans une certaine mesure uniquement (pas plus de 6.9% de plus de 60 lignes; pas plus de 22.3% de plus de 30 lignes, au plus 43.7% de plus de 15 lignes et au moins 56.3% en dessous de 15 lignes). Oui, c'est dur à tenir, mais faisable.
* *Conserver une complexité de McCabe en dessous de 5*, c'est-à-dire avec quatre branches au maximum. A nouveau, si on a une méthode avec une complexité cyclomatique de 15, la séparer en 3 fonctions avec une complexité de 5 conservera globalement le nombre 15, mais rendra le code de chacune de ces méthodes plus lisible, plus maintenable.
* *Conserver une complexité de McCabe en dessous de 5*, c'est-à-dire avec quatre branches au maximum. A nouveau, si une méthode présente une complexité cyclomatique de 15, la séparer en 3 fonctions avec une complexité de 5 conservera globalement le nombre 15, mais rendra le code de chacune de ces méthodes plus lisible, plus maintenable.
* *N'écrivez votre code qu'une seule fois: évitez les duplications, copie, etc.*, c'est juste mal: imaginez qu'un bug soit découvert dans une fonction; il devra alors être corrigé dans toutes les fonctions qui auront été copiées/collées. C'est aussi une forme de régression.
* *Conservez de petites interfaces*. Quatre paramètres, pas plus. Au besoin, refactorisez certains paramètres dans une classe, plus facile à tester.
@ -22,14 +24,12 @@ Ce livre répartit un ensemble de conseils parmi quatre niveaux de composants:
==== Au niveau des composants
* *Tout comme pour les classes, il faut conserver un couplage faible au niveau des composants* également. Une manière d'arriver à ce résultat est de conserver un nombre de points d'entrée restreint, et d'éviter qu'on ne puisse contacter trop facilement des couches séparées de l'architecture. Pour une architecture n-tiers par exemple, la couche d'abstraction à la base de données ne peut être connue que des services; sans cela, au bout de quelques semaines, n'importe quelle couche de présentation risque de contacter directement la base de données, "juste parce qu'elle en a la possibilité". Vous pourrez également passer par des interfaces, afin de réduire le nombre de points d'entrée connus par un composant externe (qui ne connaîtra par exemple que `IFileTransfer` avec ses méthodes `put` et `get`, et non pas les détails d'implémentation complet d'une classe `FtpFileTransfer` ou `SshFileTransfer`).
* *Conserver un bon balancement au niveau des composants*: évitez qu'un composant **A** ne soit un énorme mastodonte, alors que le composant juste à côté n'est capable que d'une action. De cette manière, les nouvelles fonctionnalités seront mieux réparties parmi les différents systèmes, et les responsabilités plus faciles à gérer. Un conseil est d'avoir un nombre de composants compris entre 6 et 12 (idéalement, 12), et que ces composants soient approximativement de même taille.
* *Tout comme pour les classes, il faut conserver un couplage faible au niveau des composants* également. Une manière d'arriver à ce résultat est de conserver un nombre de points d'entrée restreint, et d'éviter qu'il ne soit possible de contacter trop facilement des couches séparées de l'architecture. Pour une architecture n-tiers par exemple, la couche d'abstraction à la base de données ne peut être connue que des services; sans cela, au bout de quelques semaines, n'importe quelle couche de présentation risque de contacter directement la base de données, "_juste parce qu'elle en a la possibilité_". Vous pourriez également passer par des interfaces, afin de réduire le nombre de points d'entrée connus par un composant externe (qui ne connaîtra par exemple que `IFileTransfer` avec ses méthodes `put` et `get`, et non pas les détails d'implémentation complet d'une classe `FtpFileTransfer` ou `SshFileTransfer`).
* *Conserver un bon balancement au niveau des composants*: évitez qu'un composant **A** ne soit un énorme mastodonte, alors que le composant juste à côté ne soit capable que d'une action. De cette manière, les nouvelles fonctionnalités seront mieux réparties parmi les différents systèmes, et les responsabilités seront plus faciles à gérer. Un conseil est d'avoir un nombre de composants compris entre 6 et 12 (idéalement, 12), et que chacun de ces composants soit approximativement de même taille.
==== De manière plus générale
* *Conserver une densité de code faible*: il n'est évidemment pas possible d'implémenter n'importe quelle nouvelle fonctionnalité en moins de 20 lignes de code; l'idée ici est que la réécriture du projet ne prenne pas plus de 20 hommes/mois. Pour cela, il faut (activement) passer du temps à réduire la taille du code existant: soit en faisant du refactoring (intensif?), soit en utilisant des librairies existantes, soit en explosant un système existant en plusieurs sous-systèmes communiquant entre eux. Mais surtout en évitant de copier/coller bêtement du code existant.
* *Conserver une densité de code faible*: il n'est évidemment pas possible d'implémenter n'importe quelle nouvelle fonctionnalité en moins de 20 lignes de code; l'idée ici est que la réécriture du projet ne prenne pas plus de 20 hommes/mois. Pour cela, il faut (activement) passer du temps à réduire la taille du code existant: soit en faisant du refactoring (intensif?), soit en utilisant des librairies existantes, soit en explosant un système existant en plusieurs sous-systèmes communiquant entre eux. Mais surtout, en évitant de copier/coller bêtement du code existant.
* *Automatiser les tests*, *ajouter un environnement d'intégration continue dès le début du projet* et *vérifier par des outils les points ci-dessus*.
==== En pratique
Par rapport aux points repris ci-dessus, l'environnement Python et le framework Django proposent un ensemble d'outils intégrés qui permettent de répondre à chaque point. Avant d'aller plus loin, donc, un petit point sur les conventions, les tests (unitaires, orientés comportement, basés sur la documentation, ...), la gestion de version du code, le typage de paramètre et de valeurs de retour et sur la documentation. Plus que dans tout langage compilé, ceux-ci sont pratiquement obligatoires. Vous pourrez les voir comme une perte de temps dans un premier temps, mais nous vous promettons qu'ils vous en feront gagner par la suite.