Services and Authorization in Onion Architecture - domain-driven-design

I'm trying to learn Onion Architecture and as i understand, I've organized my solution as follows:
Domain
Domain.Entities (Business objects)
Domain.Interfaces (Interfaces for domain services and repositories)
Domain.Services (Implementation for domain services interfaces)
Infrastructure
Infrastructure.Data (Implementation for repositories and unit of work with EF)
Infrastructure.DependencyResolution (Implementation for IoC with Unity)
UI
UI.WebMVC
And here are my questions:
1- Am i right with these layers or i'm missing something ?
2- As for services that are related to a specific technology (e.g. Logging), where their interfaces should be (Domain.Interfaces or Infrastructure.Interfaces) ?
3- As i understand, The Domain Service will process my business use case so what are the benefits i'll get from application service
4- What are the differences between Domain Service and Application Service and in which project Application Service interfaces should be?
5- Should User Authorization process be a part of Application Services or Domain Services?

This a schema of hexagonal architecture, but it's really close to onion and IMO you should use that. Here are shown 3 layers: domain (yellow), application (red), infrastructure (green + blue). So answering your question - you are missing few pieces like application services.
Logging is probably not part of your domain logic, so it should be in infrastructure, both interface and implementation. To use it, you have to inject it to your application layer.
Domain services are taking care only of things that are related to your businness. Application services are most of the time preparing ground for domain services, in example creating repositories and retrieving aggregates from it, then calling domain services and passing that aggregates there. You shouldn't handle your business logic in app layer!
As I wrote in point 3. Application services should be in every projects that are using domain services.
Depends. User request your infrastructure layer with user credentials, infrastructure layer calls application layer with that credentials, there you try to retrieve user with given credentials, but first you convert raw password to hashed one with some functions. If user is found, you can authenticate user in infrastructure layer. Domain service wasn't needed here, but it's an exception.

Related

DDD: Where to put implementation of domain services

Where should Domain Service implementations reside in the DDD project structure?
If we have IDomainInterface and DomainInterface implementation, should the DomainInterface implementation reside in the Infrastructure or Core/Domain part of the solution/project ?
Domain service interfaces and their implementation may reside in the domain layer. However, if the domain service implementation depends on infrastructure concerns then by applying the Dependency Inversion Principle, the implementation would live in the infrastructure layer while depending on an interface defined in the domain.
Most domain services will not need to depend on infrastructure concerns and will be used to model use cases that cannot find a natural home within an existing aggregate, but some domain services will.
Repositories are the most common domain services that requires infrastructure knowledge and therefore you will find their implementation living in the infrastructure layer, but there are other examples.
For instance, in the IDDD's Identity & Access bounded context, the EncryptionService interface lives in the domain while the MD5EncryptionService concrete implementation lives in the infrastructure.
An onion or hexagonal architecture says that Infrastructure layer depends on inner layers.
If a contract lives in Domain layer it is because it represents some business requirement, something that represents the ubiquitous language, therefore I consider it a domain service.
If the domain service implementation requires some specific technology (for example database access, or SMTP server access or whatever), its implementation must live in the infrastructure layer. The domain simply doesn't care about implementations, if the business experts talk about something and we decide to make this "something" a contract, it must live in Domain layer. It's all about the Domain language.
Infrastructure services should not be in the Domain layer by definition. If it is something related to infrastructure, then I doubt it has anything to do with the ubiquitous language. I would expect to see infrastructure services contracts living in Application layer, because by definition an application layer is an orchestrating layer to help domain. If the implementation requires some specific technology, again, the implementation will be in the infrastructure layer.
So, to summarize and answer this question:
Where to put domain service implementations? It depends:
If the implementation does not require anything from application or from a specific technology. Place the implementation in domain layer. (Example: an order number that is calculated)
If the implementation requires anything from application layer (for example it requires accessing the Aggregate repository which, in my opinion lives in Application layer), then place the implementation in the application layer.
If the implementation requires a specific technology (for example access to a SMTP server, or a concrete http client) then place it in a infrastructure layer.
At the end, the important is that in Domain we care about the ubiquitous language, in application we orchestrate domain and the implementations go where they make sense to be placed depending on their dependencies (domain cannot depend on anything, application can only depend on domain).

DDD and Service Agents

