From 02930bd52f4dc5a494a101e62bcea901a98f95bf Mon Sep 17 00:00:00 2001 From: Fred Pauchet Date: Tue, 12 Apr 2022 19:56:25 +0200 Subject: [PATCH] Structure 12 factors --- asciidoc-to-tex.tex | 319 +---------------------------------- chapters/maintenability.tex | 324 ++++++++++++++++++++++++++++++++++++ 2 files changed, 325 insertions(+), 318 deletions(-) diff --git a/asciidoc-to-tex.tex b/asciidoc-to-tex.tex index 33c5e38..bae78a8 100644 --- a/asciidoc-to-tex.tex +++ b/asciidoc-to-tex.tex @@ -1,4 +1,4 @@ - + \hypertarget{_fiabilituxe9_uxe9volutivituxe9_et_maintenabilituxe9}{% \section{Fiabilité, évolutivité et maintenabilité}\label{_fiabilituxe9_uxe9volutivituxe9_et_maintenabilituxe9}} @@ -6,324 +6,7 @@ maintenabilité}\label{_fiabilituxe9_uxe9volutivituxe9_et_maintenabilituxe9}} \hypertarget{_12_facteurs}{% \subsection{12 facteurs}\label{_12_facteurs}} -Pour la méthode de travail et de développement, nous allons nous baser -sur les \href{https://12factor.net/fr/}{The Twelve-factor App} - ou plus -simplement les \textbf{12 facteurs}. -L'idée derrière cette méthode, et indépendamment des langages de -développement utilisés, consiste à suivre un ensemble de douze concepts, -afin de: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\item - \textbf{Faciliter la mise en place de phases d'automatisation}; plus - concrètement, de faciliter les mises à jour applicatives, simplifier - la gestion de l'hôte, diminuer la divergence entre les différents - environnements d'exécution et offrir la possibilité d'intégrer le - projet dans un processus - d'\href{https://en.wikipedia.org/wiki/Continuous_integration}{intégration - continue} ou - \href{https://en.wikipedia.org/wiki/Continuous_deployment}{déploiement - continu} -\item - \textbf{Faciliter la mise à pied de nouveaux développeurs ou de - personnes souhaitant rejoindre le projet}, dans la mesure où la mise à - disposition d'un environnement sera grandement facilitée. -\item - \textbf{Minimiser les divergences entre les différents environnemens - sur lesquels un projet pourrait être déployé} -\item - \textbf{Augmenter l'agilité générale du projet}, en permettant une - meilleure évolutivité architecturale et une meilleure mise à l'échelle - - \emph{Vous avez 5000 utilisateurs en plus? Ajoutez un serveur et on - n'en parle plus ;-)}. -\end{enumerate} - -En pratique, les points ci-dessus permettront de monter facilement un -nouvel environnement - qu'il soit sur la machine du petit nouveau dans -l'équipe, sur un serveur Azure/Heroku/Digital Ocean ou votre nouveau -Raspberry Pi Zéro caché à la cave - et vous feront gagner un temps -précieux. - -Pour reprendre de manière très brute les différentes idées derrière -cette méthode, nous avons: - -\textbf{\#1 - Une base de code unique, suivie par un système de contrôle -de versions}. - -Chaque déploiement de l'application se basera sur cette source, afin de -minimiser les différences que l'on pourrait trouver entre deux -environnements d'un même projet. On utilisera un dépôt Git - Github, -Gitlab, Gitea, \ldots\hspace{0pt} Au choix. - -\includegraphics{images/diagrams/12-factors-1.png} - -Comme l'explique Eran Messeri, ingénieur dans le groupe Google Developer -Infrastructure, un des avantages d'utiliser un dépôt unique de sources, -est qu'il permet un accès facile et rapide à la forme la plus à jour du -code, sans aucun besoin de coordination. \footnote{The DevOps Handbook, - Part V, Chapitre 20, Convert Local Discoveries into Global - Improvements} Ce dépôt ne sert pas seulement au code source, mais -également à d'autres artefacts et formes de connaissance: - -\begin{itemize} -\item - Standards de configuration (Chef recipes, Puppet manifests, - \ldots\hspace{0pt}) -\item - Outils de déploiement -\item - Standards de tests, y compris tout ce qui touche à la sécurité -\item - Outils de déploiement de pipeline -\item - Outils d'analyse et de monitoring -\item - Tutoriaux -\end{itemize} - -\textbf{\#2 - Déclarez explicitement les dépendances nécessaires au -projet, et les isoler du reste du système lors de leur installation} - -Chaque installation ou configuration doit toujours être faite de la même -manière, et doit pouvoir être répétée quel que soit l'environnement -cible. - -Cela permet d'éviter que l'application n'utilise une dépendance qui soit -déjà installée sur un des sytèmes de développement, et qu'elle soit -difficile, voire impossible, à répercuter sur un autre environnement. -Dans notre cas, cela pourra être fait au travers de -\href{https://pypi.org/project/pip/}{PIP - Package Installer for Python} -ou \href{https://python-poetry.org/}{Poetry}. - -Mais dans tous les cas, chaque application doit disposer d'un -environnement sain, qui lui est assigné, et vu le peu de ressources que -cela coûte, il ne faut pas s'en priver. - -Chaque dépendance pouvant être déclarée et épinglée dans un fichier, il -suffira de créer un nouvel environment vierge, puis d'utiliser ce -fichier comme paramètre pour installer les prérequis au bon -fonctionnement de notre application et vérifier que cet environnement -est bien reproductible. - -Il est important de bien "épingler" les versions liées aux dépendances -de l'application. Cela peut éviter des effets de bord comme une nouvelle -version d'une librairie dans laquelle un bug aurait pu avoir été -introduit. Parce qu'il arrive que ce genre de problème apparaisse, et -lorsque ce sera le cas, ce sera systématiquement au mauvais moment. - -\textbf{\#3 - Sauver la configuration directement au niveau de -l'environnement} - -Nous voulons éviter d'avoir à recompiler/redéployer l'application parce -que: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\item - l'adresse du serveur de messagerie a été modifiée, -\item - un protocole a changé en cours de route -\item - la base de données a été déplacée -\item - \ldots\hspace{0pt} -\end{enumerate} - -En pratique, toute information susceptible de modifier un lien vers une -ressource annexe doit se trouver dans un fichier ou dans une variable -d'environnement, et doit être facilement modifiable. En allant un pas -plus loin, ceci de paramétrer facilement un environnement (par exemple, -un container), simplement en modifiant une variable de configuration qui -spécifierait la base de données sur laquelle l'application devra se -connecter. - -Toute clé de configuration (nom du serveur de base de données, adresse -d'un service Web externe, clé d'API pour l'interrogation d'une -ressource, \ldots\hspace{0pt}) sera définie directement au niveau de -l'hôte - à aucun moment, nous ne devons trouver un mot de passe en clair -dans le dépôt source ou une valeur susceptible d'évoluer, écrite en dur -dans le code. - -Au moment de développer une nouvelle fonctionnalité, réfléchissez si -l'un des composants utilisés risquerait de subir une modification: ce -composant peut concerner une nouvelle chaîne de connexion, un point de -terminaison nécessaire à télécharger des données officielles ou un -chemin vers un répertoire partagé pour y déposer un fichier. - -\textbf{\#4 - Traiter les ressources externes comme des ressources -attachées} - -Nous parlons de bases de données, de services de mise en cache, d'API -externes, \ldots\hspace{0pt} L'application doit être capable d'effectuer -des changements au niveau de ces ressources sans que son code ne soit -modifié. Nous parlons alors de \textbf{ressources attachées}, dont la -présence est nécessaire au bon fonctionnement de l'application, mais -pour lesquelles le \textbf{type} n'est pas obligatoirement défini. - -Nous voulons par exemple "une base de données" et "une mémoire cache", -et pas "une base MariaDB et une instance Memcached". De cette manière, -les ressources peuvent être attachées et détachées d'un déploiement à la -volée. - -Si une base de données ne fonctionne pas correctement (problème matériel -?), l'administrateur pourrait simplement restaurer un nouveau serveur à -partir d'une précédente sauvegarde, et l'attacher à l'application sans -que le code source ne soit modifié. une solution consiste à passer -toutes ces informations (nom du serveur et type de base de données, clé -d'authentification, \ldots\hspace{0pt}) directement \emph{via} des -variables d'environnement. - -\includegraphics{images/12factors/attached-resources.png} - -Nous serons ravis de pouvoir simplement modifier une chaîne -\texttt{sqlite:////tmp/my-tmp-sqlite.db\textquotesingle{}} en -\texttt{psql://user:pass@127.0.0.1:8458/db} lorsque ce sera nécessaire, -sans avoir à recompiler ou redéployer les modifications. - -\textbf{\#5 - Séparer proprement les phases de construction, de mise à -disposition et d'exécution} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\item - La \textbf{construction} (\emph{build}) convertit un code source en un - ensemble de fichiers exécutables, associé à une version et à une - transaction dans le système de gestion de sources. -\item - La \textbf{mise à disposition} (\emph{release}) associe cet ensemble à - une configuration prête à être exécutée, -\item - tandis que la phase d'\textbf{exécution} (\emph{run}) démarre les - processus nécessaires au bon fonctionnement de l'application. -\end{enumerate} - -\includegraphics{images/12factors/release.png} - -Parmi les solutions possibles, nous pourrions nous pourrions nous baser -sur les \emph{releases} de Gitea, sur un serveur d'artefacts ou sur -\href{https://fr.wikipedia.org/wiki/Capistrano_(logiciel)}{Capistrano}. - -\textbf{\#6 - Les processus d'exécution ne doivent rien connaître ou -conserver de l'état de l'application} - -Toute information stockée en mémoire ou sur disque ne doit pas altérer -le comportement futur de l'application, par exemple après un redémarrage -non souhaité. - -Pratiquement, si l'application devait rencontrer un problème, l'objectif -est de pouvoir la redémarrer rapidement sur un autre serveur (par -exemple suite à un problème matériel). Toute information qui aurait été -stockée durant l'exécution de l'application sur le premier hôte serait -donc perdue. Si une réinitialisation devait être nécessaire, -l'application ne devra pas compter sur la présence d'une information au -niveau du nouveau système. La solution consiste donc à jouer sur les -variables d'environnement (cf. \#3) et sur les informations que l'on -pourra trouver au niveau des ressources attachées (cf \#4). - -Il serait également difficile d'appliquer une mise à l'échelle de -l'application, en ajoutant un nouveau serveur d'exécution, si une donnée -indispensable à son fonctionnement devait se trouver sur la seule -machine où elle est actuellement exécutée. - -\textbf{\#7 - Autoriser la liaison d'un port de l'application à un port -du système hôte} - -Les applications 12-factors sont auto-contenues et peuvent fonctionner -en autonomie totale. Elles doivent être joignables grâce à un mécanisme -de ponts, où l'hôte qui s'occupe de l'exécution effectue lui-même la -redirection vers l'un des ports ouverts par l'application, typiquement, -en HTTP ou via un autre protocole. - -\includegraphics{images/diagrams/12-factors-7.png} - -\textbf{\#8 - Faites confiance aux processus systèmes pour l'exécution -de l'application} - -Comme décrit plus haut (cf. \#6), l'application doit utiliser des -processus \emph{stateless} (sans état). Nous pouvons créer et utiliser -des processus supplémentaires pour tenir plus facilement une lourde -charge, ou dédier des processus particuliers pour certaines tâches: -requêtes HTTP \emph{via} des processus Web; \emph{long-running} jobs -pour des processus asynchrones, \ldots\hspace{0pt} Si cela existe au -niveau du système, ne vous fatiguez pas: utilisez le. - -\includegraphics{images/12factors/process-types.png} - -\textbf{\#9 - Améliorer la robustesse de l'application grâce à des -arrêts élégants et à des démarrages rapides} - -Par "arrêt élégant", nous voulons surtout éviter le -\texttt{kill\ -9\ \textless{}pid\textgreater{}} ou tout autre arrêt -brutal d'un processus qui nécessiterait une intervention urgente du -superviseur. De cette manière, les requêtes en cours peuvent se terminer -au mieux, tandis que le démarrage rapide de nouveaux processus -améliorera la balance d'un processus en cours d'extinction vers des -processus tout frais. - -L'intégration de ces mécanismes dès les premières étapes de -développement limitera les perturbations et facilitera la prise en -compte d'arrêts inopinés (problème matériel, redémarrage du système -hôte, etc.). - -\textbf{\#10 - Conserver les différents environnements aussi similaires -que possible, et limiter les divergences entre un environnement de -développement et de production} - -L'exemple donné est un développeur qui utilise macOS, NGinx et SQLite, -tandis que l'environnement de production tourne sur une CentOS avec -Apache2 et PostgreSQL. Faire en sorte que tous les environnements soient -les plus similaires possibles limite les divergences entre -environnements, facilite les déploiements et limite la casse et la -découverte de modules non compatibles dès les premières phases de -développement. - -Pour vous donner un exemple tout bête, SQLite utilise un -\href{https://www.sqlite.org/datatype3.html}{mécanisme de stockage -dynamique}, associée à la valeur plutôt qu'au schéma, \emph{via} un -système d'affinités. Un autre moteur de base de données définira un -schéma statique et rigide, où la valeur sera déterminée par son -contenant. Un champ \texttt{URLField} proposé par Django a une longeur -maximale par défaut de -\href{https://docs.djangoproject.com/en/3.1/ref/forms/fields/\#django.forms.URLField}{200 -caractères}. Si vous faites vos développements sous SQLite et que vous -rencontrez une URL de plus de 200 caractères, votre développement sera -passera parfaitement bien, mais plantera en production (ou en -\emph{staging}, si vous faites les choses un peu mieux) parce que les -données seront tronquées\ldots\hspace{0pt} - -Conserver des environements similaires limite ce genre de désagréments. - -\textbf{\#11 - Gérer les journeaux d'évènements comme des flux} - -Une application ne doit jamais se soucier de l'endroit où ses évènements -seront écrits, mais simplement de les envoyer sur la sortie -\texttt{stdout}. De cette manière, que nous soyons en développement sur -le poste d'un développeur avec une sortie console ou sur une machine de -production avec un envoi vers une instance -\href{https://www.graylog.org/}{Greylog} ou -\href{https://sentry.io/welcome/}{Sentry}, le routage des journaux sera -réalisé en fonction de sa nécessité et de sa criticité, et non pas parce -que le développeur l'a spécifié en dur dans son code. Cette phase est -critique, dans la mesure où les journaux d'exécution sont la seule -manière pour une application de communiquer son état vers l'extérieur: -recevoir une erreur interne de serveur est une chose; pouvoir obtenir un -minimum d'informations, voire un contexte de plantage complet en est une -autre. - -\textbf{\#12 - Isoler les tâches administratives du reste de -l'application} - -Evitez qu'une migration ne puisse être démarrée depuis une URL de -l'application, ou qu'un envoi massif de notifications ne soit accessible -pour n'importe quel utilisateur: les tâches administratives ne doivent -être accessibles qu'à un administrateur. Les applications 12facteurs -favorisent les langages qui mettent un environnement REPL (pour -\emph{Read}, \emph{Eval}, \emph{Print} et \emph{Loop}) à disposition (au -hasard: \href{https://pythonprogramminglanguage.com/repl/}{Python} ou -\href{https://kotlinlang.org/}{Kotlin}), ce qui facilite les étapes de -maintenance. \hypertarget{_concevoir_pour_lopuxe9rationnel}{% \subsection{Concevoir pour diff --git a/chapters/maintenability.tex b/chapters/maintenability.tex index 6234aeb..a817f9e 100644 --- a/chapters/maintenability.tex +++ b/chapters/maintenability.tex @@ -17,6 +17,330 @@ La poésie est "l'art d'évoquer et de suggérer les sensations, les impressions Sans aller jusqu'à demander de développer vos algorithmes sur douze pieds, la programmation reste un art régit par un ensemble de bonnes pratiques, par des règles à respecter et par la nécessité de travailler avec d'autres personnes qui ont \sout{parfois} souvent une expérience, des compétences ou une approche différente. +\section{12 facteurs} + + +Pour la méthode de travail et de développement, nous allons nous baser +sur les \href{https://12factor.net/fr/}{The Twelve-factor App} - ou plus +simplement les \textbf{12 facteurs}. + +L'idée derrière cette méthode, et indépendamment des langages de +développement utilisés, consiste à suivre un ensemble de douze concepts, +afin de: + +\begin{enumerate} +\def\labelenumi{\arabic{enumi}.} +\item + \textbf{Faciliter la mise en place de phases d'automatisation}; plus + concrètement, de faciliter les mises à jour applicatives, simplifier + la gestion de l'hôte, diminuer la divergence entre les différents + environnements d'exécution et offrir la possibilité d'intégrer le + projet dans un processus + d'\href{https://en.wikipedia.org/wiki/Continuous_integration}{intégration + continue} ou + \href{https://en.wikipedia.org/wiki/Continuous_deployment}{déploiement + continu} +\item + \textbf{Faciliter la mise à pied de nouveaux développeurs ou de + personnes souhaitant rejoindre le projet}, dans la mesure où la mise à + disposition d'un environnement sera grandement facilitée. +\item + \textbf{Minimiser les divergences entre les différents environnemens + sur lesquels un projet pourrait être déployé} +\item + \textbf{Augmenter l'agilité générale du projet}, en permettant une + meilleure évolutivité architecturale et une meilleure mise à l'échelle + - \emph{Vous avez 5000 utilisateurs en plus? Ajoutez un serveur et on + n'en parle plus ;-)}. +\end{enumerate} + + +En pratique, les points ci-dessus permettront de monter facilement un +nouvel environnement - qu'il soit sur la machine du petit nouveau dans +l'équipe, sur un serveur Azure/Heroku/Digital Ocean ou votre nouveau +Raspberry Pi Zéro caché à la cave - et vous feront gagner un temps +précieux. + +Pour reprendre de manière très brute les différentes idées derrière +cette méthode, nous avons: + +\subsection{\#1 - Une base de code unique, suivie par un système de contrôle +de versions}. + +Chaque déploiement de l'application se basera sur cette source, afin de +minimiser les différences que l'on pourrait trouver entre deux +environnements d'un même projet. On utilisera un dépôt Git - Github, +Gitlab, Gitea, \ldots\hspace{0pt} Au choix. + +\includegraphics{images/diagrams/12-factors-1.png} + +Comme l'explique Eran Messeri, ingénieur dans le groupe Google Developer +Infrastructure, un des avantages d'utiliser un dépôt unique de sources, +est qu'il permet un accès facile et rapide à la forme la plus à jour du +code, sans aucun besoin de coordination. \footnote{The DevOps Handbook, + Part V, Chapitre 20, Convert Local Discoveries into Global + Improvements} Ce dépôt ne sert pas seulement au code source, mais +également à d'autres artefacts et formes de connaissance: + +\begin{itemize} +\item + Standards de configuration (Chef recipes, Puppet manifests, + \ldots\hspace{0pt}) +\item + Outils de déploiement +\item + Standards de tests, y compris tout ce qui touche à la sécurité +\item + Outils de déploiement de pipeline +\item + Outils d'analyse et de monitoring +\item + Tutoriaux +\end{itemize} + +\subsection{\#2 - Déclarez explicitement les dépendances nécessaires au +projet, et les isoler du reste du système lors de leur installation} + +Chaque installation ou configuration doit toujours être faite de la même +manière, et doit pouvoir être répétée quel que soit l'environnement +cible. + +Cela permet d'éviter que l'application n'utilise une dépendance qui soit +déjà installée sur un des sytèmes de développement, et qu'elle soit +difficile, voire impossible, à répercuter sur un autre environnement. +Dans notre cas, cela pourra être fait au travers de +\href{https://pypi.org/project/pip/}{PIP - Package Installer for Python} +ou \href{https://python-poetry.org/}{Poetry}. + +Mais dans tous les cas, chaque application doit disposer d'un +environnement sain, qui lui est assigné, et vu le peu de ressources que +cela coûte, il ne faut pas s'en priver. + +Chaque dépendance pouvant être déclarée et épinglée dans un fichier, il +suffira de créer un nouvel environment vierge, puis d'utiliser ce +fichier comme paramètre pour installer les prérequis au bon +fonctionnement de notre application et vérifier que cet environnement +est bien reproductible. + +Il est important de bien "épingler" les versions liées aux dépendances +de l'application. Cela peut éviter des effets de bord comme une nouvelle +version d'une librairie dans laquelle un bug aurait pu avoir été +introduit. Parce qu'il arrive que ce genre de problème apparaisse, et +lorsque ce sera le cas, ce sera systématiquement au mauvais moment. + +\subsection{\#3 - Sauver la configuration directement au niveau de +l'environnement} + +Nous voulons éviter d'avoir à recompiler/redéployer l'application parce +que: + +\begin{enumerate} +\def\labelenumi{\arabic{enumi}.} +\item + l'adresse du serveur de messagerie a été modifiée, +\item + un protocole a changé en cours de route +\item + la base de données a été déplacée +\item + \ldots\hspace{0pt} +\end{enumerate} + +En pratique, toute information susceptible de modifier un lien vers une +ressource annexe doit se trouver dans un fichier ou dans une variable +d'environnement, et doit être facilement modifiable. En allant un pas +plus loin, ceci de paramétrer facilement un environnement (par exemple, +un container), simplement en modifiant une variable de configuration qui +spécifierait la base de données sur laquelle l'application devra se +connecter. + +Toute clé de configuration (nom du serveur de base de données, adresse +d'un service Web externe, clé d'API pour l'interrogation d'une +ressource, \ldots\hspace{0pt}) sera définie directement au niveau de +l'hôte - à aucun moment, nous ne devons trouver un mot de passe en clair +dans le dépôt source ou une valeur susceptible d'évoluer, écrite en dur +dans le code. + +Au moment de développer une nouvelle fonctionnalité, réfléchissez si +l'un des composants utilisés risquerait de subir une modification: ce +composant peut concerner une nouvelle chaîne de connexion, un point de +terminaison nécessaire à télécharger des données officielles ou un +chemin vers un répertoire partagé pour y déposer un fichier. + +\subsection{\#4 - Traiter les ressources externes comme des ressources +attachées} + +Nous parlons de bases de données, de services de mise en cache, d'API +externes, \ldots\hspace{0pt} L'application doit être capable d'effectuer +des changements au niveau de ces ressources sans que son code ne soit +modifié. Nous parlons alors de \textbf{ressources attachées}, dont la +présence est nécessaire au bon fonctionnement de l'application, mais +pour lesquelles le \textbf{type} n'est pas obligatoirement défini. + +Nous voulons par exemple "une base de données" et "une mémoire cache", +et pas "une base MariaDB et une instance Memcached". De cette manière, +les ressources peuvent être attachées et détachées d'un déploiement à la +volée. + +Si une base de données ne fonctionne pas correctement (problème matériel +?), l'administrateur pourrait simplement restaurer un nouveau serveur à +partir d'une précédente sauvegarde, et l'attacher à l'application sans +que le code source ne soit modifié. une solution consiste à passer +toutes ces informations (nom du serveur et type de base de données, clé +d'authentification, \ldots\hspace{0pt}) directement \emph{via} des +variables d'environnement. + +\includegraphics{images/12factors/attached-resources.png} + +Nous serons ravis de pouvoir simplement modifier une chaîne +\texttt{sqlite:////tmp/my-tmp-sqlite.db\textquotesingle{}} en +\texttt{psql://user:pass@127.0.0.1:8458/db} lorsque ce sera nécessaire, +sans avoir à recompiler ou redéployer les modifications. + +\subsection{\#5 - Séparer proprement les phases de construction, de mise à +disposition et d'exécution} + +\begin{enumerate} +\def\labelenumi{\arabic{enumi}.} +\item + La \textbf{construction} (\emph{build}) convertit un code source en un + ensemble de fichiers exécutables, associé à une version et à une + transaction dans le système de gestion de sources. +\item + La \textbf{mise à disposition} (\emph{release}) associe cet ensemble à + une configuration prête à être exécutée, +\item + tandis que la phase d'\textbf{exécution} (\emph{run}) démarre les + processus nécessaires au bon fonctionnement de l'application. +\end{enumerate} + +\includegraphics{images/12factors/release.png} + +Parmi les solutions possibles, nous pourrions nous pourrions nous baser +sur les \emph{releases} de Gitea, sur un serveur d'artefacts ou sur +\href{https://fr.wikipedia.org/wiki/Capistrano_(logiciel)}{Capistrano}. + +\subsection{\#6 - Les processus d'exécution ne doivent rien connaître ou +conserver de l'état de l'application} + +Toute information stockée en mémoire ou sur disque ne doit pas altérer +le comportement futur de l'application, par exemple après un redémarrage +non souhaité. + +Pratiquement, si l'application devait rencontrer un problème, l'objectif +est de pouvoir la redémarrer rapidement sur un autre serveur (par +exemple suite à un problème matériel). Toute information qui aurait été +stockée durant l'exécution de l'application sur le premier hôte serait +donc perdue. Si une réinitialisation devait être nécessaire, +l'application ne devra pas compter sur la présence d'une information au +niveau du nouveau système. La solution consiste donc à jouer sur les +variables d'environnement (cf. \#3) et sur les informations que l'on +pourra trouver au niveau des ressources attachées (cf \#4). + +Il serait également difficile d'appliquer une mise à l'échelle de +l'application, en ajoutant un nouveau serveur d'exécution, si une donnée +indispensable à son fonctionnement devait se trouver sur la seule +machine où elle est actuellement exécutée. + +\subsection{\#7 - Autoriser la liaison d'un port de l'application à un port +du système hôte} + +Les applications 12-factors sont auto-contenues et peuvent fonctionner +en autonomie totale. Elles doivent être joignables grâce à un mécanisme +de ponts, où l'hôte qui s'occupe de l'exécution effectue lui-même la +redirection vers l'un des ports ouverts par l'application, typiquement, +en HTTP ou via un autre protocole. + +\includegraphics{images/diagrams/12-factors-7.png} + +\subsection{\#8 - Faites confiance aux processus systèmes pour l'exécution +de l'application} + +Comme décrit plus haut (cf. \#6), l'application doit utiliser des +processus \emph{stateless} (sans état). Nous pouvons créer et utiliser +des processus supplémentaires pour tenir plus facilement une lourde +charge, ou dédier des processus particuliers pour certaines tâches: +requêtes HTTP \emph{via} des processus Web; \emph{long-running} jobs +pour des processus asynchrones, \ldots\hspace{0pt} Si cela existe au +niveau du système, ne vous fatiguez pas: utilisez le. + +\includegraphics{images/12factors/process-types.png} + +\subsection{\#9 - Améliorer la robustesse de l'application grâce à des +arrêts élégants et à des démarrages rapides} + +Par "arrêt élégant", nous voulons surtout éviter le +\texttt{kill\ -9\ \textless{}pid\textgreater{}} ou tout autre arrêt +brutal d'un processus qui nécessiterait une intervention urgente du +superviseur. De cette manière, les requêtes en cours peuvent se terminer +au mieux, tandis que le démarrage rapide de nouveaux processus +améliorera la balance d'un processus en cours d'extinction vers des +processus tout frais. + +L'intégration de ces mécanismes dès les premières étapes de +développement limitera les perturbations et facilitera la prise en +compte d'arrêts inopinés (problème matériel, redémarrage du système +hôte, etc.). + +\subsection{\#10 - Conserver les différents environnements aussi similaires +que possible, et limiter les divergences entre un environnement de +développement et de production} + +L'exemple donné est un développeur qui utilise macOS, NGinx et SQLite, +tandis que l'environnement de production tourne sur une CentOS avec +Apache2 et PostgreSQL. Faire en sorte que tous les environnements soient +les plus similaires possibles limite les divergences entre +environnements, facilite les déploiements et limite la casse et la +découverte de modules non compatibles dès les premières phases de +développement. + +Pour vous donner un exemple tout bête, SQLite utilise un +\href{https://www.sqlite.org/datatype3.html}{mécanisme de stockage +dynamique}, associée à la valeur plutôt qu'au schéma, \emph{via} un +système d'affinités. Un autre moteur de base de données définira un +schéma statique et rigide, où la valeur sera déterminée par son +contenant. Un champ \texttt{URLField} proposé par Django a une longeur +maximale par défaut de +\href{https://docs.djangoproject.com/en/3.1/ref/forms/fields/\#django.forms.URLField}{200 +caractères}. Si vous faites vos développements sous SQLite et que vous +rencontrez une URL de plus de 200 caractères, votre développement sera +passera parfaitement bien, mais plantera en production (ou en +\emph{staging}, si vous faites les choses un peu mieux) parce que les +données seront tronquées\ldots\hspace{0pt} + +Conserver des environements similaires limite ce genre de désagréments. + +\subsection{\#11 - Gérer les journeaux d'évènements comme des flux} + +Une application ne doit jamais se soucier de l'endroit où ses évènements +seront écrits, mais simplement de les envoyer sur la sortie +\texttt{stdout}. De cette manière, que nous soyons en développement sur +le poste d'un développeur avec une sortie console ou sur une machine de +production avec un envoi vers une instance +\href{https://www.graylog.org/}{Greylog} ou +\href{https://sentry.io/welcome/}{Sentry}, le routage des journaux sera +réalisé en fonction de sa nécessité et de sa criticité, et non pas parce +que le développeur l'a spécifié en dur dans son code. Cette phase est +critique, dans la mesure où les journaux d'exécution sont la seule +manière pour une application de communiquer son état vers l'extérieur: +recevoir une erreur interne de serveur est une chose; pouvoir obtenir un +minimum d'informations, voire un contexte de plantage complet en est une +autre. + +\subsection{\#12 - Isoler les tâches administratives du reste de +l'application} + +Evitez qu'une migration ne puisse être démarrée depuis une URL de +l'application, ou qu'un envoi massif de notifications ne soit accessible +pour n'importe quel utilisateur: les tâches administratives ne doivent +être accessibles qu'à un administrateur. Les applications 12facteurs +favorisent les langages qui mettent un environnement REPL (pour +\emph{Read}, \emph{Eval}, \emph{Print} et \emph{Loop}) à disposition (au +hasard: \href{https://pythonprogramminglanguage.com/repl/}{Python} ou +\href{https://kotlinlang.org/}{Kotlin}), ce qui facilite les étapes de +maintenance. + + \section{Tests unitaires et d'intégration} \begin{quote}