In fact, my project hasn't used this method lately. It is a loose idea that the domain layer model and the infrastructure layer implementation do not necessarily have to be inherited as long as they are linked by inject and the required methods are defined (duck typing).
Also, in my recent project, instead of putting the infrastructure layer, I have defined modules for port and adapter. For adapter, it's like writing an implementation of an interface defined by a domain layer or port. The concept in the domain model is placed in the domain layer, and the interface with the external systom is placed in the port.
I will write another article when I have time.
If you apply Hexagonal Architecture to Domain Driven Development, you will put the interface for repositories and domain events at the domain layer, but [zope.interface](http: //: // By leveraging docs.zope.org/zope.interface/), you can write easy-to-understand code that avoids multiple inheritance.
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 """
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)
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)