Implementation differences between Translation and AntiCorruption layers - domain-driven-design

Conceptually, I understand the difference between Translation and AntiCorruption layers, but as far as implementation is concerned, is the difference between the two that with Translation layer we don't have a Facade, nor Service(s) residing within Translation layer nor do we have an Adapter, but instead domain code itself ( residing within Bounded Context ) calls a Translator?
a. If external system ES is actually part of another application and offers functionality ( which our Bounded Context BC needs ) via its Application layer and directly from its Domain layer, how should our BC request the services it needs? By communicating with ES's Application layer or by communicating ( via Translation/AntiCorruption layer ) with ES's Domain layer?
b. Why isn't Translation/AntiCorruption layer also needed when our BC requests functionality via ES's Application layer, since the data it receives via ES's Application layer still needs to be translated into domain concepts?
c. If ES is actually part of our own application, then I assume only option is for our BC to request the functionality by communicating "directly" with ES's domain layer via Translation/AntiCorruption layer?

Translation is what the ACL does. These aren't separate concepts. Implementation can be done in various ways. The point though is to protect your domain from external systems. The ACL does this by translating the external system's model to your local domain model.
2a. The local BC should communicate with an external BC either through the application service or through an open-host service, which is basically a web service. The former approach is only feasible if you the two BCs are developed in tandem and you have direct libraries that implement both. The latter applies to 3rd party BCs or BCs that are fully encapsulated by the service.
2b. This does still need to happen, unless the two BCs are developed in tandem and have a shared kernel. I'm not a huge fan of shared kernel however.
2c. Your BC still needs to communicate with ES via ES's application service. It should never go directly to domain objects. Better yet, have the ES functionality exposed by web service which BC would call.

Related

DDD why should domain model define interfaces for infrastructure

While studying DDD I'm wondering why the Domain model need to define interfaces for the Infrastructure layer.
From my reads I got that a high level (domain model, application service, domain service) defines interfaces that need to be implemented by a lower layer (infrastructure). Simple.
From this idea I think it makes sense that an application level (in a high level) defines interfaces for a lower one (infrastructure) because the application level will use infrastructure components (A repository is a usual client of the applicaiton layer) but doesn't want to be tied to any special implementation.
However, this is confusing when I see in some books a domain level defining infrastructure interfaces because a domain model will not use ever a repository because we want our domain model "pure".
Am I missing something?
While studying DDD I'm wondering why the Domain model need to define interfaces for the Infrastructure layer.
It doesn't really -- that's part of the point.
The domain model defines the interfaces / contracts that it needs to do work, with the promise of happily working with any implementation that conforms to the contract.
So you can choose to implement the interface in your application component, or in the infrastructure component, or where ever makes sense.
Note the shift in language from "layer" to "component". Layers may be too simplistic to work -- see Udi Dahan 2007.
I came across the same question myself. From my understanding, the reason behind this is that you want the application to only consume objects/interfaces defined in the Domain Model. It also helps to keep one repository per aggregate since they sit next to each other in the same layer.
The fact that the Application layer has a reference to the Infrastructure layer is only for the purpose of dependency injection. Your Application layer services should call these interfaces exposed in the Domain layer, get Domain Objects (POCOs), do things and possibly call interfaces again; for example to commit a transaction. This is why for example the Unit of Work pattern exposes its action through a Domain Layer interface.

Do I need to test the domain services in Domain driven design?

