diff --git a/source/main.adoc b/source/main.adoc index 2d82d41..c60da59 100644 --- a/source/main.adoc +++ b/source/main.adoc @@ -10,12 +10,13 @@ Cédric Declerfayt ; Fred Pauchet :source-highlighter: rouge :icons: font -Nous n'allons pas vous mentir: il existe enormément de tutoriaux très bien réalisés sur "_Comment réaliser une application Django_" et autres "_Déployer votre code en 2 minutes_". Nous nous disions juste que ces tutoriaux restaient relativement haut-niveaux et se limitaient à un contexte donné. +Nous n'allons pas vous mentir: il existe enormément de tutoriaux très bien réalisés sur "_Comment réaliser une application Django_" et autres "_Déployer votre code en 2 minutes_". +Nous nous disions juste que ces tutoriaux restaient relativement haut-niveaux et se limitaient à un contexte donné, et ne préparaient pas réellement à la maintenance et au suivi d'une application. -L'idée du texte ci-dessous est de jeter les bases d'un bon développement, en survolant l'ensemble des outils permettant de suivre des lignes directrices reconnues, de maintenir une bonne qualité de code au travers des différentes étapes (du développement au déploiement) et de s'assurer du maintient correct de la base de code, en permettant à n'importe qui de reprendre le développement. +L'idée du texte ci-dessous est de jeter les bases d'un bon développement, en survolant l'ensemble des outils permettant de suivre des lignes directrices reconnues, de maintenir une bonne qualité de code au travers des différentes étapes menant jusqu'au déploiement et de s'assurer du maintient correct de la base de code, en permettant à n'importe qui de reprendre ce qui aura déjà été écrit. Ces idées ne s'appliquent pas uniquement à Django et à son cadre de travail, ni même au langage Python. -Juste que ces deux sujets sont de bons candidats et que le cadre de travail est bien défini et suffisamment flexible. +Ces deux sujets sont cependant de bons candidats et leur cadre de travail est bien défini, documenté et suffisamment flexible. Django se présente comme un "link:https://www.djangoproject.com/[Framework Web pour perfectionnistes ayant des deadlines]" et suit https://docs.djangoproject.com/en/dev/misc/design-philosophies/[ces quelques principes]: @@ -24,10 +25,8 @@ Django se présente comme un "link:https://www.djangoproject.com/[Framework Web * https://fr.wikipedia.org/wiki/Ne_vous_r%C3%A9p%C3%A9tez_pas[Don't repeat yourself]: on ne se répète pas ! * Rapidité du développement (après une petite courbe d'apprentissage un peu ardue au début ;-)) -Mis côte à côte, l'application de ces principes permet une meilleure stabilité du projet à moyen et long terme. -Comme nous le verrons par la suite, et sans être parfait, Django offre une flexibilité énorme -qui permet de laisser le maximum d'options ouvertes, mais également d'expérimenter facilement plusieurs pistes simultanément, -jusqu'au moment de prendre une vraie décision. +Mis côte à côte, l'application de ces principes permet une bonne stabilité du projet à moyen et long terme. +Comme nous le verrons par la suite, et sans être parfait, Django offre une flexibilité énorme qui permet de laisser le maximum d'options ouvertes, mais également d'expérimenter facilement plusieurs pistes simultanément, jusqu'au moment de prendre une vraie décision. 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. @@ -47,7 +46,7 @@ Nous aborderons les concepts clés qui permettent à une application de rester m *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.footnote:[Avec un peu d'https://www.xkcd.com[XKCD] dedans] Oui. :-) +Et tout ça à un seul et même endroit.footnote:[Avec même un peu d'https://www.xkcd.com[XKCD]] et de Calvin & Hobbes dedans. Bonne lecture. diff --git a/source/part-1-workspace/_main.adoc b/source/part-1-workspace/_main.adoc index a2b7297..b01bd6c 100644 --- a/source/part-1-workspace/_main.adoc +++ b/source/part-1-workspace/_main.adoc @@ -33,9 +33,6 @@ dès que vous en aurez détourné le regard. Un des objectifs ici est de placer les barrières et les gardes-fous (ou plutôt, les "*garde-vous*"), afin de péréniser au maximum les acquis, stabiliser les bases de tous les environnements (du développement à la production) qui pourraient accueillir notre application et fiabiliser les étapes de communication. -[quote, Robert C. Martin, Clean Architecture, Chapitre 15, What is architecture ?, page 137] -A software system that is hard to develop is not likely to have a long and healthy lifetime - Dans cette partie, nous allons parler de *méthodes de travail*, avec comme objectif d'éviter que l'application ne tourne que sur notre machine et que chaque déploiement ne soit une plaie à gérer. Chaque mise à jour doit être réalisable de la manière la plus simple possible: diff --git a/source/part-1-workspace/maintainable-applications/_index.adoc b/source/part-1-workspace/maintainable-applications/_index.adoc index 241a6dd..cdf23b6 100644 --- a/source/part-1-workspace/maintainable-applications/_index.adoc +++ b/source/part-1-workspace/maintainable-applications/_index.adoc @@ -1,28 +1,28 @@ -== Construire des applications ... +== Construire des applications -=== bien structurées ... +[quote, Robert C. Martin, Clean Architecture, Chapitre 15, What is architecture ?, page 137] +A software system that is hard to develop is not likely to have a long and healthy lifetime + +=== Bien structurées include::clean_architecture.adoc[] -=== évolutives ... +=== Evolutives include::12-factors.adoc[] -=== maintenables ... +=== Maintenables include::maintainable-applications.adoc[] include::mccabe.adoc[] -=== robustes, flexibles, ... +=== Robustes, flexibles include::solid.adoc[] -=== et testées. +=== Et testées -[quote] ----- +[quote, Robert C. Martin, Clean Architecture, page 203, Inner circle are policies, page 250, Chapitre 28 - The Boundaries] Tests are part of the system. -You can think of tests as the outermost circle in the architecture. +You can think of tests as the outermost circle in the architecture. Nothing within in the system depends on the tests, and the tests always depend inward on the components of the system ». --- Robert C. Martin, Clean Architecture, page 203, Inner circle are policies, page 250, Chapitre 28 - The Boundaries ----- \ No newline at end of file diff --git a/source/part-1-workspace/maintainable-applications/clean_architecture.adoc b/source/part-1-workspace/maintainable-applications/clean_architecture.adoc index 601e0bc..0f465d6 100644 --- a/source/part-1-workspace/maintainable-applications/clean_architecture.adoc +++ b/source/part-1-workspace/maintainable-applications/clean_architecture.adoc @@ -70,12 +70,9 @@ Ceci dit, Django compense ses contraintes en proposant énormément de flexibili *out-of-the-box*, c'est-à-dire que vous pourrez sans doute avancer vite et bien jusqu'à un point de rupture, puis revoir la conception et réinvestir à ce moment-là, mais en toute connaissance de cause. -[quote] ----- +[quote, Robert C. Martin, Clean Architecture, page 209] When any of the external parts of the system become obsolete, such as the database, or the web framework, you can replace those obsolete elements with a minimum of fuss. --- Robert C. Martin, Clean Architecture, page 209 ----- Avec Django, la difficulté à se passer du framework va consister à basculer vers « autre chose » et a remplacer chacune des tentacules qui aura pousser partout dans l’application. @@ -83,7 +80,7 @@ chacune des tentacules qui aura pousser partout dans l’application. NOTE: A noter que les services et les « architectures orientées services » ne sont jamais qu’une définition d’implémentation des frontières, dans la mesure où un service n’est jamais qu’une fonction appelée au travers d'un protocole (rest, soap, ...). -Une application monolotihique est tout aussi fonctionnelle qu’une application découpée en microservices. +Une application monolotihique sera tout aussi fonctionnelle qu’une application découpée en microservices. (Services: great and small, page 243). ==== Un point sur l'inversion de dépendances @@ -91,8 +88,8 @@ Une application monolotihique est tout aussi fonctionnelle qu’une application Dans la partie SOLID, nous avons évoqué plusieurs principes de développement. Django est un framework qui évolue, et qui a pu présenter certains problèmes liés à l'un de ces principes. -Les [https://docs.djangoproject.com/en/2.0/releases/2.0/](release notes) de Django 2.0 date de décembre 2017; parmi ces notes, -l'une d'elles cite l'abandon du support d'[https://docs.djangoproject.com/en/2.0/releases/2.0/#dropped-support-for-oracle-11-2](Oracle 11.2). +Les link:release notes[https://docs.djangoproject.com/en/2.0/releases/2.0/] de Django 2.0 date de décembre 2017; parmi ces notes, +l'une d'elles cite l'abandon du support d'link:Oracle 11.2[https://docs.djangoproject.com/en/2.0/releases/2.0/#dropped-support-for-oracle-11-2]. En substance, cela signifie que le framework se chargeait lui-même de construire certaines parties de requêtes, qui deviennent non fonctionnelles dès lors que l'on met le framework ou le moteur de base de données à jour. Réécrit, cela signifie que: diff --git a/source/part-2-deployment/_main.adoc b/source/part-2-deployment/_main.adoc index c0423bd..2affad5 100644 --- a/source/part-2-deployment/_main.adoc +++ b/source/part-2-deployment/_main.adoc @@ -1,29 +1,26 @@ = Déploiement -[quote] ----- -To be effective, a software system must be deployable. -The higher the cost of deployements, the less useful the system is. -A goal of a software architecture, then, should be to make a system that can be easily deployed with a single action. -Unfortunately, deployment strategy is seldom considered during initial development. -This leads to architectures that may be make the system easy to develop, but leave it very difficult to deploy. --- Robert C. Martin, Clean Architecture, Chapitre 15, page 137 ----- +[quote,Robert C. Martin, Clean Architecture, Chapitre 15, page 137] +To be effective, a software system must be deployable. +The higher the cost of deployements, the less useful the system is. +A goal of a software architecture, then, should be to make a system that can be easily deployed with a single action. +Unfortunately, deployment strategy is seldom considered during initial development. +This leads to architectures that may be make the system easy to develop, but leave it very difficult to deploy. -Il y a une raison très simple à aborder le déploiement dès maintenant: à trop attendre et à peaufiner son développement en local, +Il y a une raison très simple à aborder le déploiement dès maintenant: à trop attendre et à peaufiner son développement en local, on en oublie que sa finalité sera de se retrouver exposé sur un serveur. -Il est du coup probable d'oublier une partie des désidérata, de zapper une fonctionnalité essentielle +Il est du coup probable d'oublier une partie des désidérata, de zapper une fonctionnalité essentielle ou simplement de passer énormément de temps à adapter les sources pour qu'elles fonctionnent sur un environnement en particulier. -Un bon déploiement ne doit pas dépendre de dizaines de petits scripts éparpillés sur le disque. -L’objectif est qu'il soit rapide et fiable. -Ceci peut être atteint au travers d’un partitionnement correct, incluant le fait que le composant principal s’assure que -chaque sous-composant est correctement démarré intégré et supervisé. +Un bon déploiement ne doit pas dépendre de dizaines de petits scripts éparpillés sur le disque. +L’objectif est qu'il soit rapide et fiable. +Ceci peut être atteint au travers d’un partitionnement correct, incluant le fait que le composant principal s’assure que +chaque sous-composant est correctement démarré intégré et supervisé. Aborder le déploiement dès le début permet également de rédiger dès le début les procédures d'installation, de mises à jour et de sauvegardes. Déploier une nouvelle version sera aussi simple que de récupérer la dernière archive depuis le dépôt, la placer dans le bon répertoire, appliquer des actions spécifiques (et souvent identiques entre deux versions), puis redémarrer les services adéquats, et la procédure complète se résumera à quelques lignes d'un script bash. Le serveur que django met à notre disposition _via_ la commande `runserver` est extrêmement pratique, mais il est uniquement prévu pour la phase développement: en production, il est inutile de passer par du code Python pour charger des fichiers statiques (feuilles de style, fichiers JavaScript, images, ...). -De même, Django propose par défaut une base de données SQLite, qui fonctionne parfaitement dès lors que l'on connait ses limites et que l'on se limite à un utilisateur à la fois. En production, il est légitime que la base de donnée soit capable de supporter plusieurs utilisateurs et connexions simultanément... +De même, Django propose par défaut une base de données SQLite, qui fonctionne parfaitement dès lors que l'on connait ses limites et que l'on se limite à un utilisateur à la fois. En production, il est légitime que la base de donnée soit capable de supporter plusieurs utilisateurs et connexions simultanément... En restant avec les paramètres par défaut, il est plus que probable que vous rencontriez rapidement des erreurs de verrou parce qu'un autre processus a déjà pris la main pour écrire ses données. En bref, vous avez quelque chose qui fonctionne, mais qui ressemble de très loin à ce dont vous aurez besoin au final. @@ -54,14 +51,14 @@ Si nous schématisons l'infrastructure et le chemin parcouru par une requête, n . Le firewall du serveur (Debian GNU/Linux, CentOS, ...) vérifie si la requête peut être prise en compte . La requête est transmise à l'application qui écoute sur le port (probablement 80 ou 443; et _a priori_ Nginx) . Elle est ensuite transmise par socket et est prise en compte par un des _workers_ (= un processus Python) instancié par Gunicorn. Si l'un de ces travailleurs venait à planter, il serait automatiquement réinstancié par Supervisord. -. Qui la transmet ensuite à l'un de ses _workers_ (= un processus Python). +. Qui la transmet ensuite à l'un de ses _workers_ (= un processus Python). . Après exécution, une réponse est renvoyée à l'utilisateur. image::images/diagrams/architecture.png[] === Reverse proxy -Le principe du *proxy inverse* est de pouvoir rediriger du trafic entrant vers une application hébergée sur le système. +Le principe du *proxy inverse* est de pouvoir rediriger du trafic entrant vers une application hébergée sur le système. Il serait tout à fait possible de rendre notre application directement accessible depuis l'extérieur, mais le proxy a aussi l'intérêt de pouvoir élever la sécurité du serveur (SSL) et décharger le serveur applicatif grâce à un mécanisme de cache ou en compressant certains résultats footnote:[https://fr.wikipedia.org/wiki/Proxy_inverse] @@ -174,4 +171,3 @@ See https://mattsegal.dev/nginx-django-reverse-proxy-config.html * https://docs.djangoproject.com/fr/3.0/howto/deployment/[Déploiement]. * Let's Encrypt ! -