I have a WCF Service that I want to consume from my application. In following DDD I understanding that the semantics of connecting and consuming this service should be done through a Service Agent (Infrastructure Layer).
I am happy with this however it makes me ask the following questions;
Should the Service Agent Interface be defined in the Domain Layer?
Should a repository be defined that wraps this Service Agent?
Thanks
Service Agent usage should be inside infrastructure layer. SA interface doesn't belong to domain layer since it's not part of the business domain - it has strictly technical meaning (business experts probably didn't even heard of it).
Yes, repository is the most natural wrapper around WCF Service if it is dealing with fetching/storing data. If it is dealing with business operations domain service would be better choice.

Domain Services controlling the granularity

I thought domain services should only represent domain concepts, but it seems we should also use them to control the granularity of domain layer interfaces ( which also prevents domain knowledge leaking into application layer ) and to decouple clients from entities and value object:
Eric Evan's DDD book, pg. 108:
Although this pattern discussion has emphasized the expressiveness of
modeling a concept as a Service, the pattern is also valuable as a
means of controlling granularity in the interfaces of the domain
layer, as well as decoupling clients from the Entities and Value
Objects.
Medium-grained, stateless Services can be easier to reuse in large
systems because they encapsulate significant functionality behind a
simple interface. Fine-grained domain objects can contribute to
knowledge leaks from the domain into the application layer, where the
domain object's behavior is coordinated.
a) If we also introduce domain services that don't represent domain concepts, but instead only control the granularity, don't we introduce non-domain concept into domain? If so, doesn't that hurt domain model?
b) Should most of communication with upper layers be done through medium-grained domain objects? Thus, for every use-case where communication happens through fine-grained domain objects we should introduce medium-grained domain service(s)?
c) Eric Evan's DDD book, pg. 108:
Coding conventions can make it clear that these objects are just
delivery mechanisms for SERVICE interfaces and not meaningful domain
objects.
What coding conventions is he referring to?
UPDATE:
I think you're saying that the quote is describing Application Services and not Domain services?
I'm aware of Application Services and of their purpose, but I think author is describing Domain Services, since he warns that knowledge leaks into application layer can happen due to fine-grained domain objects:
... as well as decoupling clients from the Entities and Value Objects.
Medium-grained, stateless Services can be easier to reuse in large
systems because they encapsulate significant functionality behind a
simple interface. Fine-grained domain objects can contribute to
knowledge leaks from the domain into the application layer, where the
domain object's behavior is coordinated.
And if we want to prevent knowledge leaks from domain layer into application layer, then shouldn't ( by my logic at least ) a "barrier" ( ie. a medium-grained service ) be built within domain layer?
SECOND UPDATE:
a)
With regards to granularity, a domain service serves a similar role to
an application service.
What kind of domain service are you talking about? One created only for the purpose of controlling the granularity or...?
b)
IMO, it is a matter of preference whether the application service
exists in a separate application layer project or together with other
domain objects.
You're calling a service ( the purpose of which is only to control the granularity ) an Application service even if it exists within a Domain layer?
c)
The application service does a fine job of preventing knowledge leaks
and in some sense, that is its central job.
But since a "barrier" ( ie. a medium-grained service ) exists within an Application layer, doesn't this mean that domain knowledge does leak into an Application layer ( but no further thanks to Application services )?
d)
We could say that Application layer is a client of Domain layer and author does warn throughout the book that no domain knowledge must leaks into a client. Why is Application layer ( ie Application services ) an exception to this rule?
Thanks
a) If we also introduce domain services that don't represent domain
concepts, but instead only control the granularity, don't we introduce
non-domain concept into domain? If so, doesn't that hurt domain model?
While the services don't introduce any new behavior into the domain, they don't introduce non-domain concepts either. I view these services, application services specifically, as providing an encapsulating role for the domain - a facade. Each method on the service represents a domain use case and it delegates directly to domain objects. This makes it much easier for clients of the domain layer, since they don't need to worry about coordinating repositories and calling suitable behavioral methods on aggregates. Instead, they invoke a method on the application service.
b) Should most of communication with upper layers be done through
medium-grained domain objects? Thus, for every use-case where
communication happens through fine-grained domain objects we should
introduce medium-grained domain service(s)?
Outer layers should call application services, which in turn delegate to aggregates or domain services. Note, application services are different from domain services. An application service can fully encapsulate the domain such that no domain objects are exposed by its interface, instead relying on DTOs to pass messages between outer layers and the application service. In addition to protecting the domain, this provides an opportunity to utilize something other than a domain model to implement use cases, such as a transaction script.
What coding conventions is he referring to?
One convention can be the presence of Application in service name, such as CargoApplicationService. Another convention is to place application services, which BTW can also be implemented as command handlers, into an Application module within the project.
EDIT
Take a look the this project on GitHub which implements the domain discussed in the book in a modern C# style.
UPDATE
With regards to granularity, a domain service serves a similar role to an application service. IMO, it is a matter of preference whether the application service exists in a separate application layer project or together with other domain objects. Creating an additional barrier between an application service and domain objects can become a needless abstraction. The application service does a fine job of preventing knowledge leaks and in some sense, that is its central job.
UPDATE 2
a) I was talking about domain services in general, because they all tend to increase granularity beyond entities and VOs.
b) Yes, because it still captures a domain concepts, namely use cases which are less granular then the domain objects used to implement them. Sure the application service has concerns largely orthogonal to the domain, but there isn't always a reason to put them into different layers.
c) Yes, but you can't get around leaking domain knowledge all together. If you have a database table with a name Customers which corresponds to the Customer entity, you have domain knowledge leaked into database. The point isn't to prevent all leaks, but to instead create boundaries around areas of cohesion, such that when making changes, they can be isolated to a specific layer.
d) Application service creates a facade around domain objects, effectively establishing a barrier so that clients of the domain, other than app service, have a clean interface to work with. In this way, app service is an "exception", because it sits between domain objects and outer layers.

Is there a way to avoid network traffic on Web API web services hosted in IIS by accessing your services through localhost?

We have added a Web API services layer to our application to help share the code with various product teams at my client's company. I like this as a way of managing versioning and for code organization but I'm concerned about violating Martin Fowlers First Law of Distributed Object Design, namely don't distribute your objects. We can host all of the various products on the same box currently and I was wondering if having the client application access our web services through localhost would allow us to avoid the issues that Martin is calling out. If it was WCF I would configure the end point to use Named Pipes and I guess I'm trying to figure out how to do that in IIS.
If you are hosting all your projects under the same process, it would be possible to go in-memory but I am not sure how much this makes sense. Here is a good example:
Batching Handler for ASP.NET Web API
A related post for the above one
It demonstrates the usage of in-memory hosting the entire Web API pipeline. However, in your case, it seems that this won't work out but might be worth considering.

accessing app service from domain object

Can a domain entity can call or app service layer, through service layer interface ? Please tell me way also ?
In short, no.
Domain entities should not know about the application service layer. The application service layer's job is to coordinate actions between domain objects, across bounded contexts if necessary.
In my experience, this is a pretty strict rule so if you feel you need to break it you've probably got a design problem further up the chain.

Resources