I am developing a console application using domain driven design, i tried to keep the domain logic as much as possible into domain entities, but some how, some logic leaked into domain services, so now, do i need to test the domain services, if yes how to do it?
Yes, if they contain logic, they have to be tested.
If the service was properly decoupled, it should be possible to test it with unit tests and dependency injection.
First always make sure that your domain services are stateless.
The usual roles of domain services is stuff like validation and persistence. In those cases simply create mocks/stubs/dummies of infrastructure services that they use, pass them in, inside a unit test and assert certain behavior on those mocks. Business as usual. Sometimes the domain services need entities. Mock and pass those in as well. Assert as usual.
Inevitably someone will chime in with the venerable statement of: "but domain services aren't about persistence". If a domain service deals/uses some persistence mechanism (repository/gateway) to accomplish some responsibility, then it's perfectly reasonable 'english' to state 'its usual role is stuff like persistence'.
With that out of the way. DDD does not make decoupling goals. Good DDD is allowing ALL your business logic to happen in the domain. Making Domain Services stateless accomplishes that. Like VO It makes DS safe to pass around from outside layers. Keeping the API of DS consistent with your ubiquitous language insures they remain as a coherent unit of organization within your domain.
"But DS are not about persistence".. only if the ubiquitous language is not, and it often isn't, so the DS API shouldn't in those cases reflect a persistence mechanism. But it sure as hell can have internal methods that use a hell lot of persistence, and you will need to use mocks/stubs/dummies to get at those suckers in unit tests. Domain Services aren't some architectural scaffolding for keeping your layers separate. They are a unit of organization for higher level domain logic.
Domain Services are all about domain logic, so they should definitely be tested.
It's all the more simple to do since they have very few dependencies, and especially usually no coupling to infrastructure classes doing slow I/O stuff.
The domain layer is at the center of your application and isn't tightly coupled to any other layer, most calls will stay inside its boundaries. If Domain Services want to communicate to the outside world, they'll often use events. Therefore, you should need little to no mocks or stubs when testing them.
It depends on the framework you use. Using C# and depending on project complexity, I would take advantage on DI and factories (if any), or implement some functional tests (retrospectively) with SpecFlow and Moq, given interface contracts you should have written when implementing your domain services. The starting point would consist in installing SpecFlow, and then, you should create a dedicated test project...
http://www.specflow.org/getting-started/

Utility applications in DDD

I am quite new to DDD and have come across a scenario that i'm not to sure how to handle.
I have an application that is used to track vehicles. This application is what will be implementing the "core" of the domain for the business i am working for. Not only is this application going to be used, there will be other utility programs that must be created and used in order to help this "core/main" application function.
for example:
there is an windows service needed that will perform configured queries on a database and return results to an external database that my routing application will use. This windows service has the concept of a QuerySettings class that can be created and is then executed by this application.
Question1:
What do you call utility applications like the above described in DDD? ( it definitely isn't the main core of the domain but it's needed in order for the core application to work )
QUestion2:
Is QuerySettings a domain model? if not what is it and where should it be placed within following the onion architecture?
For question1: You may have a look at Bounded context, I think Bounded context contains a group of Domain models that represent concepts in a subdomain(or a core domain). You may need to map or share domain models in different bounded contexts to handle your business, this depends on your bounded context strategy, share-kernal, anti-corruption-layer(to name a few).
For question2: I have little information of how QuerySettings works but in general it is a domain model but in a generic subdomain, not in your vehicle tracking core domain. In core domain's view, it maybe an infrastructure concept.

Open Host Service VS Application layer

