Les services dans enDI

Les services ont vocation à regrouper un ensemble cohérent de fonctionnalités. Ils fournissent les avantages suivant :

1- Facile à tester; 2- En spécifiant les méthodes publiques via des interfaces, on peut avoir des services différents en fonction des objets auxquels ils sont associés.

Plusieurs niveaux :

1- Les services branchés dans un registre à l’aide de pyramid_services seront récupérables depuis une interface et configurable dans le fichier .ini de l’application

2- Les services rattachés directement aux modèles (qui sont essentiellement des moyens de ne pas trop charger le code des modèles)

pyramid_services

https://github.com/mmerickel/pyramid_services

Permet de rendre configurable les services utilisés.

On référence les services dans le fichier endi/__init__.py

ENDI_SERVICE_FACTORIES = (
   (
      "cle_dans_le_fichier_settings",
      "path_vers_l_instance_par_defaut_du_service_sous_forme_de_string",
      "chemin_vers_la_class_de_l_interface_pour_le_service",
   ),
   ...
)

Ensuite on utilise le service configuré

current_service = self.request.find_service(IInterfacePourMonService)
# Si mon service spécifie une méthode "process"
current_service.process(datas)

On trouve des exemples dans la gestion des paiements et dans les exports comptables.

Services rattachés directement aux modèles

Les services rattachés aux modèles permettent de regrouper des méthodes sous une même classe. Si ils sont privés, c’est à dire que seul le modèle y accède, ils sont essentiellement des containers pour limiter le code du modèle.

Si ils sont publics, c’est à dire qu’ils peuvent être utilisés depuis autre part dans le code, ils doivent alors respecter une interface que l’on déclarera.

Service privé

Un service peut être privé, comme les services rattachés au travers l’attribut _endi_service, le modèle va alors forwarder certains appels au service en question.

Exemple dans endi/models/third_party/customer.py

class Customer(DBBASE):
   ...
   @property
   def full_address(self):
       """
       :returns: the customer address formatted in french format
       """
       return self._endi_service.get_address(self)

Services publiques

Un service peut être public, il pourra alors être appelé par du code extérieur au modèle. La nomenclature doit dans ce cas respecter une interface déclarée dans endi/interfaces.py.

Exemple dans endi/events/files.py on accède au file_requirement_service du modèle.

def on_file_change(event):
    if hasattr(event.parent, "file_requirement_service"):
        event.parent.file_requirement_service.register(
            event.parent, event.file_object, action=event.action
        )
        if hasattr(event.parent, "status_service"):
            event.parent.status_service.update_status(
                event.parent,
            )