清洁建筑中的实体是否应该了解持久性机制?

uni*_*ptr 5 architecture design-patterns unit-of-work clean-architecture

在《清洁建筑》(Robert C. Martin)一书中。191,他指出“实体是纯粹的业务逻辑,别无其他”。我不确定我应该如何从持久性机制的实体知识方面解释这一说法。

我假设实体对象是有状态的-它们操纵了它们代表的业务数据。如果是这样,则必须通知持久层该数据的更改,以便它可以保留这些更改。因此; 实体是否可以保留对持久性接口(或工作单元接口,如果设计更为精细的话)的引用?

我倾向于认为,拥有这样一个引用(并从实体内部调用)的实体对象将不是“纯业务规则”。但我有一种感觉,只要实体持有对接口的引用,它就不算数吗?

而且,如果实体不应保留对持久性机制的引用,那么是否存在其他用于持久化业务数据更改的良好模式?

Ped*_*oes 4

关于这个问题有两个主要思路。两者都代表了不同的设计模式。这两个选项还认为您正在处理有状态实体,这些实体对业务场景的各个方面进行建模,从这个意义上说,它们知道将被持久化的“数据”,但是,它们不一定知道持久化机制本身。

现在,关于持久性机制,第一种方法可能是旧 J2EE 或 Rails 从业者最熟悉的方法,其中实体完全意识到它将被加载/保存到底层持久性中,并且其接口将传达以下方法: “获取”、“插入”、“更新”。这就是所谓的“活动记录”(Martin Fowler,企业应用程序架构模式)模式。也就是说,实体在对业务的某个方面进行建模时,它也将代表数据库中的直接记录,并且能够保存/加载自身。

另一种方法更符合您提到的“清洁架构”,一些作者将其称为“数据映射器”(也是 Martin Fowler,企业应用程序架构模式)模式。在这种情况下,实体仍然不知道持久性机制(它将是“纯粹的业务逻辑,没有其他”),并且您将“映射”实体的“数据”的责任委托给外部参与者(类/其他)当前保留在持久性机制/层中和之外。

换句话说,当采用这种方法时,您将把理解持久性机制以及从数据库到实体和从实体到数据库的转换的责任委托给翻译人员。这样,您的实体甚至永远不会意识到它们被持久化在其他地方,更不用说这种持久化过程的内部运作了。

持久性数据映射器的接口将是这样的:

interface IMyDataMapper {
    void Save(IMyEntity entity);
    IMyEntity Get(whatever criteria you use to find the entity);
}
Run Code Online (Sandbox Code Playgroud)

因此,从该界面来看,它的职责很明确:

  • 它接收一个实体(该实体不知道此操作)并读取其数据以将其存储在其他地方。
  • 它接收在其他地方查找存储数据的条件,找到它并用该数据填充实体对象以将其返回给您。