OHS ... Open Host Service
AL ... Application Layer
ACL ... AntiCorruption Layer
BC ... Bounded Context
1.
Here I'll use the term unidirectional when our OHS's public interface can only be used by external BCs to call our system, but it can't be used by our BCs to call external systems
Similarly, I'll use the term bidirectional when our OHS's public interface can be used by external BCs to call our system, but it can also be used by our BCs to call external systems
a) Is OHS unidirectional or can it also be bidirectional? I'd say it can only be unidirectional?
b) Similarly, is AL unidirectional or can it also be bidirectional? I'd say it can only be unidirectional?
2. I assume OHS doesn't replace AL, but instead sits on top of Application services/AL?
3.
a) Should OHS also be used for communication between BCs that are part of the same application or should it only be used for communication with external BCs? Whatever the answer, please elaborate your reasoning?
b) Assuming BCs communicating with each other are part of the same application and assuming we don't use OHS - should these BCs communicate with each other directly ( ie. BC would call ACL, which in turn would make a direct call to BC ) or via AL ( ie. BC would call ACL, which would call AL, which then would make a direct call to BC )?
I'd argue that these BCs should communicate directly and not via AL, since it may bloat AL's interface and may also expose inner functionality to external systems?
4.
Eric Evan's DDD book, pg. 375:
Open Host Service uses a standardized protocol for multiparty
integration. It employs a model of the domain for interchange between
systems, even though that model may not be used internally by those
systems.
a) I assume our OHS should use our application's domain model only as the basis for its own model? In other words, OHS shouldn't use application's domain model, but should instead just base its very own model on it?
b) Since our OHS has it's very own model ( which is usually based on Core Domain, whatever that may be ), I assume that we should also define a translation/anticorruption layer sitting between OHS and the rest of our application?
c) Are arguments and return values of Application services defined in terms of application's domain model?
5.
Does BC always use Infrastructure services to call another BC ( of course if BC is using ACL, then BC would call ACL, which in turn would call Infrastructure layer, which would then call the other BC ), regardless if that other BC is external or part of the same application?
thanks
EULERFX:
1.
1b) An ACL is bidirectional in that data flows in either direction -
either when you're sending a message to external service or
interpreting a message received from said service.
a) By "or interpreting a message received from said service" you mean only that our ACL can receive a reply ( ie. return value ) from the called external BC or do you also mean that the same ACL which sends messages ( on behalf of our BCs ) can also interpret the messages when external BCs call our BCs?
b) If the former, then isn't in that sense OHS also bidirectional since OHS services called by external systems can also send reply ( ie. return value ) back to these external systems? If the latter, in 4b) you said OHS itself also acts as a translator, which suggests that ACL used by our BC for calling external systems won't also be used when external systems call our BC, which would imply that ACL can't be bidirectional?
3.
3b) Assuming BCs communicating with each other are part of the same
application and assuming we don't use OHS - should these BCs
communicate with each other directly ( ie. BC would call ACL, which in
turn would make a direct call to BC ) or via AL ( ie. BC would call
ACL, which would call AL, which then would make a direct call to BC )?
If not using OHS, call the application service of the other BC.
a) So you're saying that BC should call ACL, which would call AL, which then would make a direct call to the other BC?
b) Do BCs within the same application share the same AL?
c) If internal BCs do share the same AL, doesn't this mean that we may be forced to define some Application services whose only purpose is to enable internal BCs to communicate with each other ( thus external clients are not meant to call these particular Application services ). As such, don't these Application services expose inner functionality to external clients?
Clarification: I know that external clients can only directly call our Application services if they have a reference to dll containing our Application services, but if some clients do have a reference to such dll, then there's a possibility they may call Application services intended to be used only by internal BCs calling each other?
4.
b)
I assume that we should also define a translation/anticorruption layer
sitting between OHS and the rest of our application?
In effect, the OHS will be that translation layer. It will delegate
all behavior to application service, in the process adapting to the
specific technology used to implement OHS.
According to Evans, OHS should use the underlying domain model only as the basis for its own model, meaning the two models should be separate "instances".
Domain models should be completely oblivious to anything except the domain they model. Don't same rules also apply to OHS model? In other words, shouldn't OHS model be unaware of other layers and domains and as such it shouldn't be bothered with translating messages from its own model into the domain model encapsulated by the underlying AL?
c)
Are arguments and return values of Application services defined in
terms of application's domain model?
define interface in terms of DTOs
Assuming the interfaces of Application Services are defined in terms of DTOs: OHS is defined in terms of OHS model and the Application Services encapsulate the domain model, but what model defines these DTOs? In other words, are these DTOs part of OHS model, part of domain model encapsulated by AL or... ?
5.
Does BC always use Infrastructure services to call another BC ( of
course if BC is using ACL, then BC would call ACL, which in turn would
call Infrastructure layer, which would then call the other BC ),
regardless if that other BC is external or part of the same
application?
It can be said that regardless of whether the called BC is internal or
external, you still employ an ACL to one degree or another.
a) Shouldn't ACL be applied only when there's a danger of the outside model leaking into our model?
b) Since internal BCs ( BCs within the same application ) should talk to each other via AL, I assume you'd have these BCs call AL via Infrastructure layer, since Domain layer shouldn't have any dependencies on upper layers ( ie. AL )?
c) So you disagree with #mrhobo, which states that internal BCs should communicate with each other directly ( if BC is using ACL, then BC would directly call ACL, which in turn would call the other BC ) and not via AL? Why?
EULERFX, second update:
1.
b)
If the latter, in 4b) you said OHS itself also acts as a translator,
which suggests that ACL used by our BC for calling external systems
won't also be used when external systems call our BC, which would
imply that ACL can't be bidirectional?
The translation performed by the OHS, while similar to an ACL is
different in nature because it is of a technical character.
So what did Evans mean by ( pg. 368 ) "ACL can be bidirectional" , since if communication is implemented as you suggest, then ACL can never be bidirectional ( while ACL1 used by BC1 can receive a reply from BC2, ACL1 will never be used when BC2 calls BC1, even if both BC1 and BC2 are internal – note that I'm aware that BC2 will use its own ACL, I'm just pointing out that Evans talks about bidirectional ACLs. In other words, he's implying that when BC2 calls BC1, this call would be received by ACL1 )?
3.
c) If internal BCs do share the same AL, doesn't this mean that we may
be forced to define some Application services whose only purpose is to
enable internal BCs to communicate with each other ( thus external
clientsare not meant to call these particular Application services ).
As such, don't these Application services expose inner functionality
to external clients?
As above, BCs should share application services even if they internal.
That doesn't make much sense.
a) I assume it's a typo and you meant shouldn't instead of should?
b) Internal BC also don't share OHS?
c) If internal BCs communicated with each other via OHS, wouldn't we face same problems as when these BCs communicate via AL ( ie. we may be forced to define some OHS services whose only purpose is to enable internal BCs to communicate with each other, and as such these OHC services may expose inner functionality to external clients )?
5.
a)
Shouldn't ACL be applied only when there's a danger of the outside
model leaking into our model?
Yes, but that will always be the case if you're calling some
external BC. If the BCs are locally owned then you can have some
mutual agreement on model (shared kernel), but it is still often
easier to decoupled them.
I thought even when decoupled, we can still have a simple translation layer ( instead of full blown ACL ) if the public interface between two BCs is simple enough ( at least that's how I understood Evans )?
MRHOBO
3.
b)
Assuming BCs communicating with each other are part of the same
application and assuming we don't use OHS - should these BCs
communicate with each other directly ( ie. BC would call ACL, which in
turn would make a direct call to BC ) or via AL ( ie. BC would call
ACL, which would call AL, which then would make a direct call to BC )?
The AL is meant to separate the domain from it's users and ways of
usage. Different BC's living within the same application should not
communicate through such layers, but should instead be part of the
same domain layer.
So you disagree with #eulerfx about internal BCs calling each other through AL? Why?
2)
I assume OHS doesn't replace AL, but instead sits on top of
Application services/AL?
It could sit on top of an AL, but could also sit directly on top of
the BC. An AL and a OHS are very similar. If all usage of the BC
depends on the OHS, in my opinion, there is little need to create an
in between AL.
Could you clarify in what situations all usage of BC would depend only on OHS and when would it also depend on AL?
4.
b)
Since our OHS has it's very own model ( which is usually based on Core
Domain, whatever that may be ), I assume that we should also define a
translation/anticorruption layer sitting between OHS and the rest of
our application?
You will need adaptors to translate between the domain model and the
interaction model, yes. The ACL, however, is meant to integrate two
BC's in such a way that the BC that uses the ACL is unaware of the
existence of another BC. This comes in handy for a client using an
OHS, but should not go in between the OHS and the BC on the server
side.
In other words, the translator between OHS and AL shouldn't be ACL, but instead just a "regular" translator?
1.a) Is OHS unidirectional or can it also be bidirectional? I'd say it can only be unidirectional?
Exactly, a service that needs to access other services through it's own interface is not a service at all.
1.b) Similarly, is AL unidirectional or can it also be bidirectional?
Similarly, a layer that needs to access layers that use that layer is not a layer at all. As with all layered architecture: dependencies go one way only.
2) I assume OHS doesn't replace AL, but instead sits on top of Application services/AL?
It could sit on top of an AL, but could also sit directly on top of the BC. An AL and a OHS are very similar. If all usage of the BC depends on the OHS, in my opinion, there is little need to create an in between AL.
3.a) Should OHS also be used for communication between BCs that are part of the same application or should it only be used for communication with external BCs? Whatever the answer, please elaborate your reasoning?
It all depends on your use-cases, requirements and environment. An OHS is usually not cheap to build and maintain and are usually avoided for cost and simplicity's sake. There might be good reasons to have an OHS within the same application though, for example when the application needs to be distributed for availability or performance reasons or when several teams are working on different locations on different interchangeable parts of the application.
3.b) Assuming BCs communicating with each other are part of the same application and assuming we don't use OHS - should these BCs communicate with each other directly ( ie. BC would call ACL, which in turn would make a direct call to BC ) or via AL ( ie. BC would call ACL, which would call AL, which then would make a direct call to BC )?
BC's can communicate in many different ways, directly and indirectly. These are the patterns outlined by DDD: Customer/Supplier, Shared Kernel, anti-corruption layer, etc. To be clear: the Application Layer, however, is not one of them. The AL is meant to separate the domain from it's users and ways of usage. Different BC's living within the same application should not communicate through such layers, but should instead be part of the same domain layer. Which pattern should be used to integrate BC's again depends. An ACL comes in handy when working with legacy code, but is certainly not the most optimal solution if you are in control of both BC's as is the case with most application development.
4.a) I assume our OHS should use our application's domain model only as the basis for its own model? In other words, OHS shouldn't use application's domain model, but should instead just base its very own model on it?
Yes. If you don't separate your domain model from your interaction model you are not domain modeling anymore. Interaction models usually involve concepts that have nothing to do with the domain.
4.b) Since our OHS has it's very own model ( which is usually based on Core Domain, whatever that may be ), I assume that we should also define a translation/anticorruption layer sitting between OHS and the rest of our application?
You will need adaptors to translate between the domain model and the interaction model, yes.
The ACL, however, is meant to integrate two BC's in such a way that the BC that uses the ACL is unaware of the existence of another BC. This comes in handy for a client using an OHS, but should not go in between the OHS and the BC on the server side.
4.c) Are arguments and return values of Application services defined in terms of application's domain model?
They can be yes. This is done quite often to save time, but it should not cause your domain model to become application aware.
5) Does BC always use Infrastructure services to call another BC ( of course if BC is using ACL, then BC would call ACL, which in turn would call Infrastructure layer, which would then call the other BC ), regardless if that other BC is external or part of the same application?
Communication between BC's do not always have to cross layers. As I've said before, several BC's can live within the same domain layer and can be integrated in several ways outlined by DDD. This applies when the BC's are part of the same non-distributed application. When BC's are distributed, then these BC's will need to use an infrastructure layer to interact with their external counterpart.
Update
So you disagree with #eulerfx about internal BCs calling each other through AL? Why?
Yes, it seems I do.
An application layers' responsibility is to abstract application logic from other types of logic (like presentation and infrastructure logic) and to create a single point of truth within an application. The application layer pattern was not defined by DDD and is not a BC integration pattern, like shared kernel, conformist, customer/supplier and anti-corruption layer.
One application has one application layer. It is not wrong what eulerfx suggests when you think of the application layer as a facade around the BC, which it often is, but that is simply not the definition of an application layer. Look it up if you will.
Could you clarify in what situations all usage of BC would depend only on OHS and when would it also depend on AL?
An AL and an OHS are quite similar. An AL is meant to be used within an application and an OHS for external communications. Both are facades. When your application has no presentation layer, only an OHS, there is no point in creating an application layer to go in between. When an application has a presentation layer but also exposes it's BC via an OHS, the presentation layer would use the AL and external systems would use the OHS, which would in turn would use the AL.
An OHS should depend on an AL if present, because an AL should be a single point of truth.
In other words, the translator between OHS and AL shouldn't be ACL, but instead just a "regular" translator?
Exactly.
An ACL is part of a BC, but in fact gets its information from another BC. This abstracts all the messy integration parts away and makes it possible for a BC to be coded in a way that fits the domain . An ACL prevents the BC from getting corrupted with these integration issues.
Here is a practical example: https://softwareengineering.stackexchange.com/questions/184464/what-is-an-anti-corruption-layer-and-how-is-it-used
1a) It doesn't make sense to call external systems through a BC's own open-host service. With your terminology, an open-host service is always unidirectional.
1b) An ACL is bidirectional in that data flows in either direction - either when you're sending a message to external service or interpreting a message received from said service.
2) Yes, an open-host service sits on top of application services. In a hexagonal architecture, it forms a port/adapter which adapts application layer to, say, HTTP.
3a) It depends and to determine a best solution, consider the benefits and drawbacks of OHS. The main benefit is encapsulation and when coupled with a published language, can create a standardized interface to access the service, regardless of technology. The OHS will typically be more stable than internal interfaces. A drawback is the amount of effort required to implement and maintain the OHS since effectively it is another layer.
3b) If not using OHS, call the application service of the other BC. This service can fully encapsulate the constituent domain by forming the interface entirely out of DTOs. Or you can return domain objects directly if caution is used. The AL forms a facade over the domain layer simplifying the interface. Calling domain objects directly is too granular.
4a) The OHS should stem from the domain model it encapsulates, but it will likely be different from models used by its clients which is why clients should create their own ACL.
4b) In effect, the OHS will be that translation layer. It will delegate all behavior to application service, in the process adapting to the specific technology used to implement OHS.
4c) See above. They can be, but then too much domain knowledge can leak. Instead, you can define interface in terms of DTOs - read models for queries and command objects for behaviors.
5) It can be said that regardless of whether the called BC is internal or external, you still employ an ACL to one degree or another.
UPDATE
1a) The former.
1b) If an external BC calls a local OHS then it has to call it in terms of the local OHS's published language - no local ACL is needed. An ACL in the external BC would perform the translation from the external BC's model to the language of local OHS. The translation performed by the OHS, while similar to an ACL is different in nature because it is of a technical character. It is translation, or better yet, adaptation of a domain model to, say, HTTP.
3a) Yes and the called AL would be part of the other BC - a facade over the other BC's domain model. A drawback of this approach however is that the hosting application would have to configure dependencies for all BCs that are interacting.
3b) No. Each BC would have a set of application services encapsulating the corresponding domain models. Communication between BCs, when not using OHS, would go across these application services and ACLs.
3c) As above, BCs should share application services even if they internal. That doesn't make much sense.
If you have access to DLL containing application service then you can do anything really. This is why OHS provides better encapsulation and interop.
4b) The OHS does have its own model, but this model is based around the domain model. The difference is that an OHS is an adapter between the domain model and some service technology. It is meant to expose the domain model. As such it is its responsibility to translate between its model and the domain model.
4c) They form the contract of the application layer, so they are a model of the application layer. They aren't part of domain model, but they form a facade around it. They aren't part of OHS model which has its own.
5a) Yes, but that will always be the case if you're calling some external BC. If the BCs are locally owned then you can have some mutual agreement on model (shared kernel), but it is still often easier to decoupled them.
5b) Yes, but note there is no requirement to have internal BCs call each other via AL directly. You still have OHS option.
5c) The problem with calling BCs directly and bypassing application service is that the interface is more complex and too granular. The benefits of application service are explained by the facade pattern. This is the discussion in the book about granularity.

