我刚开始学习DDD。所以我为愚蠢的问题道歉...
所以我有Post
实体。看起来很好。但它应该有tags
。
在代码中它看起来像这样(ruby代码):
class Post
attr_reader :tags
attr_reader :title
attr_reader :text
# ...
end
class Tag
attr_reader :name
attr_reader :description
# ...
end
标签作为实体没有意义。我本身不需要tag
。
但是我应该如何为帖子实现存储库?
我找到了2个变种:
1 在同一存储库中构建标记。像这样:
# PostRepository
def find(id)
# getting post data from storage here
# getting tags data
Post.new(title, text, tags_data.map { |tag_data| Tag.new(tag_data[:name], tag_data[:description]))
end
但它看起来很难看。无法清楚地说出原因。
2 为标签创建单独的存储库。
# PostRepository
def find(id)
# getting post data from storage here
Post.new(title, text, tag_repository.find(tag_ids)) # or tag_names or tag_something
end
看起来更好。但是为值对象创建单独的存储库是否可以?
DDD的正确方法是什么?
UPD: 另一方面,我必须得到所有可用的标签。我永远不必用帖子改变标签。标签的名称看起来像身份。也许我根本错了?也许标签是实体?
UPD2:
这个问题告诉我,我的设计技巧很差。 因此,我的问题有两个问题。 他们是:
但这种情况是分析不良的结果。如果我看起来更宽,我会看到标签有它自己的生命周期。虽然,在帖子的上下文中,标签是不可变的。
答案 0 :(得分:2)
标记很可能只是您域中的常规值对象。标签可以是一个实体,如果它有自己的生命周期。坦率地说,我认为你的域名不是这样的,因为你可以用另一个具有相同属性的副本替换每个标签。
您可以添加查询标记到域存储库的方法。它并不违反DDD汇总规则。聚合实际上是关于一致性的 - 如果您可以在聚合上下文之外修改聚合,则您的存储库不应返回聚合的一部分。但是,您可以显式返回聚合的值对象,仅用于读取目的(例如,收集所选日期范围内所有帖子的所有标记)。除此之外,为了提高效率,应将查询方法放在存储库中。话虽如此,在您的情况下,最好的解决方案可能是遵循CQRS原则使用单独的读取模型(使用例如nosql db)。通过这种方式,您可以根据查询需求明确调整模型,因此它非常有效。