Pourquoi structurer son code ?
Plus les projets de programmation se complexifient, plus ils deviennent difficiles à comprendre. À mesure que vous ajoutez de plus en plus de classes, bibliothèques et fonctions à votre code, il devient plus ardu de découvrir où se cachent les problèmes et de savoir ce que font les différentes parties de votre code.
Cela pose moins de problèmes lorsque vous débutez en tant que développeur, mais dès que vous aurez besoin que quelqu’un d’autre utilise un projet, ou que vous travaillerez en équipe, vous devrez commencer à trouver des solutions pour rendre votre projet plus compréhensible. Vous serez même surpris de voir à quel point il est difficile de revenir à un projet après l’avoir laissé de côté pendant quelques mois !
C’est important de structurer son code, car cela diminue les efforts nécessaires à sa maintenance et à son extension. Cela garantit que les nouveaux développeurs puissent rapidement se familiariser avec un projet et ses éléments internes.
En finalité, le fait de structurer son code permet de devenir plus efficace.
Nous pouvons prendre en compte certains principes en écrivant notre code :
Principe n°1 : la découvrabilité
La découvrabilité désigne la facilité ou la difficulté à trouver l’emplacement de fonctionnalités précises. La découvrabilité peut aussi faire référence à la difficulté de compréhension du code lui-même : est-ce que l’on comprend clairement ce que fait le code, simplement en le regardant ? Ou faut-il aller chercher ailleurs pour comprendre ?
Nous pouvons garantir une bonne découvrabilité en découpant notre code de façon logique, avec des fichiers et des dossiers qui assurent que les sections de code ayant des fonctionnalités similaires soit regroupées.
Principe n°2 : la simplicité
On peut également garantir que chaque section de code ait aussi peu de responsabilités que possible – de préférence une seule ! Les fonctions et méthodes qui ne font qu’une seule chose sont plus faciles à comprendre et à tester.
Principe n°3 : le style
Un code bien structuré a un style cohérent. Pour un projet professionnel ou open source, vous aurez un guide de style. Suivez-le pour garantir que votre code et celui de vos collègues et collaborateurs soient similaires.
Structurez votre code
Les outils les plus utiles pour structurer du code sont simplement les fichiers et les dossiers. Le découpage de nos programmes en fichiers et dossiers (bien nommés) aide à la découvrabilité.
De façon générale, il convient de placer chaque classe dans un fichier distinct, et de donner un nom logique ou similaire entre le module et la classe qu’il contient. Si cela n’est pas possible ou pas souhaitable, on peut placer un groupe de classes liées logiquement dans le même fichier, avec un nom approprié.
Il est également important de nommer de façon logique les classes, fonctions/méthodes et variables. Les noms doivent raconter une histoire. Regardez cette fonction :
def calculation(a, b):
return a * (1 - (b / 100))
Que fait-elle ? Eh bien…
def subtract_discount(price, discount):
return price * (1 - (discount / 100))
Avec ces noms, il apparaît tout de suite évident que cette fonction soustrait un pourcentage de réduction donné à un prix.
Les noms de classe doivent être tout aussi logiques. Vous vous souvenez de notre ContactSystem
et de ses sous-classes de tout à l’heure ?
Ces noms montrent clairement ce que font ces classes, et qu’elles sont liées entre elles. Nous devrions utiliser la même compréhension conceptuelle que pour concevoir nos classes, dans nos décisions sur la façon de structurer notre code !
Modules et paquets Python
À ce stade, vous devriez avoir utilisé des bibliothèques externes dans vos programmes, avec la déclarationimport
pour importer du code externe à votre programme.
Un module, c’est simplement le code exécutable et les définitions de classe/fonction contenus dans un fichier Python unique, alors qu’un paquet (ou package) est une collection de modules regroupés logiquement dans un répertoire et partageant un fichier de configuration (__init__.py
).
Cet __init__.py
peut contenir n’importe quel code d’initialisation, et contient parfois une définition__all__
, qui définit tous les modules du paquet, comme ceci :
__all__ = ["contact", "textcontact", "owlcontact"]
En plaçant ainsi les modules dans un paquet, nous obtenons des déclarations import plus logiques – ce qui est particulièrement utile si vous fournissez votre code comme bibliothèque à quelqu’un d’autre. Par exemple, si la déclaration « all » ci-dessus se trouve dans un dossier nommécontact
, nous pouvons faire ceci :
from contact import contact, textcontact, owlcontact
text = textcontact.TextContactSystem("01234 567890")
Nous pourrions également importer uniquement le système SMS avec :
import textcontact.TextContactSystem
En structurant notre code logiquement avec des modules et des paquets, nous pouvons le rendre plus simple en termes de navigation et d’utilisation.
Voici un schéma courant dans les programmes Python :
if __name__ == "__main__":
do_something()
print("Hello, World")
Qu’est-ce que nous voyons dans ce schéma ?
__name__
est une variable automatiquement assignée à chaque module. Par défaut, elle contient le nom du module.Vous pouvez voir que l’on teste l’égalité entre la variable
__name__
et le nom__main__
.
Mais pourquoi ? Je ne nomme jamais mes fichiers __main__
, moi !
En effet, ce nom n’est pas un nom que vous utiliserez pour nommer vos fichiers. Cependant, le fichier principal de votre code (celui que vous utilisez pour lancer le programme) verra automatiquement son nom changé en __main__
!
Cette condition permet donc d'exécuter du code seulement si le fichier courant est le point d’entrée de l’application. Le code ne s'exécutera donc pas si ce fichier a été importé depuis un autre module.
Il est particulièrement important de noter que vous avez très peu de contrôle sur l’ordre du code dans les différents paquets importés : ne vous reposez dessus que pour l’import de paquets et la configuration, et rien d’autre !
À vous de jouer : structurez un logiciel existant
Téléchargez ce fichier et importez-le dans l’éditeur de votre choix. Vous pouvez constater qu’il est plein de classes, de fonctions et de code autre, tous mélangés dans un seul fichier.
Découpez le programme en modules et en paquets, en ajoutant des fichiers__init__.py
et des déclarations import là où c’est nécessaire. Assurez-vous que le programme lui-même puisse être exécuté en exécutant unmain.py
dans le répertoire à la racine du projet.
En résumé
Un fichier Python, contenant du code Python, est appelé un module.
Un paquet est un répertoire de modules Python contenant un fichier
__init__.py
.Nous pouvons utiliser des déclarations import pour inclure des classes et des fonctions d’autres modules et paquets Python.
Maintenant que nous connaissons les mécanismes à utiliser pour structurer notre code, nous allons nous pencher dans le prochain chapitre sur les mécanismes de pensée et les décisions de conception impliqués dans la décomposition d’un problème.