I have an application with the following layers:
Web API - Provides an access point for external calls to enter the application.
Infrastructure - Provides repositories which allows access to the database.
Service layer - Responsible for different use cases (e.g. 'Add item to cart').
Domain - Contains domain objects with business logic.
You can see how they reference each other, in the drawing below.
I want to add a typed http client, to fetch certain information from an external API.
In what layer/project, should the typed client be created?
My reasoning so far:
The first thing that came to me, was the infrastructure project. But since the infrastructure points towards the service layer (which needs the data from the API), that means introducing an interface on top of the API. This also means that the response object, from the typed client, must be defined in the infrastructure layer (this is where it starts to get messy).
If that is the case, that means that one of the two following must be true:
A) The service layer gets to depend on the API response directly or
B) The typed client must map the response to an object defined in the service layer.
This means that I can either introduce a dependency, in which case I might as well put it all in the service layer. Or I make the typed client more than a typed client, which really feels like a code smell.
Some thoughts about your layering
Based on the your definitions:
Infrastructure - Provides repositories which allows access to the database.
Service layer - Responsible for different use cases (e.g. 'Add item to cart').
none of these have the responsibility to communicate with 1st and/or 3rd party services. It seems like your Infrastructure layer is a data access layer (in other traditional layered architecture naming), whereas the Service layer is the business logic layer.
Where to place
After this little detour let's focus on your question where to place the typed client(s). You can reason about that either of the layers can be good home of the typed clients. I would suggest to make a decision based on the followings:
If you have multiple independent typed clients and most of your business logic calls only one of them OR if the business logic utilizes multiple typed clients but only to aggregate their responses
Then place it where it feels right, It does not matter whether they are defined at the bottom layer or in the middle
If you have business processes / workflows which are typically utilizing multiple typed clients in a specific order OR in a pipeline fashion (one client's response is the input for the other client's request)
Then define them in the same layer as the process/workflow reside, because they are interconnected and most probably you want to avoid that situation that an other layer can use them in the wrong order or just partially
I hope my guidance could be applied for your particular case as well :)
Related
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
I am fairly new to Arhitecture Designs in OOP ( I'm coming from programming robotics, so it's a bit of a struggle ). The team that I am taking part of is creating a rather large application and the Leading Project Manager presented us with the requirements and in that requirements we must use Layers in creating the modules. The technologies we are using are C# WinForms and Oracle for the data-store.
My module consists of User Administration and I have tried to separate the logic from the implementation, so I have the following arhitecture:
Business Layer
Data Layer
Presentation Layer
I am using the Repository Pattern and IoC with EF and everything looks and works fine but now my boss has told me that I need to seperate the Presentation Layer from the Data Layer completely. The problem consists that from the Presentation Layer I use IoC and if I want to create a User object for example I do the following:
_userRepo.InsertNewUser(new User { props here } ); .
So this is incorrect because I access the DAL directly. My boss has told me that I need another layer that isolates these kind of calls and implement Business Rules ( ?! )
I have searched and researched the internet and I found nothing of help ( mainly because everything is filtered here at work ).
I think my boss wants something of a Domain Layer / Service Layer but I have no ideea how to implement it in the current design. I can post the project without any problem, any sensitive data will be removed from the code.
Any help would be appreciated.
I'm posting this as an answer, even though it might be opinion-based, and even though I cannot read your boss's mind :-)
Fundamentally, I think what your boss wants is to reduce dependencies between all layers. The architectural pattern you choose to do this, depends on the application at hand. What you described looks like a three-tier architecture. Let us briefly recall how a three-tier architecture looks like, and how things are supposed to work:
The presentation tier displays information and serves as a boundary to the user.
The application tier (or business logic) controls the functionality of the application. In particular it processes data and distributes it to the other tiers.
The data tier, containing the data access layer (DAL), stores or retrieves data. It should keep your application independent from the storage solution at hand. It will usually work with data access objects (DAOs).
There are different schools of thought when it comes to which tier should know which other tiers. But from what I read, I think you are supposed to promote the business logic as kind of mediator. This means, the business logic knows the presentation tier and the data tier, but the other tiers do not know each other. I try to clarify this by going through two sample scenarios:
A. Display an existing user
Business logic asks data tier for a specific User DAO, e.g. the one corresponding to id==123.
Data tier returns the User object.
Business logic reads the values stored in the User object and sets the values in the presentation tier accordingly, e.g. the firstName, lastName etc. It does not forward the User itself, only the contained values.
B. Create a new user
Presentation tier collects all values necessary to create the new user.
When "submitting", these values arrive in the business logic (e.g. IoC).
The business logic tells the data tier to create a new User object with the values it got from the presentation tier.
The data tier creates and stores the object.
What creates dependencies between the different tiers are the DAOs. I.e. if your presentation tier was to instantiate a User object, it would need to import a class belonging to the DAL (which is not what your boss wants).
So what you can do instead is to leave all the communication between presentation tier and data tier to the business logic.
As an alternative in scenario B, you can also make the business logic create the User, so that your DAL methods get simpler.
As I said in the beginning, there is no one way of doing it. If you need more specific information or have further questions, don't hesitate to ask.
Thank you for the all the answers and guidelines so far.
I think what my boss wants ( I didn't get reach of him because he is in DE and I am in RO ) is to fully separate the concerns between layers, something like the Model-View-Presentation Pattern, so that the Presentation Layer ( UI ) will not directly access the Data Layer. It can access it but through an intermediary layer.
I added a Domain/Service Layer to the application and now the Presentation Layer calls the Service Layer and the Service Layer calls the Business Layer and creates the user / group objects.
The following thing is, he said something about Business Rules that this Domain Layer should include. What are these Business Rules, an example would be appreciated?
The only think I came up for Business Rules were some Validation Rules, suchs as: Before you call: return userRepository.GetUserName( User user ) check the User object passed as a parameter that is not null, or similar checks.
So now the "mechanics" are:
In the Presentation Layer I inject into the constructor the IService object and then I use the IService object to call a method for example "GetAllUsers()".
The IService per-se is in fact a "copy" of the User Object's Repository class so when the IService object calls "GetAllUsers()", there is a exact named method in the IService classes that will do: "return _userRepository.GetAllUsers()" - in this way the Presentation Layer calls object specific methods through an Intermediary Layer and this Intermediary Layer will have direct access to certain methods of the DL.
I hope I made my self as clearly as possible. I will provide screenshots if necessary.
As I stated before, I'm just beggining to have experience with Arhitecture Design, since in the robotic fields there is no such thing, so please do not throw so many rocks :D
I've been in the process of re-writing the back-end for a web site and have been moving it towards a three-tiered architecture.
My intention is to structure it so:
Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)
My issue is with the placement of the DTO's within this structure. I'll need to use DTO's to move data between the business layer and the WCF service and from the WCF service to the consuming web site.
During my research on here I've read some excellent discussions though I've been left scratching my head a bit:
Davide Piras makes some great points in this post and if I were to follow this design then I'd declare interfaces for the POCOs in a separate project. These would then be implemented by tiers (1) and (2). Whilst I like the use of interfaces it does seem like I'd be making more work for myself by declaring POCOs in (1) and (2) and then copying their data back and forth using something like AutoMapper.
This post uses a system where a business objects project is created which would be referenced by all tiers. This seems to be simplier than the other solution and seems to lead me to a solution that would be
Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)
^ ^ ^
| | |
[ -- Business Objects Referenced here --]
My question is this: is there a code smell from sharing the business objects across three layers of the solution or are the two methods I've listed above just two different ways of cracking the same nut?
Let's think of your UI (website) and service (WCF + BL + DAL) as two distinct entities.
If you have 100% control over both, you should choose approach #2 since it will avoid translation between WCF proxy objects and your business objects in the UI layer.
Else, you are better off with approach #1 since one of the entities is kind of a 'black box' and is subject to change by external stakeholders. So, it's safer to maintain an internal set of business objects. This will need translation between your business objects and the WCF proxy objects (through Extension methods or a translator framework).
Now, not exactly sure of your UI layer complexity or its implementation (MVC, WebForms, etc.), so you may or may not need View specific objects (lighter for data-binding, faster to serialize to JSON, etc.), let's call this object as the Model.
If you don't need a distinct UI specific Model, suggest to mark your business objects as DataContract (in the context of WCF) and use them across layers. Don't forget to explicitly mark entities as Serializable if you are invoking WCF via the web ($.ajax).
Else, use DataContract in the service and a translator to convert DataContract to Model in the UI layer. A Service Adapter is a good fit here - it sits in the UI layer and is responsible for consuming the WCF service and translating between DataContract and Model. You may use a Service Proxy in the UI layer, which is a wrapper over your WCF service and is consumable over the web.
Lastly, aren't you are missing a reference to the Business Objects in your Data Layer? I believe you will populate your Business Objects from the data-store in the Data Layer itself.
I would say that it often depends on the complexity of the project you're building. For smaller projects that I've built, I shared my 'entities' (they were just simple DTOs, serializable data buckets with getters and setters) across the layers and didn't care too much about this. On of the biggest downsides was that the logic got scattered across the project (not only in the 'Business Layer') and had a procedural-style all around. This really seems like the Anemic Domain Model, but the complexity didn't creep in as the project didn't grow too much. Entity Framework has some templates you can build you entities off of as such (if I'm not mistaken they're called self tracking entities?).
For medium/bigger projects, I wouldn't use this approach and would keep entities and DTOs separately as they would serve different roles. The DTOs might have a totally different shape than your entities and trying to share them between the tiers/layers would be often smelly.
Several "parts" (a WinForms app for exmaple) of my project use a DAL that I coded based on L2SQL.
I'd like to throw in several WebApps into the mix, but the issue is that the DAL "offers" much more data than the WebApps need. Way more.
Would it be OK if I wrapped the data that the websites need within a web-service, and instead of the website connecting directly to the DAL it would go through the web-service which in turn would access the DAL?
I feel like that would add a lot of overhead, but on the other hand, I definitely don't like the feeling of knowing that the WebApps have the "capabilities" of accessing much more data than they actually need.
Any input would be greatly appreciated.
Thank you very much for the help.
You can either create web services, or add a repository layer that presents only the data that your applications require. A repository has the additional benefit of being a decoupling layer, making it easier to unit test your application (by providing a mock repository).
If you plan on eventually creating different frontends (say, a web UI and a WPF or Silverlight UI), then web services make a lot of sense, since they provide a common data foundation to build on, and can be accessed across tiers.
If your data access layer were pulling all data as IQueryable, then you would be able to query your DAL and drill down your db calls with more precision.
See the very brief blog entry I wrote on Repository and Service layers using Linq to SQL. My article is built around MVC but the concept of Repository and Service layers would work just fine with WebForms, WinForms, Web Services, etc.
Again, the key here is to have your Repository or your Dal return an object AsQueryable whereby you wait until the last possible moment to actually commit to requesting data.
Your structure would look something like this
Domain Layer
Repository Layer (IQueryable)
Service layer for Web App
Website
Service layer for Desktop App
Desktop App
Service layer for Web Services
Web Service
Inside your Service layer is where you customize the specific calls based on the application your developing for. This allows for greater security and configuration on a per-app basis while maintaining a complete repository that doesn't need to be modified until you swap out your ORM (if you ever decide you need to swap out your ORM)
There is nothing inherently wrong with having more than you need in this case. The entire .NET 4 Client Profile contains over 50MB of assemblies, classes, etc. I might use 5% of it in my entire career. That doesn't mean I don't appreciate having all of it available in case I need it.
If you plan to provide the DAL to developers that should not have access to portions of the data, write a wrapper or derive a new DAL. I would avoid the services route unless you're confident you can accommodate for the overhead.
Sounds like you are on the right track. If many applications are going to use the this data you gain a few advantages by having services with DTOs.
If the domain model changes, just the mapping to the DTO needs to change. You can isolate the consuming application from these changes.
Less data over the wire
You can isolate you applications from the implementation of the DAL.
You can expose different services (maybe different DTOs) for different applications if it is necessary to restrict what parts of the object model should be exposed.
I am wondering about the long term advantages (if any) of layering my web app by separating my business logic and data from my web forms. (ie a form, business logic, data not in the same file, but each in it's own class in another folder by itself or combined with other like classes). I like to make everything as modular as possible and to do so efficiently it seems that keeping all the code in one file - in the web form makes organization and reuse much easier. There are certain functions that are used across the site like managing connections that would be in their own classes and files. I am pretty new to c#, sorry if I am messing up the terminology.
Thanks
The separation of code into layers brings benefits beyond just C# language.
If your data access code is kept in a separate layer, it will be easy to adjust it to work with a different database. Database-specific code will be encapsulated in this layer while clients will work with database-agnostic interfaces. Therefore changes here will not affect the business layer implementation.
If your business logic is kept in one place, you will be able to offer its services to other applications, for example, to serve requests made via web services.
If your code is clean and well structured, the maintenance efforts will be kept lower. Whenever you need to change something, you'll know where to find the responsible code, what to change and how to assure the change will not affect the rest of the code.
As for ASP.NET, not following the separation of concerns has caused many projects to turn into a giant code blurb - presentation code performs business decisions, code-behind talks directly to the database whenever no suitable business method exists, database gets written to from many places, dataflow is following multiple paths which are difficult to trace, changes in one path not introduced to all of them will break integrity and cause data corruption => Result? Almost unmaintainable code black box where any change requires more and more effort until it stalls - project is "finished". Technical bankruptcy.
We usually layer our application as follows (each of the layer is in a separate project of the solution and consequently in a separate Dll:
What I would always go for (first) is to have a layered application
Presentation Layer (JUST UI and databinding logic)
Interface Layer to
the Business Layer (defining the
contracts for accessing the BL)
Business Layer implementation (the
actual logic, data validation etc...)
Interface Layer to the Data Access
Layer (defining the contracts for
accessing the DAL)
Data Access Layer
implementation
You can then use some factory for retrieving the corresponding objects. I would take a look at some library, possibly using dependency injection like Spring.Net or Microsoft Unity from the MS patterns and practices.
The advantages are the following:
separation of logic where it belongs to
no business logic in the UI (developers have to pay attention to this)
all of your applications look the same and consequently developers knowing this architecture will immediately know where to search for the corresponding logic
exchangeable DAL. The interfaces define the contracts for accessing the corresponding layer.
Unit testing becomes easier, just focusing on the BL logic and DAL
Your application could have many entry points (web interface, Winforms client, webservice). All of them can reference the same business logic (and DAL).
...
Just could not live without that..