Le modèle d'acteur

Fil rouge

Gestion des documents

Objectifs

  • Créer des documents
  • Gérer les versions des documents
  • Gérer les accès des documents
  • Gérer la validation des documents

Gestion des documents

Étape 1 :

Le processus de validation des documents

Étape 1

Gestion des documents

Étape 2 :

Comment peut-on modéliser ce fonctionnement ?

Étape 2 :

Version 1 : Par module

Étape 2 :

Version 2 : Par couche

Étape 2 :

Version 3 : Par fonction

Étape 2 :

Version 4 : Par acteur

Gestion des documents

Étape 3 :

Et la technique dans tout ça ?

Étape 3

L'étape précédente permet de concevoir d'un point de vue fonctionnel le problème, mais comment peut-on le développer ?

 

La conception se concentrera ici sur l'organisation des acteurs

Étape 3

Version 1 : Par les fonctions

Avantages

  • Très facile de savoir ce que peut faire chaque acteur
  • Représente souvent l'organisation de l'entreprise

Inconvénients

  • Si l'application grossit, il sera difficile de maintenir le système avec des acteurs « atomiques »
  • Si un utilisateur a plusieurs rôles, comment combiner les modèles d'acteurs ?
  • Peu adapté à un fonctionnement requête client/serveur (l'acteur n'existe que durant la requête ?)

Étape 3

Version 1 : Par les fonctions

Étape 3

Version 2 : Par les services

Avantages

  • Approche plus classique permettant un passage progressif sur ce modèle

Inconvénients

  • Risques de retomber dans les pièges de la conception classique
  • Gestion des autorisations ?
  • Risques de blocage inutile du système

Étape 3

Version 2 : Par les services

Étape 3

Version 3 : Par les données

Avantages

  • Très facile de comprendre la modélisation des données
  • Gestion des contraintes sur les données aisée
  • Gestion des états des données simplifiée

Inconvénients

  • Difficile de visualiser les opérations de chacun des utilisateurs
  • Gestion des autorisations ?

Étape 3

Version 3 : Par les données

Avis personnel : Conception recommandée pour débuter

Étape 3

Le mieux, c'est de mixer

le tout selon les besoins

Gestion des documents

Étape 4 :

Système de workflow : Les FSM

Étape 4

Étape 4

// How this code is usually written with classic services?
class documentService {
  create(document) {
    // persist document
  }

  update(id, newDocument) {
    const document = this._find(id);
    if (!document.isValidating && !document.isBroadcasted) {
      // persist newDocument
    }
  }

  validate(id) {
    const document = this._find(id);
    if (!document.isValidating && !document.isBroadcasted) {
      document.isValidating = true;
      // persist document
    }
  }

  accept(id) {
    const document = this._find(id);
    if (document.isValidating && !document.isBroadcasted) {
      document.isBroadcasted = true;
      // persist
    }
  }

  refuse(id) {
    const document = this._find(id);
    if (document.isValidating && !document.isBroadcasted) {
      document.isValidating = false;
      // persist
    }
  }

  read(id) {
    const document = this._find(id);
    if (document.isBroadcasted) {
      return document;
    }
  }

  delete(id) {
    const document = this._find(id);
    if (document.isBroadcasted) {
      // remove document
    }
  }

  _find(id) {/*…*/}
}

Étape 4

// How this code should be written?
// Use of my personal FSM library (https://github.com/kneelnrise/fms-js)
function getFSM(id) {
  const fsm = k.fsm.create((fsm) => {
    fsm.when("draft", (state) => {
      state.on("update", (data, newDocument) => {
        return ["draft", newDocument];
      });
      state.on("validate", (data) => {
        return ["validating", data];
      });
    });
 
    fsm.when("validating", (state) => {
      state.on("accept", (data) => {
        return ["broadcast", data];
      });
      state.on("refuse", (data) => {
        return ["draft", data];
      });
    });
  
    fsm.when("broadcast", (state) => {
      state.on("read", (data) => {
        return ["broadcast", data];
      });
    });
  
    // Currently, this function does not exist in the library, but keep the logic in mind
    fsm.afterEachEvent((data, state) => {
      db.persist({data: data, state: state});
    });
  
    // We initialize our FSM from saved item
    const saved = db.find(id);
    fsm.startWith(saved.state, saved.data);
  });
}

Avantages

  • Plus grande maîtrise des états de la données
  • Conception et code proche
  • Facilité de maintenance

Inconvénients

  • La donnée doit vivre pour pouvoir utiliser ce design pattern (inadapté aux requêtes client/serveur basiques)

Étape 4

Gestion des documents

Étape 5 :

Communication entre les acteurs

Étape 5

Organisation des acteurs

Étape 5

Messages échangés

Étape 5

Comment contacter l'acteur

  • Boite à lettres
  • Adresse logique de l'acteur
  • Adresse physique de l'acteur
  • => Répartition sur plusieurs serveurs

Gestion des documents

Étape 6 :

Une opération à la fois

Étape 6

Cas d'étude

  1. Nom de document unique
  2. Transaction (traitements) longue avant la diffusion
    • La transaction peut échouer en raison de contraintes métiers
    • La transaction dure entre 1s et 10s

