AntiCorruption layer's Facades, Services and SRP - domain-driven-design

1)
a) ACL Facade offers access only to those features of the other system ( external system or perhaps even another Bounded Context also developed by our team ) that our BC needs. If other system exposes functionality ( which our BC is interested in ) that we could categorize into several different responsibilities, should we define one ACL Facade for each of these responsibilities or should we have single ACL Facade expose all the responsibilities ( offered by external system ) that our BC needs?
b) If answer to a) is that we should define one ACL Facade for each of the responsibilities offered by external system, should we in turn also define one ACL Service for each ACL Facade?!
2)
a) Evan's book ( pg. 366 ):
The public interface of the AntiCorruption Layer ussually appears as a
set of Services ... It may not even make sense , in our model, to
represent the external system as a single component. It may be best to
use multiple Services, each of which has a coherent responsibility in
terms of our model
ACL itself doesn't reside within Domain layer, but don't according to the above quote ACL services represent domain concepts? If so, couldn't we argue that:
I - ACL services are Domain Services?
II - that domain concepts have leaked into ACL?
b) What is the responsibility of ACL service? Simply to mediate between our BC and an external system ( ie other BC ) or can ACL Service have a responsibility different from the responsibility offered by external system, and as such ACL Service could use functionality offered by external system only to execute its own designated tasks?
3) Evan's book ( pg. 366 ):
The public interface of the AntiCorruption Layer ussually appears as a
set of Services ... It may not even make sense , in our model, to
represent the external system as a single component. It may be best to
use multiple Services, each of which has a coherent responsibility in
terms of our model
Is author saying that it may not make sense to represent an external system as having a single responsibility, but instead that system could be represented as having several responsibilities and as such we would define ACL Facade + ACL service ( and corresponding Adapter ) for each of these responsibilities?
4) Btw - I assume ACL can also be defined between two Bounded Contexts existing within the same application and developed by the same team?
UPDATE:
1)
a) I don't quite understand your reasoning:
If the facade is used by the same project at the distinct
responsibilities still fall into the same bounded context, then use
the same facade. The benefits of the technical cohesion along the
external system API axis will outweigh the benefits of functional
coupling along the responsibility axis.
I. I assume "at" is a typo and should be replaced with "and"?
II. By "distinct responsibilities still fall into the same bounded context" are you referring to the fact that Facade is only exposing responsibilities of a single BC?
III. And if Facade was exposing responsibilities of several BCs, then we should have one Facade for each of these external BCs? If yes, why is it preferred over having a single Facade for all BCs? Simply because the Facade interface would become a mess?
IV. By "If the facade is used by the same project" you mean if both BCs are part of the same application, then we should use single Facade to expose all Responsibilities? And what if the other BC belongs to a different application?
V.
The benefits of the technical cohesion along the external system API
axis will outweigh the benefits of functional coupling along the
responsibility axis.
Why is techical cohesion preferred over functional coupling?
b)
The facade itself is effectively a service or set of services. No need
to define an additional service.
Uhm, I'm not sure I understood this. Anyways, how do ACL services map to Facade? Perhaps each ACL service is mapped to one Responsibility that our Facade exposes ( ie if Facade exposes a single responsibility, then we only have one ACL service,if it exposes two responsibilities, we have two ACL services etc )?
3)
Is author saying that it may not make sense to represent an external
system as having a single responsibility, but instead that system
could be represented as having several responsibilities and as such we
would defineACL Facade + ACL service ( and corresponding Adapter ) for
each of these responsibilities?
Yes, the external system may play different roles in your system. As
such, it can be represented as multiple services in the ACL. There is
no need to define an additional service for each ACL service - they
already are services.
I must admit I haven't yet listened to Udi's Making Roles explicit, so I'm kind of lost here, but I wasn't implying that we should add additional ACL service for each ACL service that we already have. Instead I was asking whether author meant we should have one ACL service for each responsibility ( ie if the other BC/Facade has one responsibility, we should define a single ACL service, if it has two responsibilities, we should define two ACL Services etc )
4)
Correct. However, the relationships between two BCs developed locally
may be different than that of the external system.
Different how?
SECOND UPDATE:
1)
a)
II.
A facade encapsulates an API of an external system. If the
functionality provided by the API is only used by a single BC but
there are multiple use cases, then it is OK to have a single facade
service for that BC. The alternative is to create a facade for each
use case. This is also fine, but like I said, the technical cohesion
of the first approach may be beneficial.
Q1 - You're using the term "use case" instead of Responsibility. Am I correct in assuming that saying "a Facade exposes a single Use-case" generally suggests that Facade exposes a single method, while saying "a Facade exposes a single Responsibility" could also mean that Facade exposes several methods ( which together accomplish a particular task )?
Q2 - So should a Facade expose Responsibilities or use-cases?
V.
Normally, functional cohesion is preferred over technical or logical
cohesion. Generally however, you will have mixes of both. Technical
cohesion can be convenient at smaller scales. For example, you may use
similar serialiation or translation mechanisms in a facade. It is
convenient to share those among facades, however not at the cost of
functional cohesion. Therefore, it is OK to share such functionality
within a single BC, but not across BCs.
From a distance a single Facade having Technical cohesion rather than Functional cohesion makes sense. But it gets rather confusing how this process looks in practice. To explain, assuming external system exposes several responsibilities, then we can design Facade such that it has Technical cohesion rather that Functional cohesion simply by having a single Facade exposing all the responsibilities offered by an external system.
But I'm having more difficulty imagining a scenario when external system ( and thus Facade ) exposes only a single responsibility – is even in such a scenario possible to design a Facade in such way that it has a Technical cohesion rather than Functional cohesion? If yes, could you provide a simple example?
VI. Is Functional cohesion in any way related to Side-Effect Free functions / Pure functions?
2)
b)
Anyways, how do ACL services map to Facade? Perhaps each ACL service
is mapped to one Responsibility that our Facade exposes ( ie if Facade
exposes a single responsibility, then we only have one ACL service,if
it exposes two responsibilities, we have two ACL services etc )?
The ACL is a facade consisting of services. And yes, your assumption
is an acceptable way to go about it. The term facade here isn't meant
to refer to a single class, but the set of classes (services)
comprising the anti-corruption layer. It may only be one class, or it
may be many.
I. I think I understand what you're implying, but just to be sure - assuming our BC is communicating only with one external system and as such we only have one Facade, is a Facade usually implemented as a single class?
II. Btw, I assume that ACL services don't call this Facade directly, but instead call on methods of corresponding Adapters, which in turn call methods on this Facade?
III.
And yes, your assumption is an acceptable way to go about it.
So you're essentially suggesting that if external system exposes two responsibilities, we should have a single Facade exposing both responsibilities, but on the other hand we should have two ACL services, one for each Responsibility?
THIRD UPDATE:
Your answers got me very much confused, so before I can produce any meaningful questions in response to your answers ( in both this and the other topic I made ), I must ask you the following:
As far as I understand your answers, it seems you're essentially saying that ACL services make up the Facade, meaning that these ACL Services represent the interface of the Facade? Which would also imply that Facade belongs to our BC since it is expressed in terms of our BC's domain model ( reason being that ACL Services are expressed in terms of our BC's domain model )?!
But Evans claims that Facade belongs in the BC of the other system ( and as such should be expressed using domain concepts of external system ), while ACL services should belong to our BC and as such should be expressed using the domain concepts of our BC:
pg. 367:
The Facade belongs in the BC of the other system
So did I misunderstand your post or is your opinion on the subject a bit different than that of Evans's opinion?
thank you

1a) If the facade is used by the same project and the distinct responsibilities still fall into the same bounded context, then use the same facade. The benefits of the technical cohesion along the external system API axis will outweigh the benefits of functional coupling along the responsibility axis.
1b) The facade itself is effectively a service or set of services. No need to define an additional service.
2a1) Yes.
2a2) Yes, however I wouldn't say leaking in a derogatory sense. The purpose of an ACL is to adapt an external model to the local domain model. Therefore, naturally, domain concepts will be there.
2b) The ACL service should only mediate between external system and your BC. The nature of this mediation can be stretched however. The central goal is protecting against corruption that can result from changes in the external model.
3) Yes, the external system may play different roles in your system. As such, it can be represented as multiple services in the ACL. There is no need to define an additional service for each ACL service - they already are services.
4) Correct. However, the relationships between two BCs developed locally may be different than that of the external system.
UPDATE
1a1) Yes, typo. Corrected.
1a2) A facade encapsulates an API of an external system. If the functionality provided by the API is only used by a single BC but there are multiple use cases, then it is OK to have a single facade service for that BC. The alternative is to create a facade for each use case. This is also fine, but like I said, the technical cohesion of the first approach may be beneficial.
1a3) In this case, there would be a facade in each BC. The alternative would be to try and share a facade. As you said, this would become a dependency mess.
1a4) Yes. If other BC is part of different app, create new facade specific to that BC as stated in 1a3.
1a5) Normally, functional cohesion is preferred over technical or logical cohesion. Generally however, you will have mixes of both. Technical cohesion can be convenient at smaller scales. For example, you may use similar serialiation or translation mechanisms in a facade. It is convenient to share those among facades, however not at the cost of functional cohesion. Therefore, it is OK to share such functionality within a single BC, but not across BCs.
2b) The ACL is a facade consisting of services. And yes, your assumption is an acceptable way to go about it. The term facade here isn't meant to refer to a single class, but the set of classes (services) comprising the anti-corruption layer. It may only be one class, or it may be many.
3) Yes that is what the author is saying.
4) This is also discussed in later sections of the book. The difference for local BCs could be that teams developing them can communicate and this adjust their models to fulfill requirements of the other. For external BCs, this may not be possible.
UPDATE 2
1a1) The term "use-case" was intended to be interchangeable with "responsibility". They could mean a single method or a few.
1a2) I think responsibilities is a better term.
V.) An external system could certainly provide only a single functions. For example, you can have a 3rd party service which returns the exchange rate for a currency. It only has a single method and the ACL would be in place in order to manage the differences in the way currencies and exchange rates are represented in the different systems. In this case however, you aren't thinking about cohesion because you only have a single responsibility.
VI.) No. It is just a type of cohesion that aligns along the domain at hand, as opposed to some technical aspect.
2b1) You'd have a single class that implements the domain service which exposes the external BC to the local BC. However, this class could make use of other classes, such as for serialization or whatever. Those classes however are "hidden" behind this service class.
2b2) The ACL services are what make up the facade. This may just be a confusion in terminology. An ACL is a facade.
2b3) You could have a single service expose both responsibilities. This way you can share some code easily - technical cohesion. However, you can also extract the shared code into a utility class that can be used by two distinct services. All I'm saying is that the first approach isn't terrible since you're still confined to a single BC.

