Guidelines de développement

Principes généraux

En règle générale, il faut suivre les principes suivants: - Lisibilité - à quel point le code est compréhensible - Maintenabilité - Comment le code permet au projet d'évoluer - Risque - Sécurité, réglementations et autres vulnérabilités - Correction - Si le code fait ce que vous voulez - Robustesse - Comment le code gère les circonstances non prévues - Performance - L'efficacité en termes de ressources du code

Lisibilité

Le code est lisible s'il répond à nos attentes et ne nous surprend que lorsqu'il y a quelque chose qu'on ne connais pas encore à propos de la technologie. On attends du code qu'il ressemble aux autres codes autour. Qu'il suive la plupart, sinon tous les idiomes de la technologie. Qu'il utilise des noms clairs et informatifs. Qu'il explique pourquoi une déviance existe.

Maintenabilité

La maintenabilité est la relation du code avec l'équipe et le temps. On doit être capable d'apprendre tout ce qu'on doit savoir pour modifier, tester et déployer le code. On doit être convaincu que tout changement qu'on apporte n'entraînera pas de modifications non intentionnelles ailleurs dans le code. Pour apporter un changement, on essaiera de toucher aussi peu de code que possible. On doit pouvoir déboguer un problème le plus facilement possible. On doit pouvoir retracer et modifier rapidement les changements qui introduisent un bug. On doit pouvoir comprendre facilement pourquoi un changement existe.

Risque

Un code est à faible risque s'il tient compte, et lorsque c'est possible, atténue les divers risques pour un projet.

Correction

Le code correct fait ce qu'on attend de lui et nous surprend seulement quand il y a quelque chose à propos du système qu'on n'a pas encore compris. Le code correct n'est qu'aussi compliqué que les concepts qu'il modélise.

Robustesse

Le code robuste gère les circonstances inattendues de manière sûre, rapide et prévisible.

Performance

Le code performant est efficace en termes de ressources.

Codestyle

  • Le code doit être écrit en anglais.

  • Tout le code doit être écrit en respectant le PEP8.

  • L'utilisation de type hints est recommandée. Cheatsheet des type hints: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html

  • Flake8 est utilisé pour vérifier le code. L'intégration de Flake8 dans l'IDE est recommandée.

  • Le code doit être formaté avec Black. L'intégration de Black dans l'IDE est recommandée.

  • Les imports doivent être organisés avec l'outil isort. L'intégration de isort dans l'IDE est recommandée.

  • Tous ces outils seront configurés dans pre-commit pour vérifier le code avant chaque commit.

  • L'utilisation des f-strings est fortement recommandée pour l'interpolation des strings. str.format() ou %-formatting peuvent être utilisés dans certains cas, si ils aident à la lisibilité du code.
  • Utiliser des underscores pour les noms de variables et de fonctions. Les noms de classes doivent être en PascalCase.
  • Tous les strings doivent être marqués pour la traduction.

Dépendances

Avant d'ajouter une nouvelle dépendance, il faut vérifier plusieurs choses: - Quel est le nombre de mainteneurs du projet? Si le nombre est faible, il faut éviter d'utiliser la dépendance. - Quand a été la dernière mise à jour du projet? Si la dernière mise à jour date de plus d'un an, il faut éviter d'utiliser la dépendance. - Quel est la complexité de la dépendance? Si la dépendance n'est pas trop complexe, il vaut mieux l'implémenter soi-même. -

Django

Settings

  • Utiliser des variables d'environnement pour les valeurs qui peuvent changer entre les environnements. Par exemple, l'url de la base de données, les clés secrètes, etc.
  • Les variables d'environnement doivent être définies dans le fichier .env à la racine du projet.

Modèles

Les modèles doivent être définis dans le fichier models.py du module correspondant. Le principe "fat models, thin views" doit être respecté. L'utilisation de custom managers et querysets est recommandée pour la gestion des modèles.

Il faut éviter de modifier les valeurs des champs des modèles ou l'appel à la méthode save() directement. L'utilisation de méthodes dans les models et les managers est recommandée pour les opérations de modification des données.

Par exemple, au lieu de faire:

user = User.objects.get(id=1)
user.blacklisted = True
user.blacklisted_at = timezone.now()
user.save()

On peut faire:

class User(models.Model):
    ...
    def blacklist(self):
        self.blacklisted = True
        self.blacklisted_at = timezone.now()
        self.save()

user = User.objects.get(id=1)
user.blacklist()

Céla permet de centraliser les opérations de modification des données et de les réutiliser dans les vues et les autres modules. ça facilite aussi la validation des données et la gestion des erreurs.

Les méthodes agissant sur une instance concrète doivent être définies dans le modèle. Les méthodes agissant sur un ensemble d'instances doivent être définies dans le manager. Le queryset doit être utilisé pour les opérations de filtrage et de tri.

Les managers et les querysets doivent être définis dans le fichier managers.py du module correspondant.

Documentation Django sur les managers et les querysets: https://docs.djangoproject.com/en/4.2/topics/db/managers/

API

L'API est developpée avec Django-Ninja.

Pour chaque module ayant besoin d'une API, créer un package api dans la racine du module. A l'intérieur de ce module créer les fichiers schemas.py, routers.py et filters.py.

Le fichier schemas.py contiendra les schemas pydantic qui vont servir à la validation et serialization des données. Toujours essayer d'avoir un schema pour la lecture et un schema pour l'écriture. Dans certains cas, il est aussi nécessaire d'avoir un schema pour les updates (par exemple, si on veut avoir des champs réquis différents entre les actions de création et de modification)

Le fichier routers.py contiendra les routes de l'API. Créer un Router ninja pour chaque modèle et ensuite les ajouter au APIRouter du module principal.

Le fichier filters.py contiendra les filtres pour les requêtes de l'API. Le principe "fat models, thin views" doit être respecté, ce qui veut dire qu'il faut éviter à un maximum de mettre de la logique dans les vues.