Conclude first chapter
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Fred Pauchet 2022-04-12 19:48:27 +02:00
parent c4ebdaa48b
commit 7e6ea730de
4 changed files with 93 additions and 176 deletions

View File

@ -1,170 +1,4 @@
\begin{Shaded}
\begin{Highlighting}[]
\ControlFlowTok{if} \VariableTok{True} \OperatorTok{==} \VariableTok{False}\NormalTok{:}
\ControlFlowTok{pass} \CommentTok{\# never happens}
\CommentTok{\# continue ...}
\end{Highlighting}
\end{Shaded}
TODO: faut vraiment reprendre un cas un peu plus lisible. Là, c'est
naze.
\hypertarget{_conclusion}{%
\subsection{Conclusion}\label{_conclusion}}
En ayant connaissance de toutes les choses qui pourraient être modifiées
par la suite, l'idée est de pousser le développement jusqu'au point où
un service pourrait être nécessaire. A ce stade, l'architecture
nécessitera des modifications, mais aura déjà intégré le fait que cette
possibilité existe. Nous n'allons donc pas jusqu'au point où le service
doit être créé (même s'il peut ne pas être nécessaire), ni à l'extrême
au fait d'ignorer qu'un 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 🙃
Avec cette approche, les composants sont déjà découplés au niveau du
code source, ce qui pourrait s'avérer suffisant jusqu'au stade où une
modification ne pourra plus faire reculer l'échéance.
En terme de découpe, les composants peuvent l'être aux niveaux suivants:
\begin{itemize}
\item
Code source
\item
Déploiement, au travers de dll, jar, linked libraries, \ldots{} voire
au travers de threads ou de processus locaux.
\item
Services
\end{itemize}
Cette section se base sur deux ressources principales
cite:{[}maintainable\_software{]} cite:{[}clean\_code{]}, qui
répartissent un ensemble de conseils parmi quatre niveaux de composants:
\begin{itemize}
\item
Les méthodes et fonctions
\item
Les classes
\item
Les composants
\item
Et des conseils plus généraux.
\end{itemize}
Ces conseils sont valables pour n'importe quel langage.
\hypertarget{_au_niveau_des_muxe9thodes_et_fonctions}{%
\subsubsection{Au niveau des méthodes et
fonctions}\label{_au_niveau_des_muxe9thodes_et_fonctions}}
\begin{itemize}
\item
\textbf{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.
\item
\textbf{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 ayant chacune une complexité de 5 conservera la complexité
globale à 15, mais rendra le code de chacune de ces méthodes plus
lisible, plus maintenable.
\item
\textbf{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.
\item
\textbf{Conservez de petites interfaces}. Quatre paramètres, pas plus.
Au besoin, refactorisez certains paramètres dans une classe ou une
structure, qui sera plus facile à tester.
\end{itemize}
\hypertarget{_au_niveau_des_classes}{%
\subsubsection{Au niveau des classes}\label{_au_niveau_des_classes}}
\begin{itemize}
\item
\textbf{Privilégiez un couplage faible entre vos classes}. Ceci n'est
pas toujours possible, mais dans la mesure du possible, éclatez vos
classes en fonction de leur domaine de compétences respectif.
L'implémentation du service \texttt{UserNotificationsService} ne doit
pas forcément se trouver embarqué dans une classe
\texttt{UserService}. De même, pensez à passer par une interface
(commune à plusieurs classes), afin d'ajouter une couche
d'abstraction. La classe appellante n'aura alors que les méthodes
offertes par l'interface comme points d'entrée.
\end{itemize}
\hypertarget{_au_niveau_des_composants}{%
\subsubsection{Au niveau des
composants}\label{_au_niveau_des_composants}}
\begin{itemize}
\item
\textbf{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, "\emph{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 \texttt{IFileTransfer} avec
ses méthodes \texttt{put} et \texttt{get}, et non pas les détails
d'implémentation complet d'une classe \texttt{FtpFileTransfer} ou
\texttt{SshFileTransfer}).
\item
\textbf{Conserver un bon balancement au niveau des composants}: évitez
qu'un composant \textbf{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.
\end{itemize}
\hypertarget{_de_maniuxe8re_plus_guxe9nuxe9rale}{%
\subsubsection{De manière plus
générale}\label{_de_maniuxe8re_plus_guxe9nuxe9rale}}
\begin{itemize}
\item
\textbf{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.
\item
\textbf{Automatiser les tests}, \textbf{ajouter un environnement
d'intégration continue dès le début du projet} et \textbf{vérifier par
des outils les points ci-dessus}.
\end{itemize}
Unresolved directive in part-1-workspace/\_main.adoc -
include::mccabe.adoc{[}{]}
\hypertarget{_fiabilituxe9_uxe9volutivituxe9_et_maintenabilituxe9}{%
\section{Fiabilité, évolutivité et
maintenabilité}\label{_fiabilituxe9_uxe9volutivituxe9_et_maintenabilituxe9}}

View File

@ -174,12 +174,94 @@ Il est impossible de se projeter dans le futur d'une application: il est impossi
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.
Il est impossible d'imaginer ou de se projeter dans tous les éléments qui pourraient devoir être modifiés après que votre développement ait été livrée.
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ù une décision pourrait devoir être faite.
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 d'application de la philosophie de René Descartes, où le fait de seulement envisager une possibilité ouvre un maximum de portes.
Avec cette approche, les composants seront déjà découplés au mieux.
En terme de découpe, les composants peuvent l'être aux niveaux suivants:
\begin{itemize}
\item
\textbf{Code source}
\item
\textbf{Déploiement}, au travers de dll, jar, linked libraries, \ldots{} voire
au travers de threads ou de processus locaux.
\item
\textbf{Mise à disposition de services}
\end{itemize}
Cette section se base sur deux ressources principales \cite{maintainable_software} \cite{clean_code}, qui répartissent un ensemble de conseils parmi quatre niveaux de composants:
\begin{itemize}
\item
Les méthodes et fonctions
\item
Les classes
\item
Les composants
\item
Et des conseils plus généraux.
\end{itemize}
\subsection{Au niveau des méthodes et fonctions}
\begin{itemize}
\item
\textbf{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.
\item
\textbf{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 ayant chacune une complexité de 5 conservera la complexité globale à 15, mais rendra le code de chacune de ces méthodes plus lisible, plus maintenable.
\item
\textbf{N'écrivez votre code qu'une seule fois: évitez les duplications, copie, etc.}: 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.
\item
\textbf{Conservez de petites interfaces et signatures de fonctions/méthodes}. Quatre paramètres, pas plus.
Au besoin, refactorisez certains paramètres dans une classe ou une structure, qui sera plus facile à tester.
\end{itemize}
\subsection{Au niveau des classes}
\begin{itemize}
\item
\textbf{Privilégiez un couplage faible entre vos classes}.
Ceci n'est pas toujours possible, mais dans la mesure du possible, éclatez vos classes en fonction de leur domaine de compétences respectif.
L'implémentation du service \texttt{UserNotificationsService} ne doit pas forcément se trouver embarqué dans une classe \texttt{UserService}.
De même, pensez à passer par une interface (commune à plusieurs classes), afin d'ajouter une couche d'abstraction.
La classe appellante n'aura alors que les méthodes offertes par l'interface comme points d'entrée.
\end{itemize}
\subsection{Au niveau des composants}
\begin{itemize}
\item
\textbf{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, "\emph{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 \texttt{IFileTransfer} avec ses méthodes \texttt{put} et \texttt{get}, et non pas les détailsd'implémentation complet d'une classe \texttt{FtpFileTransfer} ou \texttt{SshFileTransfer}).
\item
\textbf{Conserver un bon balancement au niveau des composants}: évitez qu'un composant \textbf{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.
\end{itemize}
\subsection{De manière générale}
\begin{itemize}
\item
\textbf{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 faisantdu 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.
\item
\textbf{Automatiser les tests}, en ajoutant un environnement d'intégration continue dès le début du projet et en faisant vérifier par des outils automatiques tous les points ci-dessus.
\end{itemize}

View File

@ -152,7 +152,7 @@ protocoles du langage.
\section{The Zen of Python}
\begin{listing}[!ht]
\begin{listing}[!h]
\begin{verbatim}
>>> import this
The Zen of Python, by Tim Peters

View File

@ -36,6 +36,7 @@
\listoffigures
\listoftables
%\listoflistings
\clearpage
\addcontentsline{toc}{chapter}{\listlistingname}{\listoflistings}
\mainmatter