Related

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/

A bounded context is a full application?

I've been reading about DDD and bounded contexts and I think I'm getting the idea wrong. At first, I liked the idea of subdomains and bounded contexts, I understood it like that: there's a software to be developed, but attacking all at once is too much, so we break it into logical pieces and develop each at once. Another problem we solve is ambiguities on the ubiquitous language.
This led me to think about bounded contexts as basically just folders where I group and bound code related to some specific piece of the application. This code I believed to be made up from things like
The domain model of that bounded context, including abstractions for repositories and services
Infrastructure layer for that bounded context, implementations of repositories and so on
Of course, being the domain model and infrastructure properly separeted within the bounded context.
Reading further, it seems, however, that each bounded context is an entire application on it's own right. It seems, sometimes, that each bounded context has it's own application layer, for instance.
This made me confused, because sometimes I don't want to end up developing tons of applications, I just one to develop one. The bounded context division of the application was supposed to build one app, not many apps to be integrated.
I've seem this question where #MikeSW says both approaches presented by the OP are valid. What I'm asking is about a third structure:
<bc 1>
|_ domain
|_ infrastructure
<bc 2>
|_ domain
|_ infrastructure
|_ application
|_ presentation
At least for all the applications I've seem this makes much more sense. I want one app, not several apps with several presentations, but I still want to be able to break the domain and benefit of things like "bounding the ubiquitous language".
So, is a bounded context a full aplication? Or can a bounded context be used like I understood and felt more useful? There are any problems with my approach?
The domain layer is usually the most complex part of your program, and can also change often due to business requirements and refactoring. So you generally don't want to expose it directly to your presentation layer or other bounded contexts. If you feel that you can expose it, it might be the case that your application logic or use case methods are mixed into your domain layer, or that your program is not large or complex enough to require multiple BC's to begin with. Otherwise, I would go with including the application layer in each BC to protect the domain model's integrity and expose only the commands that need to be called from a use case perspective.
I want one app, not several apps with several presentations, but I
still want to be able to break the domain and benefit of things like
"bounding the ubiquitous language".
You can have a thin application layer for each bounded context, and still have a single presentation layer. This is sometimes called a "composite UI", which should be considered a separate BC in itself. If you need to handle common logic such as authentication, create another application service or facade in the composite UI and have it handle the authentication before in turn calling the application service of an outside BC.
I think most of the examples you see in books and on the web are over-simplified in that they have 1 BC per physical running application (and perform some kind of network communication between them), whereas in the real world you might have a complex application that you need to split into separate logical units, but not run them as separate processes unless the need arrives.
At the end of the day the answer is both. The important thing to take away from bounded context is not how you structure your app, but that you have different spaces where you model specific behavior relating to some context. How you define the boundaries between these contexts is dependent on the problem you need to solve.
There is nothing wrong using namespaces(folders) to define bounded contexts. Like you said most of the time you are simply writing one application. You can also define your bounded context by having separate projects for each context. In this case your presentation layer will reference the project it needs.
There are many right ways to code DDD. You should ask yourself "Am I following the core principle by doing it this way"
The bounded context describes a subset of the complete solution and everything within that context serves that context. So, imo, each context has it's own domain so it could be a separate application or just a subsystem of the same project. The point of the "context" is that the ubiquitous language applies directly TO that context. For example, a User in the Account context might mean something completely different than a User in the Sales context. Each "User" will have different capabilities and follow different rules in each context. Each context needs to be isolated from any other context and are not allowed to share references (unless it's via a 'Shared' context); any communication should be mediated through a service that sits on top of that context. A context doesn't even have to follow DDD to be "DDD compliant" since each context can follow it's own approach (e.g. domain driven, data driven, etc.). Contexts are simply silos that outline a logical section of the business.
Whatever you need to do to prevent direct references across contexts is fine whether that means different namespaces, different assemblies within a solution, or different projects altogether.
The bounded context is the scope on which the code operates. It relies on a domain model, that can be supported by a ORM (or not). It implements different kinds of services (domain services and application services) but its aim is to expose only domain services to its environment. DDD is a service oriented architecture, meant to work as offline as possible and in a loose-coupled way. You may decide to consume your services in different ways. The solution implements different kinds of components, different kinds of layers, different kinds of projects. I believe the most critical attention must concern the model, that should not be distributed across components. Solution design and domain model are orthogonal purposes.

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.

