域实体如何在清洁架构中相互引用
How domain entities refer to each other in Clean Architecture
根据 Bob 叔叔的实体定义:
"The Entity is pure business and nothing else."
我想澄清一下实体之间的业务逻辑关系。
假设我们有 2 个 classes,我们需要实现它们之间的关系。我看到 3 个选项:
有一个Client和Pet classes(客户端一对多Animal)。动物 class 有客户 ID
class Client {
private _clientID: ClientID;
public getID(): ClientID {
return this._clientID;
}
}
class Animal {
private _animalID: AnimalID;
private _ownerID: ClientID;
public getID(): AnimalID {
return this._animalID;
}
public getOwnerID(): ClientID {
return this._ownerID;
}
}
在这种情况下,我们可以通过 ID 知道谁是宠物的主人。我们可以根据 ownerID 的存在做出一些决定。
问题 #1。如果我们需要根据相关的实体字段做出一些关键的业务决策,我们应该怎么做?
相同 class,但 Animal class 具有客户端依赖性
class Client {
private _clientID: ClientID;
public getID(): ClientID {
return this._clientID;
}
}
class Animal {
private _animalID: AnimalID;
private _owner: Client;
public getID(): AnimalID {
return this._animalID;
}
public getOwner(): Client {
return this._owner;
}
}
在这种情况下,我们了解所有者的一切。
问题#2。在这种方法中,可能会出现这样的情况:
A {
B {
C {
... and so on ...
}
}
}
事实上,我们必须从数据库中初始化每个实体并将它们的实例注入到其他实体中。
我们没有任何关系 ID。我们在存储库中创建类似 "getPetsByClientId" 的方法(反之亦然),并协调用例中的所有内容。
class Client {
private _clientID: ClientID;
public getID(): ClientID {
return this._clientID;
}
}
class Animal {
private _animalID: AnimalID;
public getID(): AnimalID {
return this._animalID;
}
}
问题 2:我觉得我们正在丢失业务逻辑的主要部分。例如,我们需要根据 "is there an owner of this pet?" 做出一些决定(是的,新条件 - 现在我们可以在没有实际所有者的情况下创建 Pet),这个决定是一个高级策略,一个纯业务逻辑(同样,假想)。所以它的位置在一个实体中。
4(额外)。没有灵丹妙药。每个案例都需要单独实施。 (<=最悲伤的)
实体应该包含和建模最重要的业务规则。如果两个域对象之间的双向依赖关系是一个如此重要的业务规则,那么它应该反映在实体中。
这可以通过对 link 实体使用 ID 或使用直接对象引用来实现。稍后您可能已经根据您的编程语言的支持为您的实体实现自定义相等和比较操作。
根据 Bob 叔叔的实体定义:
"The Entity is pure business and nothing else."
我想澄清一下实体之间的业务逻辑关系。 假设我们有 2 个 classes,我们需要实现它们之间的关系。我看到 3 个选项:
有一个Client和Pet classes(客户端一对多Animal)。动物 class 有客户 ID
class Client { private _clientID: ClientID; public getID(): ClientID { return this._clientID; } } class Animal { private _animalID: AnimalID; private _ownerID: ClientID; public getID(): AnimalID { return this._animalID; } public getOwnerID(): ClientID { return this._ownerID; } }
在这种情况下,我们可以通过 ID 知道谁是宠物的主人。我们可以根据 ownerID 的存在做出一些决定。
问题 #1。如果我们需要根据相关的实体字段做出一些关键的业务决策,我们应该怎么做?
相同 class,但 Animal class 具有客户端依赖性
class Client { private _clientID: ClientID; public getID(): ClientID { return this._clientID; } } class Animal { private _animalID: AnimalID; private _owner: Client; public getID(): AnimalID { return this._animalID; } public getOwner(): Client { return this._owner; } }
在这种情况下,我们了解所有者的一切。
问题#2。在这种方法中,可能会出现这样的情况:
A {
B {
C {
... and so on ...
}
}
}
事实上,我们必须从数据库中初始化每个实体并将它们的实例注入到其他实体中。
我们没有任何关系 ID。我们在存储库中创建类似 "getPetsByClientId" 的方法(反之亦然),并协调用例中的所有内容。
class Client { private _clientID: ClientID; public getID(): ClientID { return this._clientID; } } class Animal { private _animalID: AnimalID; public getID(): AnimalID { return this._animalID; } }
问题 2:我觉得我们正在丢失业务逻辑的主要部分。例如,我们需要根据 "is there an owner of this pet?" 做出一些决定(是的,新条件 - 现在我们可以在没有实际所有者的情况下创建 Pet),这个决定是一个高级策略,一个纯业务逻辑(同样,假想)。所以它的位置在一个实体中。
4(额外)。没有灵丹妙药。每个案例都需要单独实施。 (<=最悲伤的)
实体应该包含和建模最重要的业务规则。如果两个域对象之间的双向依赖关系是一个如此重要的业务规则,那么它应该反映在实体中。
这可以通过对 link 实体使用 ID 或使用直接对象引用来实现。稍后您可能已经根据您的编程语言的支持为您的实体实现自定义相等和比较操作。