Finalize Git review

This commit is contained in:
Fred Pauchet 2020-12-15 13:10:07 +01:00
parent 0f01bdcecb
commit ee29769649
12 changed files with 146 additions and 99 deletions

View File

@ -13,5 +13,6 @@ admonition:
stroke_color: ff0000
size: 24
image:
align: center
caption:
align: inherit

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -24,8 +24,8 @@ 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 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.
*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.
@ -36,12 +36,12 @@ A la fin de cette partie, vous disposerez d'un code propre et d'un projet foncti
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.
*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!
Et tout ça à un seul et même endroit. Oui. :-)
Et tout ça à un seul et même endroit.footnote:[Avec un peu d'https://www.xkcd.com[XKCD] dedans] Oui. :-)
Bonne lecture.

View File

@ -16,11 +16,11 @@ Dans cette partie, nous allons parler de *méthode de travail*, avec comme objec
. prévoir un rollback si cela plante
. se préparer une tisane en regardant nos flux RSS (si cette technologie existe encore...).
NOTE: La plupart des commandes qui seront présentées dans ce livre le seront depuis un shell sous GNU/Linux. Certaines d'entre elles pourraient devoir être adaptées si vous utilisez un autre système d'exploitation (macOS) ou n'importe quelle autre grosse bouse commerciale (MS Windows).
NOTE: La plupart des commandes qui seront présentées dans ce livre le seront depuis un shell sous GNU/Linux. Certaines d'entre elles pourraient devoir être adaptées si vous utilisez un autre système d'exploitation (macOS) ou n'importe quelle autre grosse bouse commerciale.
include::building-maintainable-applications.adoc[]
include::maintainable-applications/_index.adoc[]
include::environment/index.adoc[]
include::environment/_index.adoc[]
include::venvs.adoc[]

View File

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

View File

@ -0,0 +1,122 @@
== Boite à outils
=== Python
Le langage https://www.python.org/[Python] est un https://docs.python.org/3/faq/general.html#what-is-python[langage de programmation] interprété, interactif, orienté objet (souvent), fonctionnel (parfois), open source, multi-plateformes, flexible, facile à apprendre et difficile à maîtriser.
.https://xkcd.com/353/
image::images/xkcd-353-python.png[]
A première vue, certains concepts restent difficiles à aborder: l'indentation définit l'étendue d'un bloc (classe, fonction, méthode, boucle, condition, ...), il n'y a pas de typage fort des variables et le compilateur n'est pas là pour assurer le filet de sécurité avant la mise en production (puisqu'il n'y a pas de compilateur 😛).
Et malgré ces quelques points, Python reste un langage généraliste accessible et "bon partout", et de pouvoir se reposer sur un écosystème stable et fonctionnel.
Il fonctionne avec un système d'améliorations basées sur des propositions: les PEP, ou "**Python Enhancement Proposal**".
Chacune d'entre elles doit être approuvée par le http://fr.wikipedia.org/wiki/Benevolent_Dictator_for_Life[Benevolent Dictator For Life].
==== PEP8 - Style Guide for Python Code
La première PEP qui va nous intéresser est la https://www.python.org/dev/peps/pep-0008/[PEP 8 -- Style Guide for Python Code]. Elle spécifie comment du code Python doit être organisé ou formaté, quelles sont les conventions pour lindentation, le nommage des variables et des classes, ...
En bref, elle décrit comment écrire du code proprement, afin que dautres développeurs puissent le reprendre facilement, ou simplement que votre base de code ne dérive lentement vers un seuil de non-maintenabilité.
Dans cet objectif, un outil existe et listera l'ensemble des conventions qui ne sont pas correctement suivies dans votre projet: pep8. Pour l'installer, passez par pip. Lancez ensuite la commande pep8 suivie du chemin à analyser (`.`, le nom d'un répertoire, le nom d'un fichier `.py`, ...). Si vous souhaitez uniquement avoir le nombre d'erreur de chaque type, saisissez les options `--statistics -qq`.
[source,bash]
----
$ pep8 . --statistics -qq
7 E101 indentation contains mixed spaces and tabs
6 E122 continuation line missing indentation or outdented
8 E127 continuation line over-indented for visual indent
23 E128 continuation line under-indented for visual indent
3 E131 continuation line unaligned for hanging indent
12 E201 whitespace after '{'
13 E202 whitespace before '}'
86 E203 whitespace before ':'
----
Si vous ne voulez pas être dérangé sur votre manière de coder, et que vous voulez juste avoir un retour sur une analyse de votre code, essayez `pyflakes`: cette librairie analysera vos sources à la recherche de sources d'erreurs possibles (imports inutilisés, méthodes inconnues, etc.).
Il existe une solution qui couvre ces deux domaines: https://github.com/PyCQA/flake8[flake8].
Sur base de la même interface que `pep8`, vous rencontreez en plus tous les avantages liés à `pyflakes`
==== PEP257
NOTE: à remplir avec `pydocstyle`.
NOTE: parler de Napoleon.
=== Environnement de développement
Concrètement, nous pourrions tout à fait nous limiter à Notepad ou Notepad++.
Mais à moins d'aimer se fouetter avec un câble USB, nous apprécions la complétion du code, la coloration syntaxique, l'intégration des tests unitaires et d'un debugger, ainsi que deux-trois sucreries qui feront plaisir à n'importe quel développeur.
Si vous manquez d'idées ou si vous ne savez pas par où commencer:
* https://vscodium.com/[VSCodium], avec les plugins https://marketplace.visualstudio.com/items?itemName=ms-python.python[Python]et https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens[GitLens]
* https://www.jetbrains.com/pycharm/[PyCharm]
* https://www.vim.org/[Vim] avec les plugins https://github.com/davidhalter/jedi-vim[Jedi-Vim] et https://github.com/preservim/nerdtree[nerdtree]
Si vous hésitez, et même si Codium n'est pas le plus léger (la faute à https://www.electronjs.org/[Electron]...), il fera correctement son travail (à savoir: faciliter le vôtre), en intégrant suffisament de fonctionnalités qui gâteront les papilles émoustillées du développeur impatient.
.Codium en action
image::images/environment/codium.png[]
=== Un terminal
_A priori_, les IDE footnote:[Integrated Development Environment] proposés ci-dessus fournissent par défaut ou _via_ des greffons un terminal intégré.
Ceci dit, disposer d'un terminal séparé facilite parfois certaines tâches.
A nouveau, si vous manquez d'idées:
. Si vous êtes sous Windows, téléchargez une copie de https://cmder.net/[Cmder]. Il n'est pas le plus rapide, mais propose une intégration des outils Unix communs (`ls`, `pwd`, `grep`, `ssh`, `git`, ...) sans trop se fouler.
. Pour tout autre système, vous devriez disposer en natif de ce qu'il faut.
.Mise en abîme
image::images/environment/terminal.png[]
=== Un gestionnaire de base de données
Django gère plusieurs moteurs de base de données.
Certains sont gérés nativement par Django (PostgreSQL, MariaDB, SQLite); _a priori_, ces trois-là sont disponibles pour tous les systèmes d'exploitation. D'autres moteurs nécessitent des librairies tierces (Oracle, Microsoft SQL Server).
Il n'est pas obligatoire de disposer d'une application de gestion pour ces moteurs: pour les cas d'utilisation simples, le shell Django pourra largement suffire (nous y reviendrons).
Mais pour faciliter la gestion des bases de données elles-même, et si vous n'êtes pas à l'aise avec la ligne de commande, choisissez l'une des applications d'administration ci-dessous en fonction du moteur de base de données que vous souhaitez utiliser.
* Pour *PostgreSQL*, il existe https://www.pgadmin.org/[pgAdmin]
* Pour *MariaDB* ou *MySQL*, partez sur https://www.phpmyadmin.net/[PHPMyAdmin]
* Pour *SQLite*, il existe https://sqlitebrowser.org/[SQLiteBrowser]
PHPMyAdmin ou PgAdmin.
=== Un gestionnaire de mots de passe
Nous en auront besoin pour gé(né)rer des phrases secrètes pour nos applications.
Si vous n'en utilisez pas déjà un, partez sur https://keepassxc.org/[KeepassXC]: il est multi-plateformes, suivi et s'intègre correctement aux différents environnements, tout en restant accessible.
image::images/environment/keepass.png[]
=== Un système de gestion de versions
Il existe plusieurs systèmes de gestion de versions.
Le plus connu à l'heure actuelle est https://git-scm.com/[Git], notamment pour sa (très) grande flexibilité et sa rapidité d'exécution.
Il est une aide précieuse pour développer rapidement des preuves de concept, switcher vers une nouvelle fonctionnalité, un bogue à réparer ou une nouvelle release à proposer au téléchargement.
Ses deux plus gros défauts concerneraient peut-être sa courbe d'apprentissage pour les nouveaux venus et la complexité des actions qu'il permet de réaliser.
.https://xkcd.com/1597/
image::images/xkcd-1597-git.png[]
Même pour un développeur solitaire, un système de gestion de versions (quel qu'il soit) reste indispensable.
Chaque "branche" correspond à une tâche à réaliser: un bogue à corriger (_Hotfix A_), une nouvelle fonctionnalité à ajouter ou un "_truc à essayer_" footnote:[Oui, comme dans "Attends, j'essaie vite un truc, si ça marche, c'est beau."] (_Feature A_ et _Feature B_).
De cette manière, il est beaucoup plus facile pour le développeur de se concenter sur un sujet en particulier, dans la mesure où ce sujet ne doit pas obligatoirement être clôturé pour changer de contexte.
.Git en action
image::images/diagrams/git.png[]
Cas pratique: vous développez cette nouvelle fonctionnalité qui va révolutionner le monde de demain et d'après-demain, quand, tout à coup (!), vous vous rendez compte que vous avez perdu votre conformité aux normes PCI parce les données des titulaires de cartes ne sont pas isolées correctement.
Il suffit alors de sauver le travail en cours, revenir sur la branche principale, créer un "hotfix", solutionner le problème, pousser le correctif sur la branche principal, et revenir tranquillou sur votre branche de développement pour fignoler ce générateur de noms de dinosaures rigolos que l'univers vous réclame à cor et à a cri.

View File

@ -1,44 +0,0 @@
== Boite à outils
=== Environnement de développement
Concrètement, on pourrait tout à fait se limiter à Notepad ou Notepad++. C'est juste qu'à moins d'aimer se fouetter avec un câble USB, on appréciera la complétion du code, la coloration syntaxique, l'intégration des tests unitaires et d'un debugger et de deux-trois sucreries qui feront plaisir à n'importe quel développeur.
* https://vscodium.com/[VSCodium], avec les plugins https://marketplace.visualstudio.com/items?itemName=ms-python.python[Python], https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens[GitLens], https://marketplace.visualstudio.com/items?itemName=mechatroner.rainbow-csv[Rainbow-CSV] (celui-là, c'est juste pour le fun; on n'en aura pas besoin pour la suite)
* https://www.jetbrains.com/pycharm/[PyCharm]
* https://www.vim.org/[Vim] avec les plugins https://github.com/davidhalter/jedi-vim[Jedi-Vim], https://github.com/preservim/nerdtree[nerdtree]
image::images/environment/codium.png[]
=== Un terminal
Si vous êtes sous Windows, https://cmder.net/[cmder].
Pour tout autre système, vous devriez disposer en natif de ce qu'il faut.
image::images/environment/terminal.png[align="center"]
=== Un gestionnaire de base de données
Django gère plusieurs types de base de données.
Essayez de conformer votre environnement de développement à l'environnement sur lequel l'application sera sensée tourner en production:
* Pour *PostgreSQL*, il existe https://www.pgadmin.org/[pgAdmin]
* Pour *MariaDB* ou *MySQL*, partez sur https://www.phpmyadmin.net/[PHPMyAdmin]
* Pour *SQLite*, il existe https://sqlitebrowser.org/[SQLiteBrowser]
PHPMyAdmin ou PgAdmin.
_A priori_, ces trois types de bases de données sont disponibles pour tous les systèmes d'exploitation, et sont nativement supportés par Django.
Pour tous les autres cas, le shell Django pourra largement suffire.
=== Un gestionnaire de mots de passe
Nous en auront besoin pour gé(né)rer des phrases secrètes pour nos applications.
Si vous n'en utilisez pas déjà un, partez sur https://keepassxc.org/[KeepassXC].
image::images/environment/keepass.png[align="center"]
=== Un système de gestion de versions
https://git-scm.com/[Git], pour développer rapidement des preuves de concept, switcher vers une nouvelle fonctionnalité à développer, un bogue à réparer ou une nouvelle release à proposer au téléchargement. Même en développant seul dans son coin, un système de gestion de versions reste indispensable.

View File

@ -0,0 +1,7 @@
== Construire des applications maintenables
include::12-factors.adoc[]
include::maintainable-applications.adoc[]
include::solid.adoc[]

View File

@ -1,39 +1,7 @@
== Chaîne d'outils
=== PEP8 - Style Guide for Python Code
Le langage Python fonctionne avec un système d'améliorations basées sur des propositions: les PEP, ou "**Python Enhancement Proposal**". Chacune d'entre elles doit être approuvée par le http://fr.wikipedia.org/wiki/Benevolent_Dictator_for_Life[Benevolent Dictator For Life].
La première qui va nous intéresser est la https://www.python.org/dev/peps/pep-0008/[PEP 8 -- Style Guide for Python Code]. Elle spécifie comment du code Python doit être organisé ou formaté, quelles sont les conventions pour lindentation, le nommage des variables et des classes, … En bref, elle décrit comment écrire du code proprement pour que dautres développeurs puissent le reprendre facilement, ou simplement que votre base de code ne dérive lentement vers un seuil de non-maintenabilité.
Sur cette base, un outil existe et listera l'ensemble des conventions qui ne sont pas correctement suivies dans votre projet: pep8. Pour l'installer, passez par pip. Lancez ensuite la commande pep8 suivie du chemin à analyser (`.`, le nom d'un répertoire, le nom d'un fichier `.py`, ...). Si vous souhaitez uniquement avoir le nombre d'erreur de chaque type, saisissez les options `--statistics -qq`.
[source,bash]
----
$ pep8 . --statistics -qq
7 E101 indentation contains mixed spaces and tabs
6 E122 continuation line missing indentation or outdented
8 E127 continuation line over-indented for visual indent
23 E128 continuation line under-indented for visual indent
3 E131 continuation line unaligned for hanging indent
12 E201 whitespace after '{'
13 E202 whitespace before '}'
86 E203 whitespace before ':'
----
Si vous ne voulez pas être dérangé sur votre manière de coder, et que vous voulez juste avoir un retour sur une analyse de votre code, essayez `pyflakes`: il analysera vos sources à la recherche de sources d'erreurs possibles (imports inutilisés, méthodes inconnues, etc.).
Finalement, la solution qui couvre ces deux domaines existe et s'intitule https://github.com/PyCQA/flake8[flake8]. Sur base la même interface que `pep8`, vous aurez en plus tous les avantages liés à `pyflakes` concernant votre code source.
==== PEP257
NOTE: à remplir avec `pydocstyle`.
NOTE: parler de Napoleon.
==== Tests
=== Tests
Comme tout bon *framework* qui se respecte, Django embarque tout un environnement facilitant le lancement de tests; chaque application est créée par défaut avec un fichier **tests.py**, qui inclut la classe `TestCase` depuis le package `django.test`:
@ -68,7 +36,7 @@ django_coverage_plugin
[run]
branch = True
omit = ../*migrations*
plugins =
plugins =
django_coverage_plugin
[report]
@ -151,7 +119,7 @@ def compare(a, b, c, d, e):
return 1
----
Potentiellement, les tests unitaires qui seront nécessaires à couvrir tous les cas de figure seront au nombre de quatre: le cas par défaut (a est différent de b, rien ne se passe), puis les autres cas, jusqu'à arriver à l'impression à l'écran et à la valeur de retour. La complexité cyclomatique d'un bloc est évaluée sur base du nombre d'embranchements possibles; par défaut, sa valeur est de 1. Si on rencontre une condition, elle passera à 2, etc.
Potentiellement, les tests unitaires qui seront nécessaires à couvrir tous les cas de figure seront au nombre de quatre: le cas par défaut (a est différent de b, rien ne se passe), puis les autres cas, jusqu'à arriver à l'impression à l'écran et à la valeur de retour. La complexité cyclomatique d'un bloc est évaluée sur base du nombre d'embranchements possibles; par défaut, sa valeur est de 1. Si on rencontre une condition, elle passera à 2, etc.
Pour l'exemple ci-dessous, on va en fait devoir vérifier au moins chacun des cas pour s'assurer que la couverture est complète. On devrait donc trouver:
@ -160,7 +128,7 @@ Pour l'exemple ci-dessous, on va en fait devoir vérifier au moins chacun des ca
. Un test pour entrer dans la condition `c == d`
. Un test pour entrer dans la condition `d == e`
. Et s'assurer que n'importe quel autre cas retournera la valeur `None`.
On a donc bien besoin de minimum cinq tests pour couvrir l'entièreté des cas présentés.
Le nombre de tests unitaires nécessaires à la couverture d'un bloc fonctionnel est au minimum égal à la complexité cyclomatique de ce bloc. Une possibilité pour améliorer la maintenance du code est de faire baisser ce nombre, et de le conserver sous un certain seuil. Certains recommandent de le garder sous une complexité de 10; d'autres de 5.
@ -255,7 +223,7 @@ test.py:18:1: W391 blank line at end of file
On trouve des erreurs:
* de *conventions*: le nombre de lignes qui séparent deux fonctions, le nombre d'espace après un opérateur, une ligne vide à la fin du fichier, ... Ces _erreurs_ n'en sont pas vraiment, elles indiquent juste de potentiels problèmes de communication si le code devait être lu ou compris par une autre personne.
* de *définition*: une variable assignée mais pas utilisée ou une lexème non trouvé. Cette dernière information indique clairement un bug potentiel.
* de *définition*: une variable assignée mais pas utilisée ou une lexème non trouvé. Cette dernière information indique clairement un bug potentiel.
L'étape d'après consiste à invoquer pylint. Lui, il est directement moins conciliant:
@ -291,7 +259,7 @@ En gros, j'ai programmé comme une grosse bouse anémique (et oui, le score d'é
* de la redéfinition de variables (W0621).
Pour reprendre la http://pylint.pycqa.org/en/latest/user_guide/message-control.html[documentation], chaque code possède sa signification (ouf!):
Pour reprendre la http://pylint.pycqa.org/en/latest/user_guide/message-control.html[documentation], chaque code possède sa signification (ouf!):
* C convention related checks
* R refactoring related checks
@ -309,14 +277,14 @@ PyLint est la version **++**, pour ceux qui veulent un code propre et sans bavur
https://black.readthedocs.io/en/stable/[Black].
Une chose qui fonctionne bien avec le langage Go, c'est que les outils de base sont intégrés au compilateur : le formatage de code et les tests unitaires sont à la portée de tout le monde au travers de deux commandes simples :
Une chose qui fonctionne bien avec le langage Go, c'est que les outils de base sont intégrés au compilateur : le formatage de code et les tests unitaires sont à la portée de tout le monde au travers de deux commandes simples :
. `go fmt`
. `go test`
En Python, c'est plus complexe que cela, puisqu'il n'existe pas une manière unique d'arriver à un résultat (on l'a vu ci-dessus, rien que pour les tests, on a au moins deux librairies...).
Pour revenir à Go : est-ce que ce formatage est idéal et accepté par tout le monde ? Non.
Pour revenir à Go : est-ce que ce formatage est idéal et accepté par tout le monde ? Non.
Black fait le même travail: il arrive à un compromis entre la clarté du code, la facilité d'installation et d'intégration et un résultat. Ce résultat ne sera pas parfait, mais il conviendra dans 97,83% des cas (au moins).
@ -326,5 +294,5 @@ Black fait le même travail: il arrive à un compromis entre la clarté du code,
=== mypy
=== Towncrier
voir https://pypi.org/project/towncrier/[ici]