我对DDD的概念很感兴趣,但是对于封装和保护AggregateRoot内部实体的概念以及如何引用它们,我有一些疑问。我创建了一个简单的例子(如果域设计不好,不要打我,这只是一个澄清问题的例子)。
// can be referenced from outside, is aggregate root
public class Library : AggregateRoot
{
IList<Shelf> shelfs { get; }
}
// can be referenced from outside, is aggregate root
public class Shelf : AggregateRoot
{
Book GetBookById(Guid Id) {...}
}
// should be accessed through Shelf, not referenced outside the context
public class Book : Entity<Guid>
{
Guid Id { get; } // or something else uniqe, e.g. ISBN
}
// how to reference a book here?
// I think, I should not use Id because this is internal and
//only valid for Shelf Aggregate (but I can't have a second one of this book)
public class Lending : AggregateRoot
{
// feels wrong because of passing internals from Shelf
Guid LendedBook { get; set; }
// should I Clone() an object with unique identity, is this allowed in DDD?
Book LendedBook { get; set;}
// create separate type for lending (but what should this type cointain)
LendedBookInfo LendedBook { get; set;}
}希望得到一个清晰的答案,因为大多数示例都是关于ValueObjects的(这很容易,因为它们无论如何都是复制的,而不是真正引用的)。我在我的示例中使用了C#风格的代码,但是任何其他编程语言或伪代码都是欢迎的。
发布于 2015-11-10 12:42:02
外部ID使用示例
Guid LendedBook { get; set; }都没问题。要使模型更加明确,您可以做的是创建一个值对象BookId,并使用该对象作为参考书。然后,值对象BookId是一个上下文范围的概念,即不是特定聚合的本地概念。
除此之外,您可能不希望在模型中将公共setter或IList作为返回类型。但我想这只是一个例子,而不是真正的问题。
发布于 2015-11-10 13:30:16
在DDD中,模拟现实世界从来都不是坏事。如果您与该领域的领域专家(图书管理员)进行了交谈,他们可能有一些术语和工作流可以帮助您对域进行建模。
例如,他们可能会谈论使用“图书票系统”“借出一本书”,当他们想按标题查找一本书时,他们可能会在“书名目录”中查找。
这可能导致一个设计,其中有一个BookTicketService类和一个LendBook(lender, book)方法,这可能导致一个条目被记录在BookTicketSystem中。或者有一个TitleCatalogueService方法的SearchByTitle(title)类。或者,当图书馆接受一本新书进入图书馆时,它的记录可能会出现在AccessionRegister中,等等。
如果您使用这种无处不在的语言对库进行建模,那么它允许库域中的其他人更容易地获取您的软件,而最重要的是,它允许软件开发人员与图书馆员讨论他们的需求,而无需使用软件开发术语。
我会搜索一些东西,比如“如何启动库”或“库术语词汇表”,并尝试将您发现的一些语言和过程引入您的软件。人们已经拥有数以万计的书籍和贷款人,充分运作的图书馆。理论上,您所需要做的就是了解他们是如何做到的,他们使用的术语以及在软件中建模应该是可能的。
https://stackoverflow.com/questions/33616463
复制相似问题