Refactoring an old API into a new one, because of several tools using it (admin and some mainteinance scripts) and compatibility with older versions reasons the database structure must remain the same.

I have a table user and another table user_optionals related 1:1. The user_optionals are just a bunch of fields with some extra options set by the user.

This, in my app, is currently reflected by a User and a UserOptional models.

Thus I'm using the repository pattern, each one has it's own repo, UserRepository and UserOptionalRepository.

I'm a bit concerned of having to inject and handle two different repositories in my services since a UserOptional won't exist if its related User previously doesn't.

I've been reading, and seems to fit in a Domain Driven Development concept known as an Agregate, but still not sure how to deal whith it.

So I'm wondering if I should apply any pattern or methodology here which agrupates both. Maybe grouping both on a unique Model or creating a new repository composed by a UserRepository and a UserOptionalRepository, maybe I'm overthinking it...

  • Isn't this case is just about that your User aggregate should contain the UserOptionals as an entity or as an invariant? If so rethink/redesign your model as so, then your repository just need to take care of correctly hydrating your User object filled the proper invariants. – kayess Aug 10 at 9:45
  • Dont have two repositories for the same database – Ewan Aug 10 at 11:16
  • I'm not clear on the problem, having to inject two repos to a service doesn't sound awful, and its solved by just making it one repo. Adding UserOpional as a property of User to make an aggregate object, also solves the issue, but makes your User object bigger. would that be an issue? – Ewan Aug 10 at 11:19
  • Exactly why do you have a user optional table rather than put it all in user? Do you not have known good default values for these optionals? – candied_orange Aug 10 at 11:37
  • Well, legacy code. I'm trying to refactor all the project in a new framework – vivoconunxino Aug 10 at 13:05
up vote 3 down vote accepted

It is normal (but not not mandatory) that aggregates span multiple tables in your database.

If UserOptional entities are subordinate to User entities -- if they don't get re-assigned from one user to another, if the life cycle of a UserOptional is within the life cycle of a User, if there is an invariant that spans multiple UserOptional within the same User... then it can make sense to have a "aggregate" that encloses both the User entity and also the related UserOptional entities.

The User entity in your domain model would probably act as the "aggregate root".

One heuristic to consider -- do you need to support concurrent modification of UserOptionals that are related to the same User?

Aggregates are, in effect, a coarse grained lock that ensures that modifications to data within the boundary of the aggregate happens one at a time. If that constraint is going to introduce too much contention for your use cases, then you may need to treat UserOptional as a distinct aggregate that it represents.

  • The user is who modifies its own options, so I guess concurrency it's not a problem. – vivoconunxino Aug 14 at 8:04

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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