资讯动态

DDD(领域驱动设计)篇二:DDD 和三层架构到底差在哪?

发布时间:2026/10/28 2:03:20 来源:尧图企业网站定制
DDD领域驱动设计篇一DDD 到底在解决什么问题1、先摆结构两个架构长什么样你熟悉的三层架构和 mpc 中台我们系统里的中台叫mpc实际的 DDD 分层长这样左边是三层所有活挤在 Service 一层里。右边是 DDD同样一次请求被拆成四层注意业务规则住在领域层锁和缓存这类技术细节被隔离在最底下。看起来只是把 Service 拆成了三块不。关键区别不是层数是业务逻辑搬家了。打个比方三层架构像一家什么都管的便利店一个店员Service 方法同时收银、煮关东煮、盘库存、修打印机。生意小没事生意大了每个店员都得是全能选手换一个店员改需求另三样活都可能被牵连。DDD 像一家正规餐厅应用层是领班——不做饭只安排哪桌的菜、交给哪个厨师领域层是厨师和菜谱——真正的手艺在这里基础设施层是后厨设备——冰箱坏了换设备菜谱不用改。2、拿真代码对比一下三层版patient 模块下单 OrderServiceImpl.java 的createOrder一千六百行大类中的一员简化后Transactional(rollbackFor Exception.class) public OrderSeqVO createOrder(CreateOrderDTO dto) { // 业务校验患者是否满足挂号条件 boolean checkHospitalValid checkHospitalValid(consultationValidDTO); Validator.validateTrue(checkHospitalValid, 就诊人信息不满足条件); // 远程调用查医院特色服务决定走哪条分支 MapString, DictVo specialServiceMap hospitalApi .getHospitalSpecialServerList(dto.getHospitalId()).getData()...; // 业务分支续方购药走这、特色服务走那、在线复诊还要校验号源 if (serverTypeEnum ServerTypeEnum.DOCTOR_CONTINUE_BUY) { ... } // 技术细节分布式锁防重复下单 RLock lock redissonClient.getLock(SysContextHolder.getUserId() createOrder); if (!lock.tryLock(1, 30, TimeUnit.SECONDS)) { GlobalException.throwEx(请勿重复提交订单); } // 再往后号源智能分配、耗时统计、按业务类型决定是否重试…… }数一数一个方法混了五种东西而且变更节奏完全不同成分变更频率举例业务规则月月改、经常改挂号条件、医生号源匹配、新的挂号类型远程调用偶尔改hospitalApi 查特色服务技术细节半年不动Redisson 锁、tryLock 参数流程编排随业务改分支判断、重试统计观测几乎不动StopWatch 耗时统计痛点不在代码烂——每段单拎出来都没毛病。痛点在五种节奏不同的东西拧在一起改任何一个都得通读全文。DDD 版同一工程里 mpc 中台的订单取消OrderBaseSalesRuntimeContext.java应用层就是那个领班Transactional(rollbackFor Exception.class) public ResultCancelOrderDto cancelOrder(CancelOrderParam param) { // 1. 把订单实体从仓库捞出来 OptionalOrderBasedSalesEntity optional orderEntityRepo.findOrder(orderId, orderNo, sourceChannel, externalOrderNo); OrderBasedSalesEntity orderEntity optional.get(); // 2. 加锁交给锁的适配器不自己摸 Redisson return iDomainLockAdapter.logicWithLock(orderEntity.getOrderLockKey(), () - { // 3. 触发取消事件规则由状态机和 Handler 说话 EventModel cancelEvent EventModelFactory.INSTANCE .getEventModel(SalesOrderEventConstants.cancel); cancelEvent.setValueObject(JSONUtil.parseObj(param)); orderEntity.onEvent(cancelEvent); // ← 核心就这一行 return Result.success(new CancelOrderDto()); }); }那什么状态下能取消、取消后干啥去哪了——能不能取消由状态机描述符说了算没注册的状态事件组合框架直接抛异常取消后干什么由 Handler 说了算锁怎么加由 IDomainLockAdapter 说了算领域层连 Redisson 的类都没 import 过。3、逐项对比表维度三层架构DDD业务逻辑住在哪Service 方法里领域对象 状态机 HandlerEntity 的角色数据袋子贫血只有 getter/setter有行为有规则充血如isOrderRefundable()状态流转怎么管每个方法手写 if/setStatus状态机统一声明非法流转自动拦截改一条规则全局搜、多处改、容易漏通常只改一处分布式锁/缓存直接 import Redisson/RedisTemplate适配器隔离领域层不知道 Redis 存在单元测试依赖一堆mock 到手软领域规则不碰中间件纯逻辑好测上手成本低应届生一周上手高概念多需要人带简单接口的代价三个类搞定可能要建实体、描述符、Handler 一套最后两行是 DDD 的真实代价不吹不黑。4、到底什么时候用哪个判断逻辑其实就两问有没有复杂的状态流转规则是不是常变 / 多团队共用决策路径是这样的对应的场景表场景建议配置管理、字典、简单 CRUD三层别折腾复杂查询、报表、导出三层查询为主就该轻快订单/支付/退款这类多状态流转DDD 收益明显规则复杂且常变计费、退费、风控DDD多团队共用的中台/平台DDD 划边界几乎是刚需我们项目就是现成的印证patient 模块面向 C 端单一业务接口虽多但链路相对独立三层够用硬改 DDD 属于过度设计mpc 中台是库存、订单、支付回调、IM 好几个业务方共用一套骨架外部还有京东极速咨询这种多渠道接入描述符里label jd_quickmed_service领域骨架让新业务接入变成声明一个描述符 写几个 Handler。同一个工程、两种架构并存这不是技术债是按业务复杂度选型的正常状态。5、一个容易踩的认知坑很多人以为DDD 把 Service 的代码搬到 Entity 里。不对。搬家只是表象前提是你先想清楚业务的边界和规则——哪些状态、哪些事件、哪些规则属于订单这个地盘。想不清楚就动手结果只是把一锅粥从一个碗倒进另一个碗。这也是为什么 DDD 实践里先和产品对语言、先画状态图比先写代码重要得多。6、思考题翻出你上周写过的最复杂的一个 Service 方法你自己心里有数是哪个做三件事数一数里面混了几类职责业务规则、远程调用、缓存、锁、事务、参数组装……找出其中的状态变更代码改了哪个字段这个字段还有哪些别处也在改问自己如果这个方法只保留业务规则其他都挪走它会变短多少带着答案进入下一篇——把项目里真实的三层订单和DDD 订单放在显微镜下对照。DDD领域驱动设计篇三实战对照——同一个订单业务两种架构怎么写

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