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..
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 creating my first stand alone desktop WPF application using Entity Framework. Do I need a WCF layer to access database? Is this a bad practise if I just call DBContext directly from ViewModels?
TL; DR
The short answer is: it depends!
The long answer
It depends on your use case you need to implement. If you need to add another layer of abstraction -the WCF layer- to hide your OR/M away you can do it. However if your strategy is easy enough like a standalone WPF application I wouldn't bother making a WCF layer. You can simply access the IDBContext in your application, but keep in mind to not tightly couple your viewmodels with EF.
Always worth try keeping the concerns separate!
And these concerns are:
Data- or Persistence (EF) Models that are used to map your database to your OO models
ViewModels that are supporting your Views with data to show
Mapping of your Persistence and ViewModels
This way you can achieve a lightweight setup that aims for better separation and better testing ability.
Further Extensibility
Later on your development path, when you arrive at a point where you need to add an infrastructural concern like a WCF layer which could serve as a public API -or an entry point- to your shared database access, you can easily add it as a new project, put its classes behind interfaces (these are the only ones you will have as reference added to your WPF project) and let this project have the exact implementations.
Just recently, our application expanded to support 4 different UIs.
We have business logic that is integrated into our data layer.
We do not have a physical business layer that separates our UI from our data layer. Often times in the UI, the database is being called directly. Obviously, this causes problems.
My question is, should I implement a physical business layer, and over time, migrate the existing logic in the data layer to the new business layer. Or should I keep the business layer in the same dll as the data layer?
What are your thoughts on adding a business layer to an application without one?
You should definitely introduce some separation of concerns by doing things in different layers. Directly referencing the database from the UI is not sound architecture and will lead to tight coupling and difficulties in maintenance and extensibility later on.
The best time to do this separation is at the beginning, when there are no costs of refactoring involved, but if you expect the product to be expanding, doing it now will also bring significant benefits in terms of extensibility and maintenance.
Here is an approach for introducing a service layer that stays on top of the model and exposes the same functionality that gets reused by multiple UIs and gateways. This layer helps you unify your business logic across all your interfaces and all exposed services (if you ever need to expose functionality/data) which is very important - you definitely don't want to create and change things in multiple places when you can do it in a single place and guarantee 100% consistency.
Regarding the part of the question about physically implementing the logic in a different dll, I think it is not that important and necessary - you will have the most important benefits of using separate layers without having to physically separate them. Maybe it will make sense if you plan on scaling up and you think that having multiple instances of the same layer on multiple machines will solve a problem of yours (e.g. using some king of load balancing approach for) but otherwise I don't think it is mandatory to do it this way.
Good luck!
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 will try to explain in as much detail as possible. There may be similar questions here on SO and I've gone through all of those but none of those have what I needed.
So, I'm starting out with a large scale C# MVC5 based Web Project and I want to organize everything in as much decoupled way as possible. For the database part I'm going to use Data Access ORM from Telerik (Previously known as Open Access) because I will be using MySQL for my project.
So far I have organized everything as below. I have defined solution level folders to divide the projects because I think there may be a possibility to have more projects in one layer in future.
**Solution**: td
- Business (Folder)
-- td.core (Project) (Contains Services and ViewModels)
-- td.interfaces (Project)
- Data (Folder)
-- td.data (Project) (Contains Database Models i.e. Telerik, Repository, Context Factory and Unit of Work class)
- Presentation (Folder)
-- td.ui (Project) (MVC5 Project, also Implemented IoC here)
- Shared (Folder)
-- td.common (Project)
Generally, when you bind models in your MVC project, if you have just one project in your solution, it works pretty easily without an issue.
i.e. in a MVC Controller
var obj = new TempClass();
return View(obj.getAllUsers());
and then in the corresponding view you use this at the top
#model (model type here)
When I separate all these layers in their own projects as mentioned above. The data layer would be the one directly communicating with the database hence I will generate the Telerik Data Access rlinq schema in my Data node where it will also generate the classes for the tables in my database (Default config)
Now, from the setup above, from the controller I'm supposed to call the Business layer to fetch the data and which will communicate with the Data node.
The question is that in the controller and in the view I will need the data types / references of the model I'm binding to. So, should I keep my automatically generated classes still in the Data node or can I move ONLY the generated classes to the Shared Node and then use those for the binding in the Controller/View? Which one is going to be a good practice? as I don't want to reference the Data nodes directly in the controller otherwise there is no point in separating everything like above.
Another quick question. I would be integrating so many third party APIs via REST/SOAP. In which layer should these best fit?
If anyone has any other Architectural suggestion or something that I'm missing here, please do suggest.
Thanks in advance everyone.
UPDATE!!!
Please see my updated architecture above.
Here's what I did so far.
I have added Repositories, Services and IoC.
In my Global.asax, I'm initializing the IoC which configures the Services etc for me.
My controller has an overloaded constructor now having the service from the business layer as the parameter.
Controller calls the service to get the data and the service calls the repository for it.
I have followed the generic repository path instead of creating repositories manually for each type
For 3rd party APIs, I will use the data layer and business later won't know where the data came from. It just needs to ask what it needs.
All this was made easier with the help of a dedicated Interfaces project which is being referenced from both the Business and Data layers when needed. Because as both want to implement abc interface I cannot declare it in either Business or Data layer since there would be circular referencing then which prevents me to reference both (Business/Data) projects to each other.
So, with the help of above changes, I can easily do what I want now and Everything is working perfectly as I want. Now the last question I have is
Is there any flaw in this architecture?
For a domain-centric architecture where it's easy to add another type of UI or change persistence technology and where business classes are easily testable in isolation, here's what I'd do :
Business layer with no dependencies. Defines business types and operations.
Data layer with data access objects/repositories that map from database to business types. You can also put your third party API accessors and adapters here. Depends on Business layer where repository interfaces are declared.
No Shared layer. Business types are the basic "currency" that flows through your system.
UI layer depending on the data access interfaces declared in the Business, but not on the Data layer. To decouple UI further, you can introduce an additional UI-agnostic Application layer.
You can read more about this at Onion Architecture or Hexagonal Architecture.
As it is, your architecture is pretty much data-driven (or Telerik Data driven) since the business and UI layers are tightly coupled to the Telerik schema. There's nothing wrong with that, but as I said in my comment, it enables other things such as quick development from an existing database schema, over full domain decoupling, framework agnosticism and testability.
Whether your Telerik generated model lives in the Data or Shared module makes little difference in that scenario IMO. It is still the reference model throughout your application and your controllers will be coupled to it anyway. The only thing I would advise against is moving the generated files manually - if it can be automated all the way, definitely do it or don't move the files at all.
I'm nether an expert for your special technologies, nor would I regard this as the ultimate answer, but I give you some hint's of the possibilities you may have (depending on your technologies):
Business should have exclusive access to data
Currently I don't really get, why your controller and view need access to any data-base related stuff at all? Shouldn't your business layer handle all of that and hide it from controller and view? But let's assume it's necessary for some reason.
Ways to split the data layer
You shouldn't move generated classes manually. You could change your generation-settings, to generate them elsewhere partially. But manually cherry-picking and moving them, results in an architecture which is hard to maintain.
The cleaner solution would be, if you can change the visibility of your classes. Can you generate classes with project or folder visibility instead? Or can you only export defined packages or classes in the project settings?
A workaround which requires more maintenance is the local extension. You could create new classes in your shared folder, which derive from the data layer classes.
Stucturing external APIs
Give them one or more own projects, so they are easier to change later. I know approaches where you have one main folder for each API. This makes each of them easy to change, but clutters your workspace. The important project will only be 4 out of 1000 projects. I normally prefer one folder containing all APIs. Thus the APIs are slightly harder to change, but your workspace stays clean. Your decision depends on two facts: how often do you change, add, remove or just study the APIs. And does your IDE provide a way to "hide" folders/projects from your workspace.
Hope this helps a little :)