ddd分层感想

在传统的三层中,大家比较熟悉的更多是petshop的分层形式。
在其中使用Dao模式分离数据库,使用了Abstract Factory模式提供反射创建Dao中的持久实例。
很多人首次对ms在demo中使用设计模式感到欣慰,以为是ms看到.net方面要提高下设计模式的
能力。我想其中有一些这样的原因。是个人都知道,ms做什么都想入门简单。如果真的能解决那个问题
ms还愿意用Abstract Factory模式吗?这个问题就是循环依赖。ORM能解决。但是Abstract Factory相比ORM来说
还是AF简单的多了。然而许多人还美其名曰“依赖注入”,其实它那是没办法.如果不想循环依赖,那就不能在dao中使用model中的实体。
在大中型项目中,这样的做dao可以想象是场灾难。

下面唠叨下DDD中的分层

Infrastructure(最底层) 为上层提供通用的技术能力。
Domain在Infrastructure的上一层。
按照分层的基本原则:某一层中的所有元素只能依赖于同一层的其他元素或依赖其所有比它底的下层元素(Relaxed Layered Stystem)(Buschmann et al,1996)。
也就是说Domain可以引用Infrastructure,而Infrastructure不能引用Domain,这样就导致前面的问题
领域实体到了Infrastructure就被打散成基本元素(这里没有使用ORM)。Infrastructure跟其他层也是同样的
问题。数据的封装到了Infrastructure中显得那么别扭。ddd的分层可能出现了问题。应该不是,在ddd全书中
都是使用ORM做底层,所以很少出现这样的情况。也就是说我们始终需要一个Meta Mapping Layer(元数据映射层)。

在Jimmy Nilsson的Applying Domain-Driven Design and Patterns: With Examples in C# and .NET这本书中
也讨论了这个问题。不过简单提了下。
I think there are few things to note regarding how I use layering now compared to my old style. First of all, the Application layer isn't mandatory; it is only there if it really adds value. Since my Domain layer is so much richer than before, it's often not interesting with the Application layer.
Another difference is that instead of all calls going down, the Infrastructure layer might "know" about the Domain layer and might create instances there when reconstituting from persistence. The point is that the Domain Model should be oblivious of the infrastructure.

且看Jimmy Nilsson把ddd分层改为

这样的改变,我认为不妥。图中为了不造成循环依赖,可以使用Abstract Factory提供反射创建Infrastructure中的持久实例。尽管这样能做到,但是却明显违反分层的基本原则。

今天(2008-7-11),在看houghtWork公司写的《Pragmatic.Bookshelf.The.ThoughtWorks.Anthology》书的时候,惊奇的发现,Erik也在讨论这个问题,不过里面只是简单的提了下,如下:
Erik considers a similar problem. In a well-designed system,
you decouple the domain model from infrastructure layers, but this
requires that the infrastructure layer use the metadata present in the
domain model. Some implicit metadata can be gleaned from what’s in
there such as the choice of classes to represent certain domain elements,
but it doesn’t really provide enough information for really rich
stuff like validations. Some modern languages such as Java and C#
provide for more metadata in the form annotations and attributes, and
Erik explores how to exploit these features through a case study.

这个问题,不仅仅只在infrastructure 和Domain之间存在,而是在层之间都存在。
因为分层的原则,所有设计的依赖就必须是单向的,如果下层要调用上层的对象,问题就出现了。
在ddd书中也提到了,使用回调或Observer模式可以解决。
如果不使用MVC,在infrastructure 和Domain之间也许只能提供Meta Mapping Layer才能解决问题。

总结说明下,我认为ddd中的分层没有问题。只是传统的dao要使用ddd不方便罢了。

转载于:https://www.cnblogs.com/bmrxntfj/archive/2008/07/08/1237968.html

