1

Say I have an aggregate root Entity with some flags which are represented by an encapsulated object EntityFlags:

class Entity
{
    /** @var EntityFlags */
    private $flags;
    ...
}

I have a repository for this entity.

My goal is to modify flags in the DB. There are two ways I see:

  1. Get entity from the repository, modify flags like $entity->getFlags()->set($name, true) and save it: $repository->save($entity).
  2. Create an additional method in the repository, e.g. modifyFlags(EntityId $id, EntityFlags $flags)

I think the first way is redundant. But it also seems wrong to use repository for partial entity updates like in the 2nd way. Which way is the correct one? Maybe I missed something?

1

You're placing too much responsibility into the Repository here, drifting away from the original pattern. A Repository is just supposed to be a conceptual set of domain objects, a collection you can query from or add to without minding about the underlying persistent storage.

modifyFlags(EntityId $id, EntityFlags $flags) could typically be the signature of a use case, i.e. a method in one of your Application layer Services, but not a Repository method. A repo isn't supposed to contain object modification logic.

save($entity) may also not fit very well into the repo, because knowing how to flush things to the database is a separate responsibility in itself. The Unit of Work API in most object relational mapping tools typically allows you to do that. It doesn't make much sense to have a Save(object) method on an array or a collection type - likewise on a Repository.

| improve this answer | |
  • Thanks for the answer. I don't use ORM and Unit of Work patterns in my project. According to Eric Evans' DDD book, Repository can take responsibility for DB interaction. Martin Fowler describes repos as "Mediates between the domain and data mapping layers". So if I have not ORM I must use repos for DB interaction, isn't it? – Vitaly Chirkov Apr 18 '14 at 13:32
  • If not using a Unit of Work-like mechanism, you're probably experiencing problems listed in the second paragraph here : martinfowler.com/eaaCatalog/unitOfWork.html Anyway, you don't have to use repos for DB interaction - clients shouldn't have to see it that way. Again, in the eyes of its consumers, a repo is just like an in-memory collection. If you absolutely want the add() method to be side by side with other data manipulation, at least don't reflect it in the Repository domain abstraction (interface, abstract class) that the world sees, put it at the concrete repo class level. – guillaume31 Apr 18 '14 at 14:19
  • You might be interested in these articles discussing the problem of save() in repositories : richarddingwall.name/2009/10/22/… codebetter.com/iancooper/2011/04/12/… odetocode.com/blogs/scott/archive/2010/06/13/… – guillaume31 Apr 18 '14 at 14:20
  • Thanks, it becomes clearer now. I consider the opportunity to apply Unit of Work. – Vitaly Chirkov Apr 18 '14 at 14:26
  • (I meant save() method not add()) – guillaume31 Apr 18 '14 at 14:27
1

Both are possible, but the question is why would you want to use one over another. First case allows you to do additional work when setting flags. Maybe you want to modify something else or notify other piece of code. This is especially true for aggregate roots, whose reason for existence is primarily to ensure business rules over multiple entities. But pulling whole entity from database, just to change single property does seem wasteful. Second case removes this waste, but also removes your ability to run any business rules during the change. Also, any performance optimizations should be preceded by profiling, so you don't complicate your code for "percieved" performance gain.

If it was on me, I would use the first option, and if I figure out through profiling this is a performance problem, I would change it to second option.

| improve this answer | |
  • I tend to think the 2nd way does not fit to the Repository pattern. It seems the first way is lesser evil by now. I plan to do some investigations on UoW too. – Vitaly Chirkov Apr 18 '14 at 14:34
  • @VitalyChirkov It doesn't matter if it is on repository or on some service class. And repository in itself is a service class. – Euphoric Apr 18 '14 at 14:35
  • IMHO, the service sould not have a state. But the Repository has a collection semantics and has a state. – Vitaly Chirkov Apr 18 '14 at 14:39
  • 1
    @VitalyChirkov True. But still, this method could be part of the repository. Because each repository is closely related to the entity it persist. So it is logical this repository can have methods that manipulate those entities. – Euphoric Apr 18 '14 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.