Jakub Filipczyk
Jakub Filipczyk

Reputation: 1141

Database externalization in Onion/Hexagonal architecture

I thinking about writing an app using an onion/hexagonal architecture pattern. I'm stuck on a database externalization.

My app need to make some complex data queries to fulfill a use cases. I have two aggregates "A" and "B" and they are related. To fulfill UseCase1 I need to get all "A"s having properties wich match given values and additionaly related to "B"s having properties which match other values. To fulfill UseCase2 I need to do some other "query". I plan to create a repository interface f.e. ARepository which will isolate database access details from the domain logic. Since filter rules are domain rules they cannot be an implementation detail of repository class.

My doubts:

  1. Is it ok that ARepository implementation makes some SQL joins to "B" tables?
  2. Is it ok to design some generic filter criteria object and each UseCase will create own criteria and use it to pass to ARepository::filterByCriteria()? Is it a good contract?
  3. Is it ok to create dedicated methods in ARepository for each UseCase? (I'm affraid that in the future there will be plenty of filter methods with names describing usecases)

Any other ideas are welcome

UseCase samples:

UseCase1 - Create report from "A"s:

UseCase2 - Export "A"s to external system:

Upvotes: 0

Views: 778

Answers (2)

Stephan Eggermont
Stephan Eggermont

Reputation: 15917

Your use cases have duplication in them. If they describe well the way the business thinks and talks about the system, it is ok to have dedicated entry points for them. It is important however, to make sure you eliminate duplication from their implementation systematically.

A problem I've regularly seen with this is having too many developers implementing similar use cases, using copy-and-paste style, and not taking time to communicate about them and refactor. I always run a clone detector over a new (for me) code base.

Upvotes: 0

Aaron Hawkins
Aaron Hawkins

Reputation: 2691

  1. Is it ok that ARepository implementation makes some SQL joins to "B" tables?

Yes, an aggregate can load shared pieces with other aggregates.

  1. Is it ok to design some generic filter criteria object and each UseCase will create own criteria and use it to pass to ARepository::filterByCriteria()? Is it a good contract?

There are no tenants on the design of the repository that I'm aware of, but there are several different techniques/patterns that may be used. You should find the techniques used in the language/environment you are working in and choose the one that best suits your needs.

  1. Is it ok to create dedicated methods in ARepository for each UseCase? (I'm affraid that in the future there will be plenty of filter methods with names describing usecases)

Yes, this is a valid pattern which is often used.

For reference, you should take a look at CQRS. You can have a separate reporting model that is different from your domain model and there are some interesting benefits and consequences of this approach. Check it out!

Also, when dealing with DDD, remember that bounded contexts are very important and that the domain layer is supposed to be an expressive representation of the business and its interactions. You should probably always provide your bounded context when posting a DDD question. The reason I say that is because there is no way to know how the use cases you provided relate to your business. They may not even belong in the domain layer at all.

To give an example, let's say you have use case A: User can select invoice template to apply to their generated invoices.

If you're an invoicing service, this use case may very well belong in your domain layer and I imagine Invoice would probably be an aggregate root.

If you're a carpet cleaning service, this use case is probably just UI fluff and doesn't belong in your domain layer at all. In that case, this probably fits better solely under UI or possibly under application services.

All of this is to say that use cases may or may not be apart of your domain layer depending on your business. In DDD, context is EVERYTHING.

Upvotes: 4

Related Questions