Modularisation !

Presenter Notes

Croissance du projet

$ git tag --list
autoslave-0.0.8-1
autoslave-0.0.8-2
autoslave-0.0.9-1
...
autoslave-1.49.2
autoslave-1.49.3
autoslave-1.49.4

$ git tag --list | wc -l
216

$ git log --oneline | wc -l
29923

Presenter Notes

Démultiplication des fonctionnalités

>>> len(settings.INSTALLED_APPS)
168
>>> len(models.get_models())
341
models-extract.png

Presenter Notes

Problèmes

  • Maintenance
  • Interdépendances
  • Lenteur des tests
  • Évolutivité
slow-build.png

Presenter Notes

Mais aussi...

  • Nouveaux clients
    • "On ouvre une nouvelle ville, ça devrait être facile, non ?"
    • "Je peux avoir le même, mais pour une flotte d'entreprise ?"
  • Nouveaux projets
    • "On peut reprendre juste le centre d'appel ?"
    • "Et pour superviser des soucoupes volantes ?"

Presenter Notes

La solution ?

Presenter Notes

Modulariser !

chainsaw.jpg

Presenter Notes

Le premier module

  • Utilitaires
    • Géocodage
    • Wrappers
    • Field personnalisés
  • Fonctionnalités standard
    • Authentification
    • Mise en page
    • Contrôle d'accès
    • Auto-test

Presenter Notes

Automatiser

  • Tests unitaires (mais on a l'habitude)
  • Packaging propre
    • setup.py
    • python setup.py sdist [upload]
    • Attention au Manifest.in !
  • Brancher
  • Corriger, re-livrer, re-brancher

Presenter Notes

Isoler les modules

  • Les cas évidents :
    • Périmètre fonctionnel clair
    • Réutilisable
    • Peu couplé
  • Mais aussi :
    • Agréger une fonctionnalité sur plusieurs environnements
    • Prévoir un service réutilisable

Presenter Notes

Stratégies

Plusieurs modules, une seule BDD

✔ Plus simple à administrer et déployer

✔ Plus facile à migrer

✘ Mutualisation de fonctionnalités complexe

✘ Couplage fort

Presenter Notes

Stratégies

Modules autonomes, requêtes uniquement pour l'écriture

✔ Facile à mutualiser

✔ Plannig de déploiement autonome

✔ Simple conceptuellement

✔ Résistance aux pannes

✘ Duplication des données

✘ Désynchronisation des données

Presenter Notes

Stratégies

Modules autonomes, requêtes pour lecture/écriture

✔ Facile à mutualiser

✔ Plannig de déploiement autonome

✔ Pas de duplication

✘ Forte charge sur l'infrastructure

✘ Pannes en cascades

Presenter Notes

Préparation

Utiliser des backends

def load_backend(name):
    modname, classname = name.rsplit('.', 1)
    mod = import_module(modname)
    backend_class = getattr(mod, classname)
    return backend_class()
def doit(x, y, z):
    backend = load_backend(settings.MY_BACKEND_NAME)
    return backend.doit(x, y, z)

Presenter Notes

Interlude : backends

  • Plus de flexibilité
  • Simplifient les tests
    • Émuler aisément les comportements de briques externes
    • Simuler une panne
  • Explicitent les interfaces
    • Attention aux types d'objets passés et reçus !

Presenter Notes

Préparer

  • Isoler les chemins pour création et mise à jour

    MY_CREATION_BACKEND = 'mymod.backends.multi'
    MY_UPDATE_BACKEND = 'mymod.backends.legacy'
    
  • Prévoir 3 versions des backends :

    • Ancienne version
    • Nouvelle version
    • Les deux à la fois (écriture sur les deux, lecture sur l'ancien)

Presenter Notes

Le grand saut

  1. Copier les données existantes
  2. Basculer la création sur le backend multi-versions
  3. Copier les données créées depuis l'étape 1
  4. Basculer la mise à jour sur le backend multi-versions
  5. Synchroniser les changements depuis l'étape 1
  6. Passer création et modification sur les backends "nouveau module"

Presenter Notes

Résumé

autoslave-flux-multiparc-small.png multiparc-flux-macro-small.png

Presenter Notes

Questions ?

Presenter Notes