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,
)