Zope.interface est utile pour pratiquer l'architecture hexagonale

Post-scriptum: 12/02/2017

En fait, mon projet n'a pas utilisé cette méthode ces derniers temps. C'est une idée vague que le modèle de la couche de domaine et l'implémentation de la couche d'infrastructure ne doivent pas nécessairement être hérités tant qu'ils sont liés par injection et que les méthodes nécessaires sont définies (typage canard).

Aussi, dans mon récent projet, au lieu de mettre la couche infrastructure, j'ai défini les modules de port et d'adaptateur. Pour l'adaptateur, c'est comme écrire une implémentation d'une interface définie au niveau de la couche de domaine ou du port. Le concept dans le modèle de domaine est placé dans la couche de domaine et l'interface de coopération avec le système externe est placée dans le port.

J'écrirai un autre article quand j'aurai le temps.

Aperçu

Lorsque Hexagonal Architecture est appliqué au développement piloté par domaine, l'interface pour les référentiels et les événements de domaine est placée dans la couche de domaine, mais [zope.interface](http: //: // En utilisant docs.zope.org/zope.interface/), vous pouvez écrire un code facile à comprendre qui évite l'héritage multiple.

Couche de domaine

from abc import ABCMeta
from zope.interface import Interface


class Entity(object):
    """ Base class for Entity """
    __metaclass__ = ABCMeta


class IRepository(Interface):
    """ Interafce for Repository """


class IDomainService(Interface):
    """ Interface for Domain Service """


class Blog(Entity):
    def __init__(self, identity, title):
        self._identity = identity
        self._title = title


class IBlogRepository(IRepository):
    """ Blog repository Interface """

    def add_entity(blog):
        """ add blog """

    def get_by(identity):
        """ get blog by identity """


class IBlogProvisioningService(IDomainService):
    """ Blog provisioning service interface """

    def provision_blog(title):
        """ provision blog with title. returns Blog object """

Couche d'infrastructure

import uuid
from abc import ABCMeta
from zope.interface import implementer
from domain import Blog, IBlogRepository, IBlogProvisioningService


class MySQLRepository(object):
    """ MySQL based repository """
    __metaclass__ = ABCMeta


class MemoryRepository(object):
    """ memory based repository """
    __metaclass__ = ABCMeta


@implementer(IBlogRepository)
class BlogRepository(MySQLRepository):

    def add_entity(self, blog):
        # do some stuff
        pass

    def get_by(self, identity):
        # do some stuff
        return Blog(identity, "some stored title")


@implementer(IBlogRepository)
class BlogMemoryRepository(MemoryRepository):

    def add_entity(self, blog):
        # do some stuff
        pass

    def get_by(self, identity):
        # do some stuff
        return Blog(identity, "some stored title")


@implementer(IBlogProvisioningService)
class BlogProvisioningService(object):

    def __init__(self, repo):
        self._repo = repo

    def provision_blog(self, title):
        entity = Blog(uuid.uuid4().hex, title)
        self._repo.add_entity(entity)

tester

import pytest
from zope.interface.verify import verifyClass
from domain import Blog, IBlogRepository, IBlogProvisioningService
from infra import BlogRepository, BlogMemoryRepository, BlogProvisioningService


def test_class_interface():
    assert verifyClass(IBlogRepository, BlogRepository)
    assert verifyClass(IBlogRepository, BlogMemoryRepository)
    assert verifyClass(IBlogProvisioningService, BlogProvisioningService)

Série de développement piloté par domaine

Recommended Posts

Zope.interface est utile pour pratiquer l'architecture hexagonale
python-dotfiles est pratique pour gérer les dotfiles
Watchdog est très utile pour la surveillance des fichiers
Une scène où le GPU est utile pour le deep learning?
À quoi sert Linux?