access domain service from query method ...

848 views
Skip to first unread message

Juan

unread,
May 3, 2017, 4:28:49 PM5/3/17
to DDD/CQRS
Hello, what is the right way of doing the following:

I have CQRS with Hexagonal Architecture. I don't use events for now, just synchronous communications. In my application layer I separate queries from commands. Query Services don't access the domain, they query the database directly through a secondary adapter (database adapter), and they return the objects that the client of the app needs (DTOs). They don't know about domain objects.

But I have a problem... there's some objects that aren't stored in the database of the bounded context. They are stored in another bounded context, and my domain model access them with an anti corruption layer (a domain service).

So how can I get the info of those objects in my query method if it isn't stored in the local database? I think I shouldn't call the domain service from the query method.

The local database just stores the ids of those objects, and the domain service gets the info from the another bounded context through the ACL. Is this right?

But I don't know how to get that info from my query method.

Thank you.

David Z

unread,
May 4, 2017, 9:18:45 AM5/4/17
to DDD/CQRS
Hi Juan, 

My 2 cents worth....
Not sure if my thought fits within the CQRS realm, but I would consider taking advantage of using foreign table proxies within your Database; I am assuming that your DB supports this feature. The architectural problem it can introduce is the tighter coupling between the two databases, especially if it, the table schema, is subject to change.  The advantage of this approach is that the non-local database *appears* to be local and is therefore transparent to your query service. 

Juan

unread,
May 4, 2017, 1:19:44 PM5/4/17
to DDD/CQRS
Hi. Thanks David Z. Your approach is what I meant. But the problem is how does the query method get the remote info from the local id. That job is done by a domain service. Query method shouldnt call domain services.

The only solution that comes to my mind is to replicate the info needed, either by domain events either by running a batch process with a given frequency.

Another problem I have is how does CQRS fit with an in memory database?

My database in memory is just collections of domain objects accessed by repositories called by commands.

But the query part shouldnt access repositories nor deal with domain objects. Queries should access database directly and build dtos for the client. But how to do this if the database is inmemory collections of domain objects???

Thank you.

David Z

unread,
May 5, 2017, 12:18:53 PM5/5/17
to DDD/CQRS
Sounds like if you really need the information then you should create a view in your local DB and populate; could be that the data should be within your bounded context anyway. 

Rupesh Kumar Tiwari

unread,
May 6, 2017, 7:26:53 AM5/6/17
to ddd...@googlegroups.com
Hi Juan,

I would prefer doing this via domain event. If both command and query are running in the same process then you can use in memory domain events publishers to publish domain event on execution of certain command. 

These domain event handler can be present in the query model which will create VM and persist in local db as per needed. 

I have one question if  your domain is in in memory then so far how u have created your query database. Are you not publishing events so far to create your query db ? 



Thanks,
Rupesh kumar Tiwari
 

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.
Visit this group at https://groups.google.com/group/dddcqrs.
For more options, visit https://groups.google.com/d/optout.

Juan

unread,
May 6, 2017, 7:22:42 PM5/6/17
to DDD/CQRS
Hi Rupesh,

thanks for your answer. Indeed async integration via events would be the best choice to integrate both bounded context. I would have the info of the remote BC duplicated in the local BC database. And I would update it when receiving an event saying it has changed.

But for now I'm begining implementing CQRS and I'm doing it synchronously , via domain service, with an ACL (Vaughn Vernon uses this approach in his book IDDD, integrating Collaboration BC with IdentityAndAccess BC). To maintain the local BC up to date I would have to run every certain period of time a background process asking the remote BC.

Apart from this, another issue is the inmemory database. I was missing creating the query db from the inmemory db. In my case the query db is a view from the inmemory db. This view contains "raw data" and I create the view every time I run a query method. First I create the query db (db view) from the inmemory db, and then the query method queries the query db.

Both things (BCs integration and Query Database updating) can be done with domain events, but for now I'm doing it in a synchronous way.

I have a question Rupesh... how do you fit CQRS in hexagonal architecture?

My approach is to put them in the application service (I have a package for commands and another one for querys). My application service is a primary port of the architecture, it is the use case boundary.

Commands use domain in order to do their job. They use Repositories.
Query methods doesn't use domain, they are implemented by the persistence adapter without using repositories. They hit query database.

Is this ok? Or it would be better to put the querys in another primary port? That is , one port for commands and another one for querys

Thank you.


 



Thanks,
Rupesh kumar Tiwari
 

