不同观点:DTOs与领域对象

.NET 开发中的统一实体模型问题

自 NHibernate 和 WCF 引入以来,.NET 开发者逐渐接近统一实体模型的概念。其最终目标是同一个类可以同时作为 ORM 实体、WCF DTO 以及 MVC、MVP 或 MVVM 框架的模型。然而,《.NET 依赖注入》的作者 Mark Seemann 认为这并不一定是好事。

Mark Seemann 的主要观点

Mark Seemann 的核心论点是:“在边界处,应用程序并不是面向对象的”。他指出,大多数序列化技术要求公共的默认构造函数和可写属性,这迫使设计 DTO 时打破封装和数据隐藏的原则。甚至无法强制执行字段非空/非空等基本不变性,因为 DTO 可以省略任何内容。

他进一步阐述了两个原则:

  1. 服务共享模式和契约,而不是类。
  2. DTO 不会破坏封装,因为它们根本不是对象。

解决方案的三种选择

针对这种情况,Mark 提出了三种解决方案:

  1. 坚持现有方法:通过开发翻译层将 DTO 转换为适当封装的领域对象。这是他在书中示例中采用的方法,但逐渐认为这可能不是最佳方案,因为存在可维护性问题。
  2. 将数据视为结构化数据:停止将数据视为对象,而是将其视为真正的结构化数据。Mark 认为,如果编程语言有独立的结构化数据概念会更好。他指出,C# 没有这样的概念,但 F# 提供了许多方法来建模没有行为的数据结构,这可能是处理数据的更诚实的方法。
  3. 使用动态类型:在 Dino Esposito 的文章《Cutting Edge: Expando Objects in C# 4.0》中,概述了一种动态处理结构化数据的方法,绕过自动生成的代码,提供轻量级的 API。这种方法看起来也很有前途,虽然不提供编译时反馈,但这只是一种虚假的安全感。我们必须依靠单元测试来获得快速反馈。

相关资源

如果你对面向对象设计和封装感兴趣,不要错过 Mark Seemann 的系列文章《Poka-yoke Design: From Smell to Fragrance》。

阅读 10
0 条评论