📦 DDD 里基础工具扩展方法该放哪?Shared 层到底是不是万能垃圾桶?
在做领域驱动设计(DDD)时,一个经常被忽视但极其关键的问题是:
基础工具扩展方法应该放在哪里?Shared 层究竟是工具箱,还是团队常见的“万能垃圾桶”?
这篇文章带你从 DDD 的边界思维出发,把问题讲透。
🧩 Shared 层究竟是什么?
在很多项目里,Shared 往往沦为「放不下的都放这里」的收纳箱。
但在 DDD 中,Shared 的职责非常明确:
Shared 层是跨层复用的技术能力,不包含任何业务逻辑。
典型内容包括:
- ✔ 通用工具方法(Utilities)
- ✔ 基础扩展方法(Extensions)
- ✔ 跨层通用结构(Result、PagedList)
- ✔ 通用异常类型
它的前提是:Shared 必须没有业务味道。
🛠 基础扩展方法能放 Shared 吗?
答案是:
可以,而且非常推荐。
例如:
public static bool IsNullOrEmptySafe(this string value) { ... }
public static long ToUnixTimestamp(this DateTime date) { ... }
public static IEnumerable<T> Batch<T>(this IEnumerable<T> items, int size) { ... }这类扩展方法共同的特征:
- 无业务含义
- 完全通用
- 跨层可复用
- 不依赖实体、值对象或领域服务
这些就应该放 Shared。
🚫 哪些扩展方法不能放 Shared?
以下扩展方法千万别放:
public static decimal CalculateTotal(this Order order)public static bool IsVIP(this User user, IUserRepository repo)public static Price WithTax(this Money money)原因很简单:
- 含有业务规则
- 与领域紧耦合
- 与业务变化存在强关联
业务行为一定属于 Domain,而不是 Shared。
将业务逻辑放进 Shared 会导致依赖倒置、耦合扩大,最终系统结构崩塌。
🎯 一句话判断模型
为了帮助团队快速判断,我总结了一条非常有效的规则:
通用工具 → Shared 业务逻辑 → Domain
只要和业务挂钩,就不应该放到 Shared。
只要和业务无关,就不应该放到 Domain。
一句话解决 80% 的分层争议。
🧱 推荐的项目结构
src
├─ Domain
│ ├─ Entities
│ ├─ ValueObjects
│ └─ DomainServices
├─ Application
├─ Infrastructure
├─ Shared
│ ├─ Extensions
│ ├─ Common
│ └─ ResultsShared 简洁、Domain 聚焦业务、Application 与 Infrastructure 依赖清晰。
这才是一个健康的 DDD 项目的形态。
🚀 总结
- 基础扩展方法放 Shared:✔
- 业务扩展方法必须放 Domain:✔
- Shared 不是垃圾桶,而是工具箱
- Domain 是业务核心,不能被 Shared 反向侵蚀
只要坚持这条边界原则,你的项目架构会越来越干净,也更容易维护。
✨ 结尾
我是 李勇|MUZINET 技术博客 记录架构思考、分享 .NET / DDD / Aspire 的实践经验。
欢迎交流,让我们一起构建更优雅的软件系统。
最后更新于