<think>好的,我现在需要回答用户关于DDD分层架构的设计方法、原则和最佳实践的问题。首先,我得回顾一下DDD的基本概念和分层架构的结构。 根据用户提供的引用内容,DDD分层架构包括四层:用户接口层、应用层、领域层和基础层。我需要详细解释每一层的职责和它们之间的关系。传统三层架构和DDD分层架构的区别可能是一个关键点,需要对比说明,以突出DDD的优势,比如高内聚低耦合。 接下来是设计原则。用户提到的引用中强调了依赖倒置原则,尤其是基础层如何通过接口解耦其他层的依赖。这里需要解释依赖倒置在DDD中的具体应用,比如领域层定义仓储接口,基础层实现这些接口,这样应用层和领域层不直接依赖具体的数据访问技术。 然后是最佳实践部分。引用3提到基础设施层作为数据的出向接口,使用依赖倒置,其他层只依赖接口。这部分需要详细说明结构模型,比如各层的代码模块划分。另外,引用4提到领域服务如何组装实体和仓储服务,应用层调用仓储服务,这需要具体说明各层之间的调用流程,避免逻辑泄露到应用层。 可能还需要考虑如何保持各层的边界清晰,避免层与层之间的职责混淆。例如,应用层负责协调任务和事务,但不处理业务逻辑,而领域层专注于核心业务规则。此外,基础层如何封装技术细节,如数据库、消息队列等,确保领域层不受基础设施变化的影响。 用户的问题还涉及设计方法和原则,因此需要整理出明确的列表,比如分层原则、依赖方向、领域模型核心地位等。同时,结合引用中的例子,如仓储接口的实现,具体说明如何应用这些原则。 最后,生成的相关问题需要与DDD分层架构相关,可能涉及与传统架构的对比、具体实施步骤、常见问题等。确保问题有针对性,能够帮助用户进一步理解。 现在需要组织这些信息,以清晰的结构呈现,确保每个部分都有引用支持,并正确标注引用来源。同时,检查是否符合用户的要求,如使用中文、LaTeX格式正确,特别是行内公式和独立公式的使用,虽然当前问题可能不涉及数学公式,但需要留意是否有相关内容需要处理。</think>### DDD分层架构设计方法与最佳实践 #### 一、分层架构设计 DDD分层架构包含**四层**,从上至下依次为: 1. **用户接口层** 负责与外部系统交互(如Web请求、RPC调用),处理输入参数校验与返回结果格式化。不包含业务逻辑,仅作为入口[^1][^2]。 2. **应用层** 协调领域对象完成业务用例,负责事务管理、权限校验等跨领域逻辑。例如调用领域服务组合多个实体操作[^4]。 3. **领域层** 核心业务逻辑所在层,包含**实体**、**值对象**、**领域服务**和**领域事件**。例如:订单实体的状态变更规则、库存扣减领域服务。 4. **基础层** 提供技术实现支持,如数据库访问(仓储实现)、消息队列、缓存等。通过**依赖倒置**原则向上提供接口,例如:领域层定义仓储接口,基础层实现具体数据库操作[^3]。 #### 二、核心设计原则 1. **分层职责隔离** - 用户接口层与应用层关注流程,领域层专注业务规则,基础层处理技术细节。 - 示例:支付业务中,领域层实现扣款计算,基础层处理银行API调用。 2. **依赖方向控制** - 依赖关系自上而下:用户接口层→应用层→领域层→基础层接口。 - 基础层具体实现通过依赖倒置被上层调用,例如: ```java // 领域层定义接口 interface OrderRepository { Order findById(String id); } // 基础层实现 class JpaOrderRepository implements OrderRepository {/*...*/} ``` 3. **领域模型为核心** - 所有分层围绕领域模型展开,避免业务逻辑泄露到应用层或基础层。 #### 三、最佳实践 1. **代码结构示例** ``` ├── application # 应用服务 ├── domain # 领域模型 │ ├── model # 实体/值对象 │ ├── service # 领域服务 │ └── repository # 仓储接口 └── infrastructure # 基础实现 └── repository # 仓储JPA实现 ``` 2. **关键实施要点** - **防腐层设计**:在用户接口层与外部系统间建立适配层,防止外部模型污染领域模型。 - **领域事件驱动**:通过事件解耦跨领域操作,例如订单创建后发布`OrderCreatedEvent`触发库存更新。 - **聚合根设计**:通过聚合根保证领域内一致性,如订单聚合根控制订单项修改。 3. **与传统三层架构对比** | 对比维度 | DDD分层架构 | 传统三层架构 | |----------------|--------------------------|---------------------| | 核心关注点 | 领域模型驱动业务 | 数据流转 | | 技术依赖 | 基础层隔离技术细节 | 常与数据库强耦合 | | 可维护性 | 业务变化时修改领域层即可 | 需跨数据/逻辑层修改 | #### 四、典型问题场景 1. **复杂业务规则处理** 将规则封装为领域服务,例如: ```java class DiscountService { public Money calculate(Order order) { // 实现满减、会员折扣等组合规则 } } ``` 2. **数据持久化优化** 在仓储实现中使用懒加载或JPA的`@EntityGraph`优化查询,避免领域层感知技术细节[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值