Étape 6

Cas 1 : Nom de document unique

Quel serait votre code ?

 

  • Contraintes pour ce cas :
    • Le SGBD n'a aucune notion de transaction
    • Le SGBD n'a aucune notion de contraintes sur les données (ex : colonne UNIQUE)

Java / JEE

Étape 6

Cas 1 : Nom de document unique

Javascript / ES-2015

@Local
class DocumentService {
  @PersistentContext
  private EntityManager em;

  public void create(Document document) {
    List<Document> existing = em.createQuery(
      "SELECT d FROM Document d WHERE d.name = :name",
      Document.class
    )
      .setParameter("name", document.getName())
      .getResultList();
    
    if (existing.size() > 0) {
      em.persist(document);
    }
  }
}
// global db

class DocumentService {
  create(document) {
    db.find({name: document.name}).then((existing) => {
      if (!existing) {
        em.persist(document);
      }
    });
  }
}

Étape 6

Cas 1 : Nom de document unique

Problème :

Ce code fonctionne, mais dans le cas ou deux documents sont insérés en base en même temps ?

 

  1. Vérification 1 : Le document n'existe pas
  2. Vérification 2 : Le document n'existe pas
  3. Insertion 1 : Le document n'existe pas
  4. Insertion 2 : Le document existe…

 

Le problème survient dès qu'il y a parallélisme, réparti sur un ou plusieurs serveur(s).

Étape 6

Cas 1 : Nom de document unique

Solution :

 

Ne réaliser qu'une seule opération d'insertion à la fois.

Bloquer les autres tant qu'elle n'est pas terminée.

 

Attention à ne pas bloquer le système !

 

Remarque : Cette gestion devrait être gérée par le framework ou langage, pas par le développeur

Étape 6

Cas 2 : Transaction longue avant la diffusion

  • Rappel des contraintes :
    • La transaction peut échouer en raison de contraintes métiers
    • La transaction dure entre 1s et 10s

 

Pour ce cas, nous pouvons avoir un SGBD avec la notion de transaction (ex: Oracle).

Étape 6

Cas 2 : Transaction longue avant la diffusion

  • Transaction SGBD :
    • Risque de bloquer une table entière pour ne traiter qu'un document
  • Modifier le document et revenir sur la version précédente en cas d'échec ?
    • Risques que les autres opérations impacte le document en cours ?

Étape 6

Cas 2 : Transaction longue avant la diffusion

Solution :

 

Chaque document est un acteur : Une seule opération à la fois par document (on ne bloque qu'un document)

 

Correct du point de vue métier : Deux utilisateurs ne devraient pas modifier le même document à la fois

 

Remarque : pour la persistence, se renseigner sur la notion de « insert only » (CR).

Gestion des documents

Étape 7 :

Supervision

Étape 7

Let it crash!

 

Fait inéluctable : L'application va crasher

 

Comment faire pour que notre application continue de répondre, même quand elle crash ?

Avantages

  • Si un serveur tombe, un autre prend le relais

Inconvénients

  • Gestion des erreurs dues aux ressources (DB, API externe) ?
  • Comment redémarrer le serveur ?
  • Gestion des requêtes en cours ?
  • Parallélisme des tâches (Cf. étape 6)

Étape 7

Solution 1 : Duplication

Étape 7

Solution 2 : Supervision

La supervision consiste à déléguer les cas que notre acteur ne sait pas gérer à son supérieur.

  • Gestion des erreurs
  • Gestion des exceptions
  • Gestion des crashes

 

Un supérieur racine : Se doit de maintenir le système en vie !

Avantages

  • Centralisation des erreurs
  • Le supérieur a un aperçu global de ses subordonnés :
    • Recul
    • Peut choisir la meilleure stratégie selon le contexte
  • Avantages du système d'acteurs gardés

Inconvénients

  • Plus difficile à réaliser
    • Définir la/les stratégie(s)
    • Les implémenter

Étape 7

Solution 2 : Supervision

Gestion des documents

Étape 8 :

Distributivité

Étape 8

Rappels

  • Les acteurs sont atomiques
    • Indépenance directe des autres acteurs
  • Les acteurs communiquent par message
    • Adresse logique
  • Les acteurs sont supervisés par un autre acteur
    • Avec le même système de communication

Conclusion

Le modèle même est par nature distribuable !

Gestion des documents

Conclusion

Avantages

  • Isolation des composants
  • Gestion de la concurrence
  • Capacité d'auto-guérison
  • Faible couplage
  • Distributivité
  • Parfait pour les DevOps
  • Utilisé par des gros acteurs comme Twitter
  • Akka, framework basé sur ce modèle, en scala, java et C#
  • Erlang, language basé sur ce modèle.

Inconvénients

  • Peu de langages et frameworks
  • Assez opposé aux conceptions apprises dans les centres de formation
  • Très bas niveau
  • Non adaptés aux développements UI

Conclusion

Conclusion

Webographie

Le modèle d'acteur

By Gaëtan Rizio

Le modèle d'acteur

Ce diaporama permet de présenter le modèle d'acteur en partant des conceptions classiques.

  • 480