很抱歉有这么长的问题,但是我喜欢DDD,但是有一个问题我似乎无法解决。
我们在将业务规则添加到聚合根目录时遇到了问题。
当我们从前端进行查询时,我们的体系结构基本上是这样的:
举个简单的例子,我们有一个我们想要的Book
这本书
Name必须是10个字符,Author需要15个字符。
这里是TypeScript中的伪代码:
class BookAggregateRoot {
private _name: string;
private _author: string;
private constructor(name: string, author: string) {
this._name= name;
this._author= author;
}
static create(name: string, author: string): BookAggregateRoot {
if(name.length < 10) {
throw error; // not really throwing, its just to show we have an error
}
if(author.length < 15) {
throw error; // not really throwing, its just to show we have an error
}
// all data is valid, create the Book
return BookAggregateRoot(name, author);
}
}第一个场景:保存这本书
client -> DTO -> controller -> useCases (从图书类调用创建) ->调用存储库(持久化数据)返回->数据库->数据,存储库(从图书类创建) -> useCases -> mapperToDTO->控制器->客户端。
第二个场景:获取保存的书
获取数据的方式是相同的,但不需要持久化,只需要获取数据: client -> DTO -> controller -> useCases(builds query) -> calls存储库(查询) ->数据库->存储库(3. calls from Book class) -> useCases -> mapperToDTO->控制器-> Client。
只要业务规则不改变,存储的数据和获取的数据具有相同的业务规则就可以了。
问题在于创建AggregateRoot。假设现在我的Book需要一个publishedDate,所有以前不满足从数据库获取的数据的数据在第3步就会失败。
这门课现在变成:
class BookAggregateRoot {
private _name: string;
private _author: string;
private _publishedDate: Date;
private constructor(name: string, author: string, publishedDate: Date) {
this._name= name;
this._author= author;
this._publishedDate = publishedDate;
}
static create(name: string, author: string, publishedDate: Date): BookAggregateRoot {
if(name.length < 10) {
throw error; // not really throwing, its just to show we have an error
}
if(author.length < 15) {
throw error; // not really throwing, its just to show we have an error
}
if(publishedDate.invalid) {
throw error; // not really throwing, its just to show we have an error
}
// all data is valid, create the Book
return BookAggregateRoot(name, author, publishedDate);
}
}在上面的步骤3,数据总是失败的,因为创建需要一个日期。
我们可以创建一个迁移来修复所有的数据..。但这是正确的做法吗?
请提前通知我是否有更好的设计。:)
发布于 2021-01-24 13:26:23
如果业务需要存储额外的字段/列数据,那么本质上有三种可能性:
发布于 2021-01-24 21:43:55
我不知道您的域的结构,也不知道您有哪些其他域对象,但是您是否深思过如何构造代码。
从某种意义上说,你或我可以创作一本书。创建一本书与出版一本不一样。例如,我可以写一本回忆录,却永远不会出版。
考虑到这一点,是否有可能重组代码,使发布日期是可选的?
public void PublishBook(DateTime datePublished){
_publishedDate = publishedDate;
}构造函数不需要检查是否设置了发布日期。此外,我还发现,创建一个表示可以传递给聚合构造函数的数据记录的对象,并根据需要对其进行转换以适应聚合,这是一种很好的模式,可以在重构时更容易地更新聚合,因为您并不总是需要更改构造函数。
检查书集的前提。在更广泛的层面上,也许应该有一个出版商接受一本书的记录,并出版?就像我说的,取决于你的域名的其他部分。无论如何,将对象而不是单个值传递到聚合根将使将来的生活更容易。
https://softwareengineering.stackexchange.com/questions/421443
复制相似问题