【问题标题】:How to build complex value-object?如何构建复杂的值对象?
【发布时间】:2017-04-14 13:16:07
【问题描述】:

我刚刚开始学习 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 的正确方法是什么?

统一更新: 另一方面,我必须获取所有可用的标签。而且我永远不必用帖子更改标签。标签的名称看起来像身份。也许我从根本上错了?也许标签是实体?

UPD2:

这个问题说明我的设计水平很差。 正因为如此,我的一个问题中有两个问题。 它们是:

  1. 在实体的存储库中构建值对象的正确方法是什么。
  2. 如何在我的问题中查看值和实体之间的差异。 毕竟看起来很清楚。根据指定的条件,标签是值。并且它是由 Post 的仓库构建的就可以了。

但这种情况是分析不善的结果。如果我能看得更远,我会看到这个标签有它自己的生命周期。不过,在帖子的上下文中,标签是不可变的。

【问题讨论】:

  • 问问自己,如果标签被称为ddd,然后您决定将其重命名为domain-driven-design 以供将来使用,它是否应该反映以前标记的帖子?如果不是,那么它是一个值,否则它很可能是帖子上下文中的不可变实体,但标签管理上下文中的可变实体。
  • @plalx,您能否将您的评论移至答案?它很有用,我想投票。

标签: domain-driven-design ddd-repositories value-objects


【解决方案1】:

标签很可能只是您域中的常规值对象。标签可以是一个实体,如果它有自己的生命周期的话。坦率地说,我认为您的域中并非如此,因为您可以将每个标签替换为具有相同属性的另一个副本。

您可以将查询标签的方法添加到您的域存储库。这不违反 DDD 聚合规则。聚合实际上是关于一致性的——如果您可以在聚合上下文之外修改它们,那么您的存储库不应返回聚合的一部分。但是,您可以显式返回聚合的值对象,仅用于读取目的(例如,收集选定日期范围内所有帖子的所有标签)。除此之外,为了提高效率,查询方法应该放在存储库中。话虽如此,在您的情况下,最好的解决方案可能是使用遵循 CQRS 原则的单独读取模型(使用例如 nosql db)。通过这种方式,您可以根据查询需求显式调整模型,因此效率非常高。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多