Some confusion with dependencies between Application and Infrastructure layers

When the application is using a Repository ( which is an Infrastructure service ), then Repository interface is defined within a Domain layer, while its implementation is defined within an Infrastructure layer, since that way Domain model has no outgoing dependencies.
a) If we're 100 % certain that a particular ( non-Repository ) Infrastructure service InfServ won't ever be called by any code within Domain layer, then I assume InfServ's interface doesn't need to be defined within a Domain layer?
Assuming InfServ won't be called by code within Domain layer ( and as such we don't need to define its interface within Domain layer ):
a) if InfServ will be called by Application layer's Services, I assume Application layer should have an implicit dependency on Infrastructure layer and not the other way around? In other words, both InfServ's interface and its implementation should be defined within an Infrastructure layer?
b) And the reason why it is better for Application layer to have a dependency on Infrastructure layer and not another way around is that Infrastructure layer can be reused by many applications, while Application layer is in most cases specific only to a single application and usually can't be reused by other applications?
c) If we are 100 % certain that no code within Domain layer will ever use a Repository, then we wouldn't need to define its interface within Domain layer?
UPDATE:
1)
Yes, however, the definition of domain layer can include application
services which act as a facade over the domain. The application
service usually references a repository and other infrastructural
services. It orchestrates domain objects and said services to implement
use cases.
a)
... which act as a facade over the domain
Couldn't we argue that "regular" ( those I was referring to in my question ) Application Services also act as a facade over the domain?
b)
The application service usually references a repository and other
infrastructural services.
From your reply, it seems as if you're suggesting ( though you're probably not ) that "regular" Application services don't normally reference Infrastructural services, which in fact they do ( as far as I know )?!
2)
a)
I usually merge application services, as described above, into the
domain layer.
"Regular" Application layer is also part of a BLL layer, so couldn't we argue that it is merged with Domain layer ( it actually sits on top of Domain layer )?!
b)
I tend to adhere to the Hexagonal architecture style ...
It appears Hexagonal architecture doesn't have the explicit concept of Application layer ( ie of Application Services )?
c)
Part of the benefit of declaring a repository interface in the domain
layer is that it specifies the data access requirements of the domain.
So we should include the Repository interface in Domain layer even if we domain code won't use it?
SECOND UPDATE:
2a)
If what you call a "regular" application service interacts with the
domain, I think it is acceptable to make it part of the domain
"layer". However, the domain should not directly depend on the
surrounding application service and so it is possible to split them up
into separate modules if desired.
I'm not sure whether or not you're implying that the design of Application layer ( in traditionally layered architecture ) is any different from when you merge Application layer with Domain layer using, for example, Onion architecture?
I'd say at least as far as modules are concerned, the two shouldn't be different, since in both cases we can separate Application and Domain layer modules? ( though I must confess I skipped the chaperon modules ( Evan's book ) since I didn't think I'd need that knowledge so early into learning DDD :O )
2b)
Yes because it can be contrasted with a layered architecture. A strict
layered architecture does not gel with the idea of declaring
repository interfaces in domain layer and implementing in
infrastructure layer. This is because, on the one hand, you have a
dependency in one direction, but in terms of deployment the dependency
is in the other. Hexagonal addresses these concerns by placing the
domain at the center. Take a look at the onion architecture - it is
essentially hexagonal but may be easier to grasp.
I don't yet know the MVC pattern or Asp.Net MVC, but regardless, from reading the first three parts of the series ( which confused me to the point I stopped reading it ), it appears :
a) From Onion article:
Each layer is coupled to the layers below it, and each layer is often
coupled to various infrastructure concerns.
The author is implying that in traditionally layered architecture TLA a Domain layer is coupled to Infrastructure layers, which certainly isn't true, since we normally define Infrastructure interfaces ( such as Repository interface ) within Domain layer?!
b) And if when using TLA we decide to define Infrastructure interfaces in Application layer, then Application layer also isn't coupled to Infrastructure layer?!
c) Isn't with Onion architecture an * Infrastructure layer* coupled to Application Core ( which includes Application layer ), since Infrastructure interfaces are defined in Application Core?
d) If yes to c), isn't it better to couple Application layer to Infrastructure layer ( for reasons I gave in my original question ( here I'm assuming Domain layer won't be calling Infrastructure services) )?
4)
From Onion article:
The first layer around the Domain Model is typically where we would
find interfaces that provide object saving and retrieving behavior,
called repository interfaces.
From Onion article:
The controller only depends on interfaces, which are defined in the
application core. Remember that all dependencies are toward the
center.
It appears the author is implying that since dependencies are only inwards and since Infrastructure interfaces are defined around Domain Model, that code within Domain Model shouldn't reference these interfaces. In other words, we shouldn't pass Repository reference as an argument to a method of a Domain entity ( which as you yourself has said is allowed ):
class Foo
{
...
public int DoSomething(IRepository repo)
{
...
var info = repo.Get...;
...
}
}
For reasons stated above I must confess that I fail to see the benefits of using Onion architecture or even how it is different from TLA ( assuming all Infrastructure interfaces are defined within Domain layer ) --> in other words, couldn't we depict TLA using Onion architecture diagram?!
FINAL UPDATE:
2)
b)
Yes. In TLA the domain layer would communicate directly with
infrastructure in terms of classes declared by infrastructure layer
not the other way around.
Just to be sure – you're saying that with TLA an Infrastructure interfaces would be defined in Infrastructure layer ( I know that with Hexagonal/Onion architecture they are defined in Application core )?
d)
The coupling goes both ways. The application core depends on
implementations in infrastructure and infrastructure depend on
interfaces declared in application core.
My point is that since with Onion architecture an InfServ interface is declared within Application layer ( here the assumption is that InfServ is never called by Domain Layer and as such we decide not to define InfServ interface within Domain Layer – see original 1a question ), it means that Application layer controls the InfServ interface. But I'd argue that it would be better if Infrastructure layer controlled the InfServ interface, due to reasons stated in the original 2b question?!
4)
It appears the author is implying that since dependencies are only inwards
and since Infrastructure interfaces are defined around Domain Model,
that code within Domain Model shouldn't reference these interfaces.
In my opinion, your code sample is appropriate to code.
So I was correct in saying that Onion Architecture doesn't "allow" Domain Model to reference Infrastructure interfaces, since they are defined in layer InDe ( InDe of course also resides within application core ) surrounding DM strong textand referencing them from DM would mean that dependencies go upwards from DM to InDe?
DDD is typically presented in a hexagonal/onion architectural style
which is why there may be some confusion. I think what you've probably
been doing is already hexagonal which is why it seems like it is the
same thing.
Yeah, I got that impression also. Though I do plan to look a bit deeper into the Hexagonal architecture ( especially since the new DDD book will base some examples on it ) after I finish reading Evan's book.
FOURTH UPDATE:
2)
d)
If infrastructure owned interface and implementation then the domain
or application layer would be responsible for implementing persistence
for itself.
I assume Application or Domain layers would need to implement it for themselves because referencing interfaces defined in Infrastructure layer would Onion's rule of inner layers not having dependencies on outer layers ( Infrastructure layer being the outer layer )?
4)
Domain model can reference infrastructure interfaces, such as a
repository, because they are declared together. If application layer
is split from the domain, as it is in the Onion diagram, then the domain layer
can avoid referencing interfaces because they can be defined in the
application layer.
But according to that article, Infrastructure interfaces are declared in a layer surrounding Domain Layer, which would mean it is closer to the outer edges of application core than Domain Layer – and as the article pointed out, the inner layer shouldn't have dependencies on outer layers>!
thank you
1a) Yes, however the definition of domain layer can include application services which act as a facade over the domain. The application service usually references a repository and other infrastructural services. It orchestrates domain object and said services to implement use cases.
2a,b)
I usually merge application services, as described above, into the domain layer. I tend to adhere to the Hexagonal architecture style, also called ports and adapters. The domain is at the center and is encapsulated by the application service and all external connections, including repositories, UI, and services act as ports.
2c) Part of the benefit of declaring a repository interface in the domain layer is that it specifies the data access requirements of the domain.
UPDATED
1a) I didn't intend for the application services that I mention to be distinguished from "regular" application services. If it is a facade over the domain then the rules apply.
1b) There may be services that can still be called application services, but aren't directly related to the domain and I wanted to exclude those.
2a) If what you call a "regular" application service interacts with the domain, I think it is acceptable to make it part of the domain "layer". However, the domain should not directly depend on the surrounding application service and so it is possible to split them up into separate modules if desired.
2b) Yes because it can be contrasted with a layered architecture. A strict layered architecture does not gel with the idea of declaring repository interfaces in domain layer and implementing in infrastructure layer. This is because on the one hand you have a dependency in one direction, but in terms of deployment the dependency is in the other. Hexagonal addresses these concerns by placing the domain at the center. Take a look at the onion architecture - it is essentially hexagonal but may be easier to grasp.
2c) Yes, but usually the repository interface would be referenced by an application service.
UPDATE 2
2a) They could be implemented differently, but the general responsibilities are the same. The main difference is in the dependency graph. While you can separate application services into their own modules with either architecture, the onion/hexagonal architecture emphasizes the use of interfaces to declare dependencies on infrastructure.
2ba) Yes and this is in fact a characteristic of the onion architecture.
b) Yes. In TLA the domain layer would communicate directly with infrastructure in terms of classes declared by infrastructure layer not the other way around.
c) Yes, infrastructure implements interfaces declared by domain layer.
d) The coupling goes both ways. The application core depends on implementations in infrastructure and infrastructure depends on interfaces declared in application core.
4) In my opinion, your code sample is appropriate code. There are cases where an entity needs access to a repository to perform some action. However, to improve the coupling characteristics of this code, it would be better to either define a specific interface that declares the functionality required by the entity, or if lambdas are available even better. The repository could then implement that interface and the application service would pass the repository to the entity when invoking the given behavior. This way, the entity does not depend on a general repository interface, instead it depends on a very specific role.
DDD is typically presented in a hexagonal/onion architectural style which is why there may be some confusion. I think what you've probably been doing is already hexagonal which is why it seems like it is the same thing.
UPDATE 3
2b) In TLA there would be no interfaces, or not the same kind. The domain would communicate directly with infrastructure, such as a persistence framework and so it would be responsible for persistence.
2d) If infrastructure owned interface and implementation then the domain or application layer would be responsible for implementing persistence for it self. In hexagonal/onion, the implementation of persistence is part of infrastructure - it "adapts" the abstract domain to database.
4) Domain model can reference infrastructure interfaces, such as a repository, because they are declared together. If application layer is split from domain, as it is in Onion diagram, then the domain layer can avoid referencing interfaces because they can be defined in the application layer.
UPDATE 4
2d) No that statement applies to a layered architecture with hierarchy like: UI -> Business Logic -> Data Access. The business logic layer depends on the data access layer and has to implement its data access based on the object model of the data access framework. The data access framework itself doesn't know anything about business layer.
4) The article specifies only one possible architecture. There are acceptable variations.
The only benefit I see in placing repository interfaces in the Application layer instead of the Domain is if you want to reuse the Domain DLL in another application where you would completely redefine the way you query your collections of domain entities - in other words, need completely different repositories.
However there are 2 major obstacles to that approach :
Domain layer Services. They represent processes that are at the crossroads of many entities, and thus need multiple references to do their job. It's a common and convenient thing for them to get these references by asking Repositories.
You can find an example of this in the RoutingService here.
Also, there are special cases when some entities could need the help of a repository to find a particular other entity. For instance, if you have a hierarchy of aggregate roots with parent/child relationships between them, one particular instance could say "I need the list of all my ancestors/descendants that satisfy these criteria". A repository seems like the best fit for that kind of query.

Resources