与领域驱动设计的协同增效
由于概念简单、易于掌握,端口和适配器架构很适合作为DDD的入门辅导工具,而领域驱动设计的诸多方法也能够补充端口和适配器架构的空白,形成合力。
端口和适配器架构与领域驱动设计的协同增效
校验“通用语言”
通用语言是领域驱动设计的核心精髓,它建议各方(无论是领域专家和还是开发人员)对于同一件事都使用相同的词汇。这可以防止各方在沟通领域问题、制定解决方案时不会由于不同的专业背景产生误解,最终促进了识别正确的问题,采用正确的解决方案。甚至有激进的观点认为“领域模型就是通用语言本身”。
端口和适配器虽然不能直接帮助我们找到领域模型或通用语言,但它有助于我们从通用语言中快速剔除技术概念:凡是用于实现适配器的技术细节都应该被排除。让我们回到DDD Cruise的例子:
对话片段,注意绿色字体都和Driven Adapter有关,它们应该被通用语言排除。
作为“DDD战术设计”的脚手架
领域驱动设计于2004年横空出世,一年后端口和适配器被提出,在战术设计层面,我们可以发现诸多相似点,互为呼应。以架构为例,DDD原著中提出的架构很有意思:乍看之下,以为是传统的分层架构,但却强调了Infrastructure对各层的实现。
如果我们做一下职责分析,你会发现这不就是端口和适配器嘛?
端口和适配器的优势是突出了分层不是重点,技术实现隔离才是关键,让你不再纠结是否允许组件跨层调用。而DDD原著架构的优势是用Application和Domain进一步澄清了业务逻辑这个模糊的概念。不妨合二为一:
值得一提的是,Application和Domain甚至可以是声明式的,作为端口存在,例如DDD构建块中的ApplicationService是一个典型的入口端口,而Repository则是一个典型的出口端口。
让我们回到DDD Cruise,细化Cruise的领域模型:CruiseSearch(应用服务),但实际的筛选逻辑会交给Cruise(实体)及其值对象Itinerary,Leg实现,你甚至可以引入DDD书中提到的规格模式,进一步强化单一职责,将筛选条件与领域模型筛选方法的映射工作从InMemoryCruiseSearch中剥离,使其完全只负责步骤协调。
将应用服务、领域模型代入Cruise Search