我正在使用DDD编写我的第一个应用程序(在Node with TS中),我首先开始编写所有域-在开始存储库/DB和应用程序之前,同时为每个实体编写单元测试。随着我的域的发展,我开始对我的业务逻辑有更多的怀疑。我将在下面给出给予示例。
我的一个业务逻辑指出,“请求者”可以创建和删除标签。因此,因为我首先编写所有域,所以我在Requester
实体中创建了一个方法createSectorTag
。该方法定义如下:
public createSectorTag(data: ISectorTagData): number {
this.checkIfIsActive()
const sector_tag = new SectorTag(data)
return this.sector_tags.push(sector_tag)
}
字符串
正如你所看到的,该方法创建了一个SectorTag
实体,并将其添加到我的Requester
实体中的一个私有数组中。由于这个方法中有一点逻辑,this.checkIfIsActive()
,我认为这段代码存在于我的域中是有意义的。但是,同时,我认为,如果它不是太多的工作对于一个简单的事情:我的意思是,每次我的应用程序调用我的域请求添加标记时,它都必须创建一个Requester
实体,然后将其添加到requester.sector_tags中;之后,我必须获取新的SectorTag
并将其持久化到具有存储库的DB中。
另一个例子是deleteSectorTag
方法。这个动作有一个逻辑,应该验证请求者内部的任何请求是否有该标记,如果有,应该引发异常。该方法的定义:
public deleteSectorTag(index: number): void {
/**
* Here I'll have to check if any of the requests inside the Request entity have
* the tag specified by the index in the parameter, and if so, raise an exception
*/
this.sector_tags.splice(index, 1)
}
型
但是,我再次认为所有这些业务逻辑在处理上增加了太多的负担。我必须从数据库中获取请求者的所有请求,创建一个Requester
实体,在实体中添加请求,然后进行验证。但这一切似乎都可以在数据库中进行验证。
嗯,我真的很喜欢把所有逻辑都放在域中的想法;这让我很高兴,因为我的代码似乎越来越接近现实。它适应了我的思维方式,但同时我担心性能。
如果有人能在这方面给我给予,我会非常感激。
以下是完整的Requester
实体:
import { BudgetRequest, SectorTag, BudgetEstimator } from '@/domain/BudgetRequest/entities'
import { RequesterIsInactiveError } from '@/domain/BudgetRequest/exceptions'
import {
IBudgetRequestData,
IRequesterData,
ISectorTagData,
} from '@/domain/BudgetRequest/interfaces'
export class Requester {
private readonly active: boolean
private readonly name: string
private readonly cnpj: number
private budget_requests: Array<BudgetRequest> = []
private sector_tags: Array<SectorTag> = []
private budget_estimators: Array<BudgetEstimator> = []
constructor(data: IRequesterData) {
this.active = data.active
this.name = data.name
this.cnpj = data.cnpj
}
get budgets_list(): Array<BudgetRequest> {
return [...this.budget_requests]
}
get sector_tags_list(): Array<SectorTag> {
return [...this.sector_tags]
}
public createBudgetRequest(data: IBudgetRequestData): number {
this.checkIfIsActive()
const budget_request: BudgetRequest = new BudgetRequest(data)
return this.budget_requests.push(budget_request)
}
public createSectorTag(data: ISectorTagData): number {
this.checkIfIsActive()
const sector_tag = new SectorTag(data)
return this.sector_tags.push(sector_tag)
}
public deleteSectorTag(index: number): void {
/**
* Here I'll have to check if any of the requests inside the Request entity have
* the tag specified by the index in the parameter, and if so, raise an exception
*/
this.sector_tags.splice(index, 1)
}
public bindSectorTagToBudgetRequest(i: number, j: number): void {
this.budget_requests[i].addSectorTag(this.sector_tags[j])
}
private checkIfIsActive(): void {
if (!this.active) {
throw new RequesterIsInactiveError()
}
}
}
型
1条答案
按热度按时间lb3vh1jj1#
我的一个业务逻辑指出,“请求者”可以创建和删除标记。因此,因为我首先编写所有域,所以我在我的请求者实体中创建了一个方法SectorTag。
1.那可能是个错误
1.这不是你的错
1.文学烂透了
实现 * 域 * 模型并不意味着我们必须给予合理的 * 数据 * 模型。
如果您的实现需要将一堆实际上没有用的信息加载到内存中-这表明您的模型目前并不适合您的问题。
当你在两条信息之间产生关系时,你需要仔细思考三种情况
一个快速的启发式方法来理解两条信息是否属于一起:对其中一条信息进行更改是否需要锁定对另一条信息的所有更改?
在你的例子中:修改标签应该阻止对预算请求的更改吗?
如果答案是肯定的--这些信息始终保持一致对业务至关重要--那么将这些信息组合在一起就有意义了。
如果答案是否定的,那么您应该考虑独立地锁定信息,这通常会涉及到更多的实体。
(Hint:答案通常是“不”。)
你可以用一个问题来区分这两者:数据需要多快达成一致。如果你可以在10秒到一分钟之间改变所有信息,并且领域Maven说“是的,这很好”,那么信息肯定不需要共享锁,你应该考虑不需要共享锁的候选设计,看看它是否会让事情变得更好。
此外,值得注意的是,我们的数据模型的某些部分实际上“只是”位于其他地方的信息缓存,我们真正需要做的就是使用通用工具(例如:级联删除)更新本地缓存的副本。
在这些地方,构建一个领域模型可能需要付出比它所值得的更多的努力。
不要创建一个域模型来解决贫血数据存储更好地解决的问题。