Security and Access control in a MVC application

I have only recently started working with the MVC approach, so I suppose this is an easy one for you gurus here:
Where do I put access control?
In a view? I don't want to have any logic besides switches and flags in my templates, so that sounds like the least viable option
In the model? Should each business object decide what data it will reveal about itself based on who's asking?
In the controller? That's where I have it now but it makes it hard to keep business rules consistent
Or is there another option?
This will depend on what framework you're using as that and the language will dictate a lot of the tools you have available to you.
From a high level, you should have access security configured at points-of-entry. And you should double-check access security at every level that could be considered autonomous or reused from multiple parts of your application (who knows if security was checked by your co-worker's portal that uses your logic layer? etc.). The other thing to worry about is data security, and that belongs as close to your data as possible (so, yes to your #2 above, but understand that it's separate).
This is akin to the difference between application logic and domain logic, which I'm fond of talking about. If there is any logic that is specific to one particular application (web app compared to a windows service, or whatever) then that logic should be defined in that application only. If some logic crosses the boundary between applications (is reusable between applications) then it qualifies as domain logic and should be defined in your model. Your applications can make use of domain logic, but they should not own it.
For Model (aka data) security, the Model would "control" the access and the Controller would "facilitate" the access. This provides for the reuse of the Model independently of the Controller and minimizes if not negates the general code replication necessary across dissimilar Controllers which use the Model.
For example a Car, a Driver, and a Key. (Model, Controller, API respectively). By virtue of a very small interface (key == API), the Model permits or denies Controller access per API (key fob). Different types of access are permitted (Valet key, Owner Key, Owner FOB). Using the Valet key interface, the Controller will not have access to some of the data/function of the Model such as the glove compartment, the trunk and the gas tank. This is essentially role based access implemented by the Model through identifying and categorizing the Controller with a very small API/command surface area.
This means that the Model can be used by other controllers (car with different drivers) which only need the basic authentication to access the data of the model (functions and compartments of the car).

Resources