I've been using MVC frameworks for a short while now and I really like how the concerns are separated out. I've got into a bad habit of letting the controllers do quite a bit of work. So I'm really looking for some advice.
When I first started using MVC I quite often had the controller doing manipulation on the models after database work had been done. I knew this was bad so moved that work into the models. However I'm not happy with that as I want my models to be very learn.
I've done a bit of reading and I see that people are keeping their controllers and models lean by having a service layer, which I like the look of.
I'm just trying to understand how a service layer and repository should all work together. Here are my assumptions, can you please let me know if this is a good way of working?
The controller can call the repository directly if no manipulation needs to be done on the data and as such a service layer does not need to get involved
Once any work needs to be done to data (business logic) then this should be done in the service layer and the controller will make a simple call to the service layer as and when required
Once a service has done it's business logic it will then use the repository as necessary (if data needs to be persisted).
Models ideally should be kept lean, ideally actings as nothing more than DTOs
Validation of data will be done within the models (using MonoRail validation attributes). I appreciate not even one likes polluting their models with lots of attributes, but that is a different discussion. I like the benefit of MonoRail's validation attributes for the automatic jQuery validation in the UI.
I'm trying to turn all my code around to the single responsibility principle, hence trying to sort out my coding practices.
Thanks
First, there is no set of rules that's going to work in every situation. How you model you're application depends a lot on the type and complexity of the project. Having said that, here are some ideas:
Nothing wrong with calling the repository from a controller. Just make sure the controller does not contain business logic.
The service takes care of (some) business logic and uses other services to do so. The repository is a type of service, there's nothing wrong with calling it from a service.
The model should contain business logic, actually you should always try to put it in the model first. If you need external data to perform that business logic (from another model or from the repository) then you should create a service.
Nothing wrong with validation in the models. Using attributes or not is a question of taste (if you like it then it's good). Move the validation outside of the model if it gets too complex (create a external set of rules).
Most important, do what feels right (that's usually the right answer).
This video gives great insight into how to organize your asp.net MVC solution and addressing separation of concerns, and better testability. Hopefully it will help someone else also. I learned some good stuff from it.
Ian Cooper has just written a blog post called The Fat Controller on just this subject.
Related
I want to know the right concept about it. If I have a MVC application with Repository Pattern, where the BL should be?
Should it be inside the Model? Model should have all the business
logic before call the unitofwork to insert or not the data into
database?
Should it be in the controller? Before call the model?
Should I have a service layer to do the business logic and decide if
I should call the Model to call the UnitOfWork to save the data?
A good explanation will help a lot too.
The short answer - it depends. If it's a fairly complex or sizable application, I like to create a service layer project with the repositories as dependencies. If it's a small application, I'll put the logic in the controller. In my opinion, if it takes more time and effort to create the service layer than it would be to create the application (i.e. one or two controllers), then it doesn't make sense to me to go that route. You also need to consider the likelihood that the application will grow. What might start small could grow into something much bigger and in that case, again, it might be more beneficial to create the separate service layer.
The third one... and then some.
Your application structure could look like this (each in different projects):
Data storage layer (e.g. SQL database)
ORM (e.g. NHibernate or Entity Framework)
Domain (including abstract repositories and entities)
Service layer (and optionally business)
MVC application (which has it's own models relating to the entities)
but there are many ways to go about this depending on the complexity and size of your application.
There is no "correct" answer to this question, it is primarily opinion-based. You can read about my opinion in the following project wiki:
https://github.com/danludwig/tripod/wiki/Why-Tripod%3F
https://github.com/danludwig/tripod/wiki/Dependency-and-Control-Inversion
https://github.com/danludwig/tripod/wiki/Tripod-101
https://github.com/danludwig/tripod/wiki/Testing,-Testing,-1-2-3
https://github.com/danludwig/tripod/wiki/Command-Query-Responsibility-Segregation-(CQRS)
Another piece of advice I would like to offer is never put any business logic in viewmodels or entities. These classes should not have methods, only properties to contain data. Separate your data from behavior. Use models for data, and other types for behavior (methods).
In my n-tier .Net Application I got next layers:
Data Access Layer (EF)
Business Layer (Validation & Business Logic)
Presentation Layers (1 MVC Controller and many API Controllers)
I found, that my Business Services only validate business objects, call CRUD DAO methods and return results to Api Controllers.
So, I doubt: may be Web Api Controllers should be used as Business Services?
Interesting, just answered a similar question...
So I woudn't do it I were you.
Here's just a few disadvatages of the approach from the top of my head:
Performance - a redundant HTTP roundtrip in Web MVC project.
Separation of concerns - most of the time the functionality provided
by API differs greatly form UI for the same project/application. You
might want to limit the API to a few methods with a strict contract.
In case you want Web API to be a layer between Web MVC and your DAL
you will have to expose all functionality you need for UI as well.
Also you might want to have different authorization and
authentication mechanisms. Very often API exceptions handling is
also different as well as input validation.
Maintanance - everytime you need to make a change required for UI
only you have to make sure it doesn't brake your API clients. Also
API versioning is a very important topic and mixing it with most UI
changes makes this process even more difficult.
Probably for now you application is not that complex but from the design perspective your solution is much more flexible now than it will be if you decide to put Web API between your UI and DAL layers.
N-Tier applications and multi-layer are not popular among the new wave of developers. Keep in mind, that just because something is not popular, among a group, does not mean that it does not have merit.
Pros of MVC:
Separation of Concerns
Unit Testing
Does a multi-layer MVC application using a Web.API have merit:
I know this will be met with some discontent and disagreement. However, my concern is that single purpose application developers are not giving consideration to enterprise development. Enterprise development, load balancing, manageable code maintenance, and true Separation of Concerns are only possible with multi-layer applications that can easily lend themselves to N-tier.
Many developers are operating in environments that demand that they design and implement data structures in SQL, create and maintain models and CRUD functionality, develop controllers and design good looking and friendly views. The MVC model utilizing Entity Framework makes this a manageable task for these small to moderate platform developers.
In the Enterprise, separating the Business and Data Access layers from the User Interface makes real good sense. Right now MVC is a popular and very functional platform for efficient and usable User Interface development. What will be the UI platform in ten years? Separating the UI from the other layers gives more life to the work spent developing the business logic. Not to mention, that it allows for accessing data on multiple platforms today.
Multi-layer MVC using Web.API has these advantages:
True Separation of Concerns
Supports Unit Testing
Makes the Business logic and Data Access logic more scalable and reusable than MVC alone.
Supports data processes without page refresh. (REST)
CONS:
- Does not easily support use of Entity Framework. (Which is not ready for the enterprise yet anyway)
You could have your code as part as your model, and that would even be considered as good separation of concerns since MVC is build for that.
But what my preferred thing to do is keep logic in a Business Layer of it's own. The reason for that is, I think, better separation of concerns. I like using IoC, so there might be different configurations that I route thought different running solutions. Or, I might have another UI/API/Project that uses the same logic layer.
As for the overhead, it has a little overhead, but I think worth the trouble comparing to the actual overhead in code it creates.
I agree with others here, looking into using strongly typed views, the controllers would only create an instance of the viewmodel and send it on to the view. The view model then is the intermediary to the data services layer. I personally create all my entities using EF in a different project just to separate function. The view model can either call EF directly or you can add another layer of pre-canned EF queries which the Viewmodel uses just to populate the view collections. This would look like this:
[View]-[Controller]-[Viewmodel]-[Optional repository and interface to EF]---[EF]
In the interface to EF you would catch all DB errors when trying to get information and post back to the view according to your design.
The beauty of strongly typed views is that they post back and forth from the View and can contain methods which you can call at will. Because they are a pseudo model for the view, they can also have properties specific to the view which may be used at the business layer. I pass view models around quite a bit were warranted. (After all they are just a pointer)...
You can implement business logic/validation/calucations in the actual model/entity classes rather than ApiControllers, otherwise you will end up with so much code in your controller which is not really a good thing.
Also you can use DataAnnotations Attributes to perform your validation which sits outside of your controller. for.e.g. http://msdn.microsoft.com/en-us/library/ee256141(v=vs.100).aspx
Currently I have a solution whose hierarchy looks like this.
-GUI
-ENTITIES
-DATA
-BLL
-ENTITIES
-DATA
-ENTITIES
1) Is that the right way to lay it out. I'm removing the DATA reference from GUI currently (just legacy code that I'm moving to the BLL)
2) Is there any way for ENTITIES to call a method from the BLL or DATA? Like in Entities.Order have Order.GetNextOrderID() that calls a method from DATA?
1) Is that the right way to lay it out. I'm removing the DATA
reference from GUI currently (just legacy code that I'm moving to the
BLL)
This is an extended subject and it is scenario dependant.
Picture a sistem with componentization, integration with other systems and protocols, native code, multiple client protocols, mobile, test, etc. There would be a lot of layers and multiple Solutions would be needed. Same principle apply for different platforms.
There are a lot of criteria you would have to consider, so the answer is: it depends.
But I guess for what you are doing it fits well.
2) Is there any way for ENTITIES to call a method from the BLL or
DATA? Like in Entities.Order have Order.GetNextOrderID() that calls a
method from DATA?
No, you will get cyclic dependency error. A single module would do it tho, but I wouldnt recommend it.
Also, if you are going to define validation in the entities, make sure your design will not allow for duplication in services (bll) or data. This can go out of control if you do not have a good team or pair revision etc.
The main purpose of the layers is to give it specific responsabilites. If you have well defined responsabilities to your layers you should be fine.
I will re-iterate my comment for question 1.
Is that the right way to lay it out.
The "right way" is project dependant.
Is there any way for ENTITIES to call a method from the BLL or DATA? Like in Entities.Order have Order.GetNextOrderID() that calls a method from DATA?
Not with your current setup.. you'll get a circular dependency. You've become confused between a more DDD-approach (which is what you're going for.. nice!) and an Anaemic Domain Model where the logic sits outside of the entities.
You should choose where the bulk of your logic will sit and work from there. For the DDD approach you're asking about, the Entities project will contain 90% of your logic, and it will have a dependency on the "BLL" project for any other "services" the entities may require.
The flipside for the Anaemic Domain Model is that you have a service in the BLL that loads everything it needs and does all of the operations in the actual service. Your entities then become nothing more than POCOs.
Well a good design would be to keep the Data layer separate from both the GUI and BLL. So that each layer can perform a single task i.e GUI should only concern about the User Interface, controls and views. Business Logic Layer should only implement the Business rules and data layer should interact with your database. For your second question all you need to do is add a reference of your Data project to Entity project. Hope it helps you.
I've worked on several applications that try to adhere to DDD principles, I noticed that we end up with situations where there is duplication between the Service Layer and the repositories that feels like a code smell.
For most of the operations in the Service layer, it seems like it is a direct mapping to CRUD operations, GetAll, GetById, Create, Delete etc.. the flow of the architecure is within these lines: I have a controller calling a Service layer that calls a Repository that calls an ORM which talks to the Backend ..
So for example GetAll would exist in both SL and Repository. Now, if we have a change/business requirement that GetAll should ignore certain items, how am I supposed to do it, should I ignore these in the repository, or that's business logic that should go in the Service Layer? Wouldn't life be easier if we just had a Service Layer calling the ORM directly?
To Sum up: I understand the Service Layer could abstract some businees logic but when - in most cases - it is dealing with simple CRUD operations, wouldn't it be easier to just get rid of the Repository? But, what if the SL also contains some methods with complicated business logic, should these go through a repository? From good design perspective, Should I favor consistency and always go through repository or just keep it simple and only use a repository when it is not a simple one-to-one mapping to a CRUD operation.
PS: I realize there are seemingly similar questions but didn't find any satisfying answer
I noticed that we end up with situations where there is duplication
between the Service Layer and the repositories that feels like a code
smell.
It isn't a code smell since they do different things.
You should keep in mind that Domain or Application Services reside in a different layer than Repository implementations. Layers are there for a reason - objects in different layers don't have the same responsibilities and don't talk to the same neighbors. Repository implementations are tightly coupled to the means of persistence of your objects. They might generate SQL statements and talk to a relational database, they might talk to your ORM... the important thing is that they know about the way your objects are persisted, which is not true of Application Services.
If your Services layer was to call the ORM directly, it would really do 2 big things, breaking the Single Responsibility Principle. It would also be more difficult to change your ORM for another one or for a different means of persistence.
So for example GetAll would exist in both SL and Repository. Now, if
we have a change/business requirement that GetAll should ignore
certain items, how am I supposed to do it, should I ignore these in
the repository, or that's business logic that should go in the Service
Layer?
If GetAll() ignores certain items, I strongly suggest renaming it both in the Service and the Repository to reflect that, eg : GetAllAllowedToUser(), GetAllBut...(). Thus the contract of the method will be clear and you'll avoid misunderstandings about what it's supposed to return. Plus you'll be able to keep the original genuine GetAll() method which could still be of some use.
in most cases - it is dealing with simple CRUD operations, wouldn't it
be easier to just get rid of the Repository
IMHO, I wouldn't say to get rid of Repository. I would say that if you are doing CRUD you don't need DDD (at all). If you read Fowler's enterprise patterns or Evans they both say that DDD is only of use when you have domain logic that is significantly complex. CRUD is not complex and therefore no DDD needed.
What you describe is a code smell. But I don't think it is a smell with DDD. You are just seeing an over-engineered piece of code.
+1 for Dtryon, also:
Now, if we have a change/business requirement that GetAll should ignore certain item
Not directly related and I know you just used it as an example, but I've seen this exact thing. Please don't end up with methods called GetAll that do not get all. Keep GetAll, have it GetAll, then have GetAllLive, or GetAllAvailable or something like that as well which does what it says it does
Maybe the "Finder pattern"(dont know if this is the right term) can solve your problem. According to CQS(Command-Query-Separation) principle, (IMO,) query operations are not "business logic" at all. We can write some specific "Finder"s in the Infrastructure Layer to perform various queries and let all non-query operations(business logic) stay in the Service Layer, then on the client side we treat the finders the same as services.
Sorry for my language :-(.
Almost all examples of DDD within the Alt .NET community are applied to web development; what I would like to see are some examples of DDD applied in scenarios where the client handles most of the business logic and the server is simply a web service for CRUD using DTOs [1].
I'm currently working on a product that has an anemic domain model. Coming from years of web development, this sort of thing would typically make me cringe; however, I'm not sure how I would go about structuring this code around the DDD principles. In a web app, I have direct access to the database at the point where I handle business logic (implemented within my domain model, invoked by the controllers), which means that I can easily have a rich domain model and use an ORM for CRUD. But, in my current project, DTOs are the only sane way to transfer data. 80% of the business logic is implemented in View Models (this is a WPF app), the other 20% percent is located in stored procedures - and 100% of the DAL is hand written ADO .NET. There's really isn't a lot of business logic implemented within the web services, so there aren't any "entities" to be found in the solution - they're all DTOs.
How could I introduce DDD into this sort of client/server architecture? What sort of experiences have you had, and what approach did you take? What patterns would you suggest? I haven't had much time to grok CQRS, but something tells me it could related - is that so?
Foot notes
Perhaps this is the wrong question to be asking. In this type of client/server WPF scenario, would it make sense to follow the web app paradigm, where 99% of the client's focus is on display logic?
This is funny, because I often wonder how DDD can be applied to web development.
I don't mean this to be a comprehensive answer to your question, but you might find something useful among the responses to an old question of mine: Should I map a DTO to/from a domain entity on both client and server sides?
As a very general answer to your question, I'd say that you could move logic out of the view models and into a client-side domain model (since it sounds like the server side is working just fine without any concept of a domain model). You'd use the DTOs coming out of the web service to "hydrate" these entities.
If you're creating a smart client, then you want to leverage the ability to maintain state and perform logic directly in the client (so, "no" to the footnote).