To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.

Rupesh Kumar Tiwari

unread,
May 9, 2017, 8:05:01 AM5/9/17
to ddd...@googlegroups.com
Hi Juan,

I got your point you are using anti corruption layer to get 3rd party data to your BC and for that u r might be using some repository and your domain service might be using repository to get that data. 

Now with respect to Hexagonal architecture. 
I believe your current design is good. However, I think you need to open 4 ports. 2 primary and 2 secondary.

I will try to fit CQRS in Hexagonal architecture by opening 4 ports.
1) primary - Application layer port for use case. (Command)
2) primary - Application layer port for view models or query (Query)
3) secondary - IRepository to store data in db. ( Database )
4) secondary - ISubscriber to store query model in db. (Query DB)

You already have 1, 3, and 4 ports. I think yes you can add one more port for Query/View Model. Just create the whole slice for query model that way separate the whole line across your hexagonal architecture. 

Hope it helps !
 

Thanks,
Rupesh kumar Tiwari
 

To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.

Juan

unread,
May 11, 2017, 7:32:36 PM5/11/17
to DDD/CQRS
Hola Rupesh, thank you very much for your opinion.

I think I will create a new primary port for the querys. But i've realized about a "problem" with that:

If we have say a web app (it is a primary adapter), it would attach to just one primary port. However , in this case it would access both primary ports, one to perform command use cases, and the other for querys. Maybe the point here is to split the webapp into two also, and then composite the 2 GUIs  in just one.

Another doubts I have relating to secondary ports and adapters:

(1) The secondary ports (the interdaces) belongs to the domain, and the implementation of the interfaces are the secondary adapters.

