I have a N-Layered Winforms application with 4 layers as follows:
Presentation Layer
Application Layer
Domain Layer
Infrastructure Layer
My Application Layer has a Product Services class which is used for all repository related actions for Products.
Does the interface file for the Product Services class belong in the Application Layer or Domain Layer? I ask because the interface file for my repositories is defined in the Domain Layer even though they are implemented in the Infrastructure Layer.
Thanks in advance.
Service concept can belong to any layer. If you ask for application services, then these should live in the application layer.
In the other hand, if these services are the ones directly accessing the domain, then they're still domain. That is, I would expect to find both a service interface and one or more implementations in any project prefixed with Domain.
BTW, the project has nothing to do with software layers. It's just an organizational unit to group files by some criteria. The most important point is your flow should work with inversion of control in mind to glue layers.
With DDD, is usually recommended to use Dependency Inversion (the D in SOLID), so the tree of dependencies should be
Domain Layer
|
/ \
/ \
Presentation Layer Infrastructure Layer
So the Presentation and Infrastructure "layers" depend on your domain, and not the other way around (the generic version of this is also know as Hexagonal Architecture or Ports and Adapters)
And the Application Layer is indeed part of your domain, as it defines how use cases are supposed to work. I've never used (or seen) an application layer in an application, but what I've done is to put the Application Services in a different package inside the same artefact (the terminology here might be a bit different as I come from a Java background).
Related
I am implementing a Clean Architecture. I have four projects: Domain, Application, Infrastructure, and Presentation.
I have repository implementations defined in the Infrastructure. And I have the Repository Interfaces in the Domain.
I also have Services with a corresponding repository injected. For example, StudentService. I inject the StudentRepository into the StudentService.
My question is, where do I put the interface IStudentService? Should it reside in the Domain along with the interface IStudenRepository? Or is it more proper to place it in the Application?
I currently have my IStudentService in the Application project. But my understanding is to have loose coupling and placing all Interfaces in the Domain project. Is my understanding correct?
It is generally a good practice to place interface definitions in the Domain layer of a Clean Architecture application. This is because the Domain layer represents the core business logic of the application, and interfaces are an important part of defining the contract for that logic. By placing interface definitions in the Domain layer, you can ensure that the Domain is decoupled from the implementation details in the other layers of the application.
For example, in your case, the IStudentRepository interface would be defined in the Domain layer because it represents the contract for how the StudentService can interact with the student data store. The IStudentService interface would also be defined in the Domain layer because it represents the contract for the business logic related to students.
By placing both of these interfaces in the Domain layer, you can ensure that the Domain is decoupled from the implementation details in the other layers of the application. This makes it easier to change the implementation of these interfaces without affecting the rest of the application.
In summary, it is generally a good practice to place interface definitions in the Domain layer of a Clean Architecture application in order to ensure loose coupling and separation of concerns.
To implement Clean Architecture follow the following steps:
Domain Project:
Domain should have just entities such as "Student" Entity.
Application Project:
Application should have interfaces and services and the implementation of services.
Infrastructure Project:
Infrastructure should have the implementation of interfaces that are defined in the Application, and DbContext class.
The presentation should have the UI.
I am learning about DDD and domain-centric architecture design applied to .NET solutions.
However, I am struggling a bit about how to implement it.
I have some examples that came up to my mind recently:
Filter/converting an excel file to another another kind of file json/xml and formatted following some business rules, be it a Console application or a WebAPI
Computing the energy deployed or the distance given some train stations
How to decide what goes into the Application "layer" and the Domain "layer"?
I read:
https://softwareengineering.stackexchange.com/questions/140999/application-layer-vs-domain-layer
https://github.com/thiagolunardi/MvcMusicStoreDDD
https://github.com/rafaelfgx/DotNetArchitecture
https://github.com/EduardoPires/EquinoxProject
https://github.com/ardalis/ddd-guestbook
https://github.com/dotnet-architecture/eShopOnWeb
https://github.com/HudsonLima/Product-API
https://github.com/thangchung/magazine-website
https://github.com/gigiogodoi/Blackbird
https://github.com/JasonGT/DDDBNE2017
https://github.com/felipeolimpos/base-core-ddd-mvc-ef-pg-ioc-proj
https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/ddd-oriented-microservice
The Domain layer contains all the code that enforces business rules.
It should be technology agnostic (like specific databases - sql, no sql - or protocols - HTTP, REST) and frameworks agnostic. This means that it looks the same whether the Aggregates are persisted in an SQL database or in a NoSQL database, it is called from a HTTP controller or from a console application.
It should be pure, with no side-effects. This implies it should not do any I/O (read or write from any files). It receives all the data it needs as method arguments. For me, passing an infrastructure or application layer as argument to an Aggregate method call is also bad, even it is hidden behind a domain interface, because it can do I/O.
It should not depend on any other Layers. This means no imports or use from other layers (or whatever programming language construct you use in your programming language).
The Application layer is a thin layer that loads an Aggregate from the Repository, it calls the corresponding method on the Aggregate and then it persist the Aggregate to the Repository. It basically glues the Domain with the Infrastructure.
In DDD architecture all the business logics and rules should be within the Domain layer. Application layer is responsible for referring the business logic by accessing Domain layer and do database updates through Infrastructure layer. So it is clear if you are goin to add a business rule or logic it should be Domain layer
Well my application follows DDD design principles. It is an ASP.NET MVC application with the MVC web application being the presentation layer(I moved controllers to application layer though). It also has Application Layer that is primarily application services, use cases, etc. Above the Application Layer is the Domain Layer where Domain Models reside. Then there is Infrastructure Layer, which sits on top of everything else, and is supposed to be dependent on no other layers.
But there is one problem I noticed, that if Persistence Logic goes into Infrastructure Layer as the DDD books suggest, the Infrastructure Layer will have dependency to Domain Layer. The Repositories, for instances, need to know the types of Domain Models(Entities) to create, with this knowledge they become dependent on Domain Layer. The original DDD principles however, suggest that Infrastructure Layer should have absolutely no dependency for anything.
So now I am confused, should Persistence Logic really, belong to the Infrastructure Layer? If so, it makes Infrastructure Layer dependent on Domain Layer. If not, then where should it be? Application Layer? Or maybe a separate layer between Application Layer and Domain Layer(as application services use repositories, repositories use domain models). What do you think?
Types of Dependency
I think an important concept that might assist here is to distinguish types of dependency - specifically, a layer or component can be dependent on another layer because either:
is defined in terms of concepts defined in that layer, or
it uses the other layer - by delegating to that layer (aka calling methods on services in that layer)
Or both the above
Inversion of Control and Dependency Injection make this distinction even more important. They guide that we should depend on abstractions rather than concretions.
This means that, for example, the domain layer can define and depend on an abstraction of a repository - e.g. an IEntityRepository interface.
However, the implementation (concretion) is then implemented in the infrastructure layer.
When the application layer wants to call on the repository, it depends on the abstraction (the interface), and the inversion of control system (IoC Container) supplies it with an implementation from the infrastructure layer.
In this case, the infrastructure layer depends on the domain layer - but only in order to know about the interface it is implementing, but it does NOT depend on any other layer in order to delegate to it - it is the last layer in the call stack.
This concept resolves the conflict you were concerned about, because the infrastructure layer doesn't depend on anything else to carry out it's function.
Onion Architecture
Once you start to incorporate IoC concepts into thinking about your architecture, a model that can become very helpful is the onion architecture pattern. In this view, we retain the layered approach, but rather than thinking of it as a stack, think of it as a layered onion, with the Domain in the centre and the interactions with everything outside the application on the edges.
The original DDD books didn't specifically reference this, but it has become a very common pattern for implementing DDD systems.
It is also known as the Ports and Adaptor pattern, or the Hexagonal Architecture.
The idea is that it models dependencies in terms of 'knowing about' in terms of an onion - outer layers know about inner layers but inner layers don't know about outer layers.
But it models delegation of application flow in terms of movement across the onion - from one side of the onion to the other.
To be more specific:
The outer layer (also known as a 'primary adaptor') is where the request enters the system. The adaptor has the responsibility for handling a specific API presentation (e.g. a REST api) and transforming it into a request to the Application services layer - the next layer in. This is often represented as the top-left of the onion.
The Application services layer represents a 'use case' of the application. Typically a method would use a repository interface to retrieve an instance of an aggregate, then delegate to methods on the aggregate root to execute the business logic that involves changing the state of the aggregate as required for the use case. The application services layer, then uses another interface to ask the infrastructure layer to 'save' changes (often using a unit of work abstraction)
Here we have the application layer delegating control flow to an 'outer layer' of the onion (otherwise known as 'secondary adaptors'). This is often represented as the bottom-right of the onion, and is analogous to the 'infrastructure layer' in your description.
And this is where IoC comes in. Because we have an inner layer delegating to an outer layer, it is only possible because the outer layer has implemented an interface defined in an inner layer (which it can do because it knows about the inner layer). However, the IoC container injects the actual concrete implementation which effectively permits the inner layer to delegate control to the outer layer without being dependent on it.
In this conceptualisation, the request has flowed from the top left to the bottom right without the inner layers knowing anything about the outer layers.
There are 2 options here
1) Work with DAO objects. then the infrastructure layer only needs to know about those DAO objects. Especially if you use Entity framework or something similar then this isn't a bad strategy to follow. You do gain some overhead from mapping but you can use an Automapper for that.
2) live with the fact that the infrastructure knows about your DDD model. But since everything in DDD revolves around your domain model this isn't that bad of a tradeoff. (Especially if your domain model is very well understood and thus doesn't change radically). Be very careful though not to let your domain model be influenced because of database design. It should always be the database who follows, never the domain model where you don't make a certain change because it's hard to migrate in the database.
Persistence Logic usually belongs in the Infrastructure Layer, which is in the outer layer of the onion, and since the outer layers of onions depend on the inner layers, and the Domain Layer is in the center, then yes the Infrastructure Layer depends on the Domain Layer.
In DDD scope, the Persistence Logic should belong to Infrastrure Layer, as detailed persistence implementations are not the concern of Domain Layer.
However, as we think of the architecture of our projects differently, Infrasture Layer could either be dependent on Domain Layer or being depended on by it.
In a traditional layered architecture,
A linear dependency is suggested all the way passed from Presentation Layer, via Application Layer, Domain Layer to Infrastructure Layer.
In this case Infrasture Layer is deemed as an upperstream where both the interfaces and implementations of Persistence Logic are defined.
Domain Layer, as a downstream user, would follow the interface provided by Infrastructure Layer to fetch the entities, convert into domain objects, and then do the domain logic.
Typical codes in java:
// package com.xxxx.product.application
class ProductOrderApp {
private ProductRepository repository;
void orderOneProduct(String userCode, String productCode) {
ProductEntity enitity = repository.getOneByProductCode(productCode);
// 1. convert ProductEntity to Product Object
// 2. pass Product Object to Domain layer to do some logic
...
}
}
// package com.xxxx.product.domain
class Product { ... }
// package com.xxxx.product.infrastructure
interface ProductRepository {
// does not depend on any domain concepts
ProductEntity getOneByProductCode(String code);
}
class ProductRepositoryImpl implements ProductRepository {
#Override
ProductEntity getOneByProductCode(String code) {
ProductEntity entity = ... // get entity from some database
return entity;
}
}
In an onion architecture(as well explained in top answers),
Domain Layer is considered the upperstream, and all other downstream layers should follow the interfaces provided by Domain Layer.
Thus Infrastrure Layer depends on Domain Layer as in it implements the interfaces defined by Domain Layer. Domain Layer does not depend on Infrastructure Layer.
Typical codes in java:
// package com.xxxx.product.domain
class Product { ... }
interface ProductRepository {
// other Domain Logic can easily call this method as it uses Domain Objects for interection
Product getOneByProductCode(ProductCode code);
}
// package com.xxxx.product.infrastructure
class ProductRepositoryImpl implements ProductRepository {
#Override
Product getOneByProductCode(ProductCode code) {
ProductEntity entity = ... // get entity from some database
// persistence logic knows domain objects and do the convertion here
return convertToProduct(entity); // convert to domain objects
}
}
I have the following layers currently in my application:
API
AppService Layer
Domain Model
Repository
The lower (2) layers (domain and repository) offer almost total reuse across business needs so I thought of exposing at least my domain model as a service, possibly a WCF service. Basically the domain entity data, behavior, and persistance are reusable and I need a way to centrally expose this.
I have read the following (Sharing domain model with WCF service) and ones similar that indicate for good reason why not to expose domain entities directly via WCF. Most of the examples indicate to create data contracts to expose domain data and then have mapping mechnisms to map between the domain and DTO (Data Contract) data. So far so good.
If I have a method in my domain layer like below, how do I expose it via the new WCF service? I thought I would only expose DTOs and therefore how do I also expose the shared/common domain behavior I want to reuse across processes?
public int ProcessSomeRule(string param1, string param2)
If the answer is to create a method on the WCF service that acts as a proxy still not exposing the ProcessSomeRule method directly, I'm cool with that but that spawns another question. The purpose of this abstraction and creating a method on the WCF service named for example ProcessSomeRuleWCF(string,string) that just turns around internally and calls the domain method seems to still be coupled and not offer a pure abstraction. It will still be sensitive to signature changes.
I read that by not exposing the methods directly, we can make changes internally without having to modify the contract interface. OK, this sounds great by definition, but if my internal method needs an additional parameter and now has the signature `ProcessSomeRule(string, string, string), guess what? My contract interface method will now break because it's missing the 3rd parameter, so my interface has to change. Not sure how to do this and still make the abstraction worthwhile?
My repository in the same manner is generic and can be used across processes and I want to reuse this layer too. Currently my repository (UoW) Interface is injected into my AppService layer, so I have no idea how this would work if Repository layer was a WCF service.
Question: How do I expose the shared behavior of the domain and repository layers and what would the names of these new layers be called? Is the new layer exposing the domain named 'Domain Service' and sit between 'AppService' and 'DomainModel'?
Lastly, if I'm on the wrong path with any of this feel free to guide me back. Thanks!
How do I expose the shared behavior of the domain and repository
layers and what would the names of these new layers be called?
In the context of a hexagonal (ports & adapters) architecture, your domain layer would be encapsulated by application services thereby defining the core of your application. Application services implement use cases by delegating to aggregates and domain services and orchestrating access to repositories and infrastructural services. Next, you can "adapt" your application to infrastructure. Having a repository implement an repository interface declared in the domain layer is an example of this. The repository implementation serves as an adapter between the domain and the outside world. Similarly for WCF services, usually called open-host services in DDD, they adapt your application to a transport infrastructure. The WCF service, or ASP.NET WebAPI service, would be a relatively thin layer that delegates to application services. Again, the purpose of this layer is only to serve as an adapter. This layer does own the contract that it exposes publicly. In DDD this is referred to as the published language. In WCF, for example, it would be defined via DataContract and DataMember attributes. These contracts are how external systems will access your domain. Having a buffer between published contracts and the internal domain is important because they will likely change at different rates and have different consumer requirements.
Is the new layer exposing the domain named 'Domain Service' and sit
between 'AppService' and 'DomainModel'?
No, a domain service is part of the domain layer itself, sitting along with entities, aggregates and value objects.
I think to expose domain object as service is not difficult. but system is really combination service and UI. UI access service, and service can be implemented on different ways: DDD or database-central . so it maybe not a good idea to tell the service caller how we implement our business logic.
Can anyone help, I have 2 applications and they are nearly identical. they have a completely different presentation layer (web) and the business logic and database are nearly identical. Basically one app has some things that the other doesn't.
so i was wondering if i can do the following without breaking any rules etc
Each app has their own presentation layer.
Each app has their own service layer.
Each app has their own data access layer.
Each app shares another service layer.
Hence the shared service layer both apps can access as the business logic is identical, but they both have another service layer which has 5 or 6 methods in there which are specific to that actual app
The data access layer - I don't see anyway of sharing this as there are 2 different db's with entity framework hence its got the EDM in there so its not dynamic - and the tables differ slightly.
I could use IOC on the shared data access layer I suppose
Would anyone help or comment weather this is good practise.. What I didn't want to do is have only a separate service layer when a lot of it is shared..
Is this a good idea? Maybe i have got it wrong, is there a better way?
As Arjen de Blok said, your business entities should use a repository, a repository is an object with methods to query, update or insert domain entities.
The interface which describes your repository belongs to your domain layer, but the implementation belongs to the infrastructure layer (DAL).
You can share the domain and infrastructure libraries between your two projects. If these two projects should retrieves their data through a shared web service or a shared database, you just have to choose (i.e inject) the correct implementation of your repository (your domain objects know only about the interface of your repository, not about the concrete type)
If the business logic is mostly identical then you should focus to this first.
If you want to do DDD then you should identify your entities and (business) services first and place these in a single library.
These entities and business services should talk to your infrastructure layer (your DAL).
If the infrastructure layer is very different in these two applications then try to work with interfaces. So wrap the intfrastructure layer with interfaces and only talk from the domain layer to your infrastructure layer via these interfaces.
To bind your business logic to your infrastructure's implementation you could use IoC/DI.
You could unify the DAL with a Repository interface. You could then implement the interface across projects. You will probably end up with a EF Repository base class as well. You could apply a similar technique to the services, leverage a common interface and then specialize the service implementations.