聊聊 DDD 在小团队的落地:别被教科书吓跑了

Applying DDD in Small Teams: Don't Let Textbooks Scare You Away

| Alex | 2026-08-28T19:17:08

DDD 的书看了好几本,但总觉得太理论了。这篇文章聊聊我们小团队怎么「务实地」用 DDD 的思想来组织代码。

DDD books are too theoretical for small teams. Here's how we pragmatically apply DDD concepts to organize code.

DDD(领域驱动设计)相关的书和文章我看了不少,但说实话每次看完都觉得"道理我都懂,但我们这个 5 人小团队真用不上这么重的东西"。后来想通了一件事:DDD 的思想是好的,但不一定要照搬教科书的做法。 我们怎么"轻量级 DDD" 1. 按领域而不是按层组织代码 传统的分层架构是这样的: src/ ├── controller/ │ ├── UserController.java │ ├── OrderController.java │ └── ProductController.java ├── service/ │ ├── UserService.java │ ├── OrderService.java │ └── ProductService.java └── dao/ ├── UserDao.java ├── OrderDao.java └── ProductDao.java 我们改成了按领域组织: src/ ├── module/ │ ├── user/ │ │ ├── UserController.java │ │ ├── UserService.java │ │ └── UserMapper.java │ ├── order/ │ │ ├── OrderController.java │ │ ├── OrderService.java │ │ └── OrderMapper.java │ └── product/ │ ├── ProductController.java │ ├── ProductService.java │ └── ProductMapper.java 好处是显而易见的:改一个功能的时候,相关的文件都在同一个目录下,不用在 controller、service、dao 三个目录之间跳来跳去。 2. 用值对象代替原始类型 这个改动很小但是收益很大。比如金额相关的计算,之前到处都是 BigDecimal,很容易搞混人民币和美元: // Before: 很容易搞混 BigDecimal price = calculatePrice(); BigDecimal discount = calculateDiscount(); BigDecimal total = price.subtract(discount); // 这两个是同一种货币吗? // After: 用值对象包装 Money price = Money.of(100, Currency.CNY); Money discount = Money.of(10, Currency.CNY); Money total = price.subtract(discount); // 编译时就能检查货币一致性 3. 领域事件解耦 模块之间的通信用领域事件而不是直接调用。比如用户下单之后要扣库存、发通知、记积分,不要在 OrderService 里直接调用 StockService、NotifyService、PointService,而是发一个 OrderCreatedEvent,各个模块自己监听处理。 不用的部分 我们没有用 CQRS、Event Sourcing、聚合根边界这些"重型"概念。不是说它们不好,而是在我们这个规模下收益不明显,引入反而增加了理解成本。 总结 DDD 的核心是"让代码反映业务",这个思想在任何规模的团队都适用。但具体的实践方式要根据团队规模和业务复杂度来选择,不要教条主义。


DDD concepts are valuable but textbook implementations are too heavy for small teams. Here's our pragmatic approach. What We Use Organize code by domain module instead of by layer Value objects instead of primitive types (e.g., Money class for currency safety) Domain events for inter-module communication instead of direct calls What We Skip CQRS, Event Sourcing, aggregate root boundaries - not worth the complexity at our scale. DDD's core is "make code reflect business" - applicable at any scale, but implementation should match team size.

← Back to News