附言:2017-02-12
实际上,我的项目最近没有使用这种方法。一个宽松的想法是,域层模型和基础结构层实现不一定必须继承,只要它们通过注入链接并且定义了所需的方法(鸭子类型)即可。
- http://qiita.com/ledmonster/items/3b108be6f0967bfe1093
另外,在我最近的项目中,我没有定义基础结构层,而是为端口和适配器定义了模块。对于适配器,这就像编写由域层或端口定义的接口的实现。域模型中的概念放置在域层中,与外部systom的接口放置在端口中。
我有空的时候会写另一篇文章。
概述
将六角体系结构应用于域驱动的开发时,存储库和域事件的接口位于域层中,但是通过使用zope.interface,可以编写易于理解的代码来避免多重继承我会的
域层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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 """ |
基础设施层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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) |
测试
1 2 3 4 5 6 7 8 9 10 | 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) |
域驱动开发系列
- 使用DDD设计时,请考虑使用CQRS
- Python中的ValueObject实现
- Zope.interface对于练习六角结构很有用