anoam
anoam

Reputation: 139

How to build complex value-object?

I just have started to learn DDD. So I apologise for silly question...

So I have the Post entity. It looks fine. But it should have tags. In code it looks like this (ruby code):

class Post
  attr_reader :tags
  attr_reader :title
  attr_reader :text
  # ...
end

class Tag
  attr_reader :name
  attr_reader :description
  # ...
end

Tags aren't make a sense as entity. I don't need tag itself. But how should I to implement repository for post? I have found 2 variants:

1. Build tags in same repository. Like this:

# 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

But it looks ugly. Can't clearly say why.

2. Make separate repository for tags.

# 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

Looks better. But is it fine to make separate repository for value-objects?

What is the right way according DDD?

UPD: In other hand, I have to get all available tags. And I never have to change tag with posts. And tags' name looks like identity. Maybe I'm fundamentally wrong? Maybe tag is entity?

UPD2:

This problem shows me that my design skill is very poor. Because of it, there is two question in my one. They are:

  1. What is right way to build value object inside entities' repository.
  2. How to see the difference between value and entity in my problem. After all it looks clear. According the specified conditions, tag is value. And it's ok that it's builded by Post's repository.

But this conditions is result of poor analize. If I could look wider, I would see that tag has it's own life cycle. Though, in context of post, tags are immutable.

Upvotes: 1

Views: 543

Answers (1)

Mike Wojtyna
Mike Wojtyna

Reputation: 771

Tag is most probably just a regular value object in your domain. Tag could be an entity, if it had its own lifecycle. Frankly, I don't think that's the case in your domain, as you can replace each tag with another copy with the same properties.

You can add methods to query tags to your domain repository. It's not a violation of DDD aggregate rules. Aggregates are really about consistency - your repositories should not return parts of your aggregate if you can modify them outside of aggregate context. However, you can explicitly return value objects of your aggregates just for read purposes (e.g. collecting all tags of all posts within selected date range). Besides that, query methods should be placed inside repository for the sake of efficiency. That being said, in your case probably the best solution is to use separate read model (using e.g. nosql db) following CQRS principles. This way you have the model explicitly adjusted to your query needs, so it can very efficient.

Upvotes: 2

Related Questions