But in case of a concern that is responsability of the application service  (sauthentication & authorization, transactions, ...), then the secondary port belongs to the app service, skipping the domain. I dont know if this ( is correct from hexagonal archytecture point of view. I think that it isn't

(2) ¿Should the secondary ports isolate the domain model (the inner hexagon) from the secondary adapter? (as the primary port does not allowing the use of domain objects in the GUI) . In case of secondary ports it would be that secondary adapters should not use the domain objects. For example persistence adapter should not know about domain model objects. 

Implementing hexagonañ architecture strictly is hard. Lot of maven modules. My structure and dependencies are:

Primary adapter (webapp for example) --> Primary port (app service) --> domain <-- Secondary Port (persistence interfaces) <-- Secondary Adapter (persistence implamentation)

Rupesh Kumar Tiwari

unread,
May 12, 2017, 1:11:49 PM5/12/17
to ddd...@googlegroups.com
Hi Juan,
Thanks for sharing your thoughts.

Yes this may be a composite UI if you need to show some thing from command model as well. Otherwise you can show your page directly form READ model also. It depends on design of project. 

Related to other concerns 

IN DDD ( domain driven design ):
Application layer uses Repository interfaces to fetch domain model and execute use case. 
In Domain Driven Design Repository interfaces are the building blocks of DDD tactical patterns. 
Therefore, both Application layer and Infrastructure layer must take DOMAIN dependencies. 
Its more of ONION architecture where the outer layer can take dependencies of inner layer. However, inner layer can not take dependencies of outer layer. Hence it is fine to have domain dependencies in all adapters ( like db layer or app layer ). In our project we are also doing this. 
-----------------------------------------

IN HEX Architecture with decoupled moving parts :
You can create interfaces for your domain objects and repositories so that you create truly ports.
So Domain entities now deriving from interfaces. Entity Repositories will be deriving from interfaces. And both interfaces is in one separate project that project DLL is refereed in Domain layer, infrastructure layer and application layer. 
By doing above we confirm HEX architecture and separation of concerns too. 
Services and Domain they exist in different axis and changes for different reasons. Therefore, it is not a good idea to keep domain layer dependencies in any service layer. 

Domain (core) -->Domain Interface + Repository Interfaces[PORT]<--Infrastructure.Persistance(Adapter

I have never done like this but I would want to see if anyone is doing like this in our group ? 

​share your thoughts !​



Thanks,
Rupesh kumar Tiwari
 

To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.

Juan

unread,
May 12, 2017, 6:34:13 PM5/12/17
to DDD/CQRS
Hola Rupesh...

About webapp and primary ports commands and querys... although commands don't show anything in the GUI, they are called by the webapp to perform an action, so webbapp adapter should depend on both ports, which is not correct. Maybe a better solution instead of split the webapp, should be to have another bounded context for read model with the query port. So you just have one webapp that calls both bounded context (one for commands and antoher for querys).

--------------------------------------------------------------------
My hexagonal architecture implementation is similar to what you said, I move apart truely secondary ports... but domain should not depend on them (domain should not depend on anything)... the dependencies should always point inwards... so what I do is the following (taking as an example a repository):

The repository interface belongs to the domain, for example FooRepository.
And apart I have another interface FooRepositoryPort, that belongs to another maven module. This  interface does nothing , just extends the domain repository interface (FooRepositoryPort extends FooRepository), but adds nothing (it is kind a "workaround" to make secondary port depends on domain, and not the other way).
A concrete implementation class of the port (for example JpaFooRepository) would belong to a secondary adapter that depends on the secondary port (JpaFooRepository implements FooRepositoryPort).

This way I introduce another "layer" that is a truely port from the hexagonal architecture point of view, but the complexity of the overall project increase.

So my whole project has a lot of maven modules (if I want to implement pure hexagonal architecture):

- one module for domain model (this module depends on nothing but just maybe a shared kernel and technology agnostic java utils, just utils for dates, strings, ...)
- one module for every secondary port (these modules depends on domain model module)
- one module for every secondary adapter (here a concrete secondary adapter module depends just on the module of the port that is implemented by the adapter)
- same for primary ports and primary adapters, but here I cut the transitive dependency between primary adapter and domain model through the port, so that the adapter can't reach domain object

Recently, in order to follow DDD rules, I also let the primary port (DDD application layer) depends on secondary ports, so that an application service can call a method that it will be implemented by a secondary adapter (DDD infraestructure). But from a pure hexagonal point of view I think that it isn't correct to do this.
 
And also I'm thinking about allowing secondary adapter reach the domain or not (like I do with primary). Not allowing it would increase complexity a lot.

Rupesh Kumar Tiwari

unread,
May 12, 2017, 8:52:33 PM5/12/17
to ddd...@googlegroups.com
Excellent  ! Thanks for explaining your project structure. I liked it. 

Now a days I am learning that the entire system should not be biased on some one pattern. 

We should be first dividing our entire problem domain in to solution domain bounded context. 

Then bases on the problem and requirement we can decide which bounded context needs what type of technology and pattern. 

If some BC is collaborative and competitive then follow cqrs such that end user gets nice experience with less congestion. 

If some BC is just CRUD then don't need ddd or cqrs do it with simple implementation. 

If some BC is very complex and volition changing business logic then do DDD over that BC. 

If we follow this way then we will not end up maintaining big source code base with doing lots of layers , code and maintenance. However you will end up havibg 1 or 2 small BC which may need cqrs or hexagonal architecture. 

Hope I am clear sorry for long explaination. 



Thanks,
Rupesh Tiwari

To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.

Juan

unread,
May 12, 2017, 11:06:59 PM5/12/17
to DDD/CQRS
I understand perfectly what you mean. That's the strategic DDD philosophy. It's what I do too. What I've explain about hexagonal architecture is refering to a concrete BC.

If a bounded context doesnt deserve it because it's a simple CRUD you can adopt the traditional data-driven layer architecture with anemic model. There's nothing wrong with it.

And for example if a BC is generic subdomain you can use an existing app and not develop it by yourself. It depends on the important you consider the BC for your bussines success.

In DDD is more important the strategic part and the context mapping than the tactical part used inside a BC.

First of all you have to have a clear idea of the whole system , make a good division in BCs , and the relationships between them.


About my implementation of HA, I have another approach that would solve the problem of primary ports calling directly the secondary ports:

The point is to consider the application services layer as part of the inner hexagon. This way I add another "layer" (the primary port) that does nothing, it just "redirects" the request coming from the primary adapter to the application service. But this have another "problem":

This the core (inner hexagon) of the hexagonal architecture is the application layer surrounding the domain model. So a secondary port doesn't depends directly on domain model, but transitively through the application layer. This isn't correct from the hexagonal point of view (I think).

Primary Adapter --> Primary Port --> Core <-- Secondary Port <-- Secondary Adapter

where Core = ( app --> domain )

Finally I discarded this approach because it was too complex, too much levels of redirections (I just remain with the extra secondary port "layer"), and because the DDD app layer fits in what a primary port is.

Maybe I'm to purist but I like hexagonal (ports and adapters) a lot, more than the "onion" and more than the DDD layers by Eric Evans. Ports and Adapters separate better the code and the dependencies, but the price you have to pay for it is the complexity of the project structure.

I'm struggling every day about what of the several HA approaches to follow.

From more simple (but less correct) to more complex (but more purist) they should be:

P.A. --> P.P. (app layer) --> domain model <-- S.A.      (S.P. would be inside the domain)

P.A. --> P.P. (app layer) --> domain model <-- S.P. <-- S.A.       (S.P. extends interfaces of the domain)

P.A. --> P.P. --> core ( app --> domain model ) <-- S.P. <-- S.A.        (P.P. redirects calls from P.A. to app)


By now I've taken the second approach but I'm struggling every day about it.

Greg Young

unread,
May 13, 2017, 7:00:54 AM5/13/17
to ddd...@googlegroups.com
"I have a question Rupesh... how do you fit CQRS in hexagonal architecture?"


Alistair actually did a lightning talk on this where he showed two
hexagons. I am not sure if it is videoed anywhere.
--
Studying for the Turing test

Greg Young

unread,
May 13, 2017, 9:42:41 AM5/13/17
to ddd...@googlegroups.com
I spent a few minutes and asked Alistair if he remembered the talk and
voila here is the video https://www.youtube.com/watch?v=9kQ2veoeWZM

Rupesh Kumar Tiwari

unread,
May 13, 2017, 10:12:14 AM5/13/17
to ddd...@googlegroups.com
Thanks Greg ! 

Thanks,
Rupesh Tiwari


>> Visit this group at https://groups.google.com/group/dddcqrs.
>> For more options, visit https://groups.google.com/d/optout.
>
>
>
> --
> Studying for the Turing test



--
Studying for the Turing test

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.

Juan

unread,
May 13, 2017, 10:18:19 AM5/13/17
to DDD/CQRS
Hi.

Alright, thank you.

That was my last thought about it. One hexagon BC for commands and another hexagon BC for querys.

Thanks.

Juan

unread,
May 13, 2017, 11:29:37 AM5/13/17
to DDD/CQRS
In order to fit DDD into Hexagonal Architecture, I think that I was wrong when I said that a secondary port shouldn't depend on domain (being the inner hexagon = app layer + domain).

Hexagonal architecture says nothing about the way you structure the code inside the inner hexagon. So app layer doesnt have to forbid secondary port to extend a domain interface.

A secondary port can either extends an interface defined in the app layer (for infraestructure aspects that are responsability of the app services, for example security), either an interface defined in the domain (for example a Repository).

Greg Young

unread,
May 13, 2017, 11:34:23 AM5/13/17
to ddd...@googlegroups.com
"In order to fit DDD into Hexagonal Architecture"

DDD is pretty much always in a hexagonal architecture. Infrastructure
service = port.

Juan

unread,
May 13, 2017, 6:37:26 PM5/13/17
to DDD/CQRS
Yeah of course, but what about when the secondary port belongs to app layer (this is the case when app service has to access directly the outside of the hexagon, for example for logging, security, etc).

In hexagonal architecture, secondary ports are for letting the inner hexagon communicate with outside world.

So i would consider app services as part of the inner hexagon, not as a primary port, and i would introduce an extra component to be the primary port, that it would just forward the call from the primary adsptee

Greg Young

unread,
May 13, 2017, 6:59:36 PM5/13/17
to ddd...@googlegroups.com
When I read mails like these it makes me want to abandon the list.
Perhaps you can talk about what you have been building and provide an
example as opposed to talking in wordsalad? I am not sure who here
could have possibly gained value from your post.

Juan

unread,
May 13, 2017, 7:35:18 PM5/13/17
to DDD/CQRS
It wasn't my intention to offend anyone. I was just sharing my experience, my doubts, and my thoughts when trying to implement the hexagonal architecture with DDD.

I think I didn't talk bad to anybody to deserve those words.

But if you think what you said, then I apologize you and anyone else.

I'm nobody, just someone who likes his profession and who likes to learn everyday.

Don't abandon the list, it's me who abandon. I don't wanna keep on writing things that nobody are interested in.

Sorry again and good bye. It's for sure that if nobody gained value from my post, nobody's gonna miss me.

Greg Young

unread,
May 13, 2017, 7:36:26 PM5/13/17
to ddd...@googlegroups.com
"Perhaps you can talk about what you have been building and provide an
example as opposed to talking in wordsalad?"

Reply all
Reply to author
Forward
0 new messages