gwift-book/chapters/architecture.tex

186 lines
9.1 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\chapter{Elements d'architecture}
\begin{quote}
If you think good architecture is expensive, try bad architecture
--- Brian Foote and Joseph Yoder
\end{quote}
Au delà des principes dont il est question plus haut, c'est dans les
ressources proposées et les cas démontrés que l'on comprend leur
intérêt: plus que de la définition d'une architecture adéquate, c'est
surtout dans la facilité de maintenance d'une application que ces
principes s'identifient.
Une bonne architecture va rendre le système facile à lire, facile à
développer, facile à maintenir et facile à déployer. L'objectif ultime
étant de minimiser le coût de maintenance et de maximiser la
productivité des développeurs. Un des autres objectifs d'une bonne
architecture consiste également à se garder le plus d'options possibles,
et à se concentrer sur les détails (le type de base de données, la
conception concrète, le plus tard possible, tout en
conservant la politique principale en ligne de mire. Cela permet de
délayer les choix techniques à «~plus tard~», ce qui permet également de
concrétiser ces choix en ayant le plus d'informations possibles
\cite[pp.137-141]{clean_architecture}
Derrière une bonne architecture, il y a aussi un investissement quant
aux ressources qui seront nécessaires à faire évoluer l'application: ne
pas investir dès qu'on le peut va juste lentement remplir la case de la
dette technique.
Une architecture ouverte et pouvant être étendue n'a d'intérêt que si le
développement est suivi et que les gestionnaires (et architectes)
s'engagent à économiser du temps et de la qualité lorsque des
changements seront demandés pour l'évolution du projet.
\section{Politiques et règles métiers}
\section{Considérations sur les frameworks}
\begin{quote}
Frameworks are tools to be used, not architectures to be conformed to.
Your architecture should tell readers about the system, not about the
frameworks you used in your system. If you are building a health care
system, then when new programmers look at the source repository, their
first impression should be, «~oh, this is a health care system~». Those
new programmers should be able to learn all the use cases of the system,
yet still not know how the system is delivered.
--- Robert C. Martin Clean Architecture
\end{quote}
Le point soulevé ci-dessous est qu'un framework n'est qu'un outil, et
pas une obligation de structuration. L'idée est que le framework doit se
conformer à la définition de l'application, et non l'inverse. Dans le
cadre de l'utilisation de Django, c'est un point critique à prendre en
considération: une fois que vous aurez fait ce choix, vous aurez
extrêmement difficile à faire machine arrière:
\begin{itemize}
\item
Votre modèle métier sera largement couplé avec le type de base de
données (relationnelle, indépendamment
\item
Votre couche de présentation sera surtout disponible au travers d'un
navigateur
\item
Les droits d'accès et permissions seront en grosse partie gérés par le
frameworks
\item
La sécurité dépendra de votre habilité à suivre les versions
\item
Et les fonctionnalités complémentaires (que vous n'aurez pas voulu/eu
le temps de développer) dépendront de la bonne volonté de la
communauté
\end{itemize}
Le point à comprendre ici n'est pas que "Django, c'est mal", mais qu'une
fois que vous aurez défini la politique, les règles métiers, les données
critiques et entités, et que vous aurez fait le choix de développer en
âme et conscience votre nouvelle création en utilisant Django, vous
serez bon gré mal gré, contraint de continuer avec. Cette décision ne
sera pas irrévocable, mais difficile à contourner.
\begin{quote}
At some point in their history most DevOps organizations were hobbled by
tightly-coupled, monolithic architectures that while extremely
successfull at helping them achieve product/market fit - put them at
risk of organizational failure once they had to operate at scale (e.g.
eBay's monolithic C++ application in 2001, Amazon's monolithic OBIDOS
application in 2001, Twitter's monolithic Rails front-end in 2009, and
LinkedIn's monolithic Leo application in 2011). In each of these cases,
they were able to re-architect their systems and set the stage not only
to survice, but also to thrise and win in the marketplace.
\cite[182]{devops_handbook}
\end{quote}
Ceci dit, Django compense ses contraintes en proposant énormément de
flexibilité et de fonctionnalités \textbf{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.
\begin{quote}
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
\end{quote}
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.
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, \ldots\hspace{0pt}). Une application
monolotihique sera tout aussi fonctionnelle qu'une application découpée
en microservices. \cite[243]{clean_architecture}
\section{Inversion de dépendances}
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 link:release
notes{[}\url{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{[}\url{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:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
Si vos données sont stockées dans un moteur géré par Oracle 11.2, vous
serez limité à une version 1.11 de Django
\item
Tandis que si votre moteur est géré par une version ultérieure, le
framework pourra être mis à jour.
\end{enumerate}
Nous sommes dans un cas concret d'inversion de dépendances ratée: le
framework (et encore moins vos politiques et règles métiers) ne
devraient pas avoir connaissance du moteur de base de données. Pire, vos
politiques et données métiers ne devraient pas avoir connaissance
\textbf{de la version} du moteur de base de données.
En conclusion, le choix d'une version d'un moteur technique (\textbf{la
base de données}) a une incidence directe sur les fonctionnalités mises
à disposition par votre application, ce qui va à l'encontre des 12
facteurs (et des principes de développement).
Ce point sera rediscuté par la suite, notamment au niveau de l'épinglage
des versions, de la reproduction des environnements et de
l'interdépendance entre des choix techniques et fonctionnels.
\section{Conclusions}
\begin{quote}
La perfection est atteinte, non pas lorsqu'il n'y a plus rien à ajouter, mais lorsqu'il n'y a plus rien à retirer.
-- Antoine de Saint-Exupéry
\end{quote}
Il est impossible de se projeter dans le futur d'une application: il est impossible d'imaginer les modifications qui seront demandées par les utilisateurs, de se projeter dans l'évolution d'un langage, dans les nécessités d'intégration de certaines librairies ou dans le support-même de certaines fonctionnalités par les navigateurs Web.
Ce sont des choses qui viennent avec l'expérience (ou avec la tordure d'esprit \footnote{Si, ça existe}).
Cela rejoint le fameux "YAGNI\index{YAGNI}" dont nous parlions plus tôt: il est inutile de vouloir développer absolument toutes les fonctionnalités qui pourraient un jour pouvoir être utilisées ou souhaitées, car cela complexifiera autant le code, que les déploiement, l'utilisabilité ou la compréhension que les utilisateurs pourront avoir de votre application. \cite{rework}
Il est impossible d'imaginer ou de se projeter dans tous les éléments qui pourraient devoir être modifiés après que votre a
En ayant connaissance de toutes les choses qui pourraient être modifiées par la suite,
lidée est de pousser le développement jusquau point où un service pourrait être nécessaire.
A ce stade, larchitecture nécessitera des modifications, mais aura déjà intégré le fait que
cette possibilité existe. Nous nallons donc pas jusquau point où le service doit être créé
(même sil peut ne pas être nécessaire), ni à lextrême au fait dignorer quun service
pourrait être nécessaire, mais nous aboutissons à une forme de compromis. Une forme
de comportement de Descartes, qui ne croit pas en Dieu, mais qui envisage quand même
cette possibilité, ce qui lui ouvre le maximum de portes.