First, before anyone screams dupe, I had a hard time summarizing it in a simple title. Another title might have been "What is the difference between a domain model and MVC model?" or "What is a model?"
Conceptually, I understand a Model to be the data used by the views and controller. Beyond that, there seems to be a great deal of differing opinions on what makes up the model. What's a domain model, versus an app model, vs a view model, vs a service model, etc..
For example, in a recent question I asked about the repository pattern, I was told point blank that the repository is part of the model. However, I have read other opinions that the model should be seperated from the persistence model and the business logic layer. After all, isn't the Repository pattern supposed to decouple the concrete persistence method from the model? Other people say there is a difference between the Domain model and the MVC model.
Let's take a simple example. The AccountController that is included with the MVC default project. I've read several opinions that the Account code included is of poor design, violates SRP, etc.. etc.. If one were to design a "proper" Membership model for an MVC application, what would that be?
How would you seperate the ASP.NET services (Membership provider, role provider, etc..) from the model? Or would you at all?
The way I see it, the model should be "pure", perhaps with validation logic.. but should be seperate from business rules (other than validation). For example, let's say you have a business rule that says someone must be emailed when a new account is created. That doesn't really belong in the model in my view. So where does it belong?
Anyone care to shed any light on this issue?
A1: Business Logic goes to Model part in MVC . Role of Model is to contain data and business logic. Controller on the other hand is responsible to receive user input and decide what to do.
The Right Answer Is… Business logic should live in the data model. And, what's more, it should live in the graph data model because that's the right abstraction for the next twenty years.
The Model part of the MVC application handles the application logic for the application data. It usually stores and retrieves the data from the database. It contains all of the application business logic, validation logic, and database access logic.
So what is Business Logic? The business logic are the set of codes in your application that handles communication between an end user interface and a database. In ASP.NET MVC your business logic will contain your domain models (entities), database context class, Repositories, services etc.
The way I have done it - and I'm not saying it is right or wrong, is to have my View and then a model that applies to my view. This model only has what is relevant to my view - including data annotations and validation rules. The controller only houses logic for building the model. I have a service layer which houses all business logic. My controllers call my service layer. Beyond that is my repository layer.
My domain objects are housed separately (in their own project, actually). They have their own data annotations and validation rules. My repository validates the objects in my domain before saving them into the database. Because every object in my domain inherits from a base class which has validation built in, my repository is generic and validates everything (and requires it inherits from the base class).
You might think that having two sets of models is duplication of code, and it is to an extent. But, there are perfectly reasonable instances where the domain object is not appropriate for the view.
Case in point is when working with credit cards - I have to require a cvv when processing a payment, but I cannot store the cvv (it is a $50,000 fine to do so). But, I also want you to be able to edit your credit card - change of address, name, or expiration date. But you aren't going to give me the number or the cvv when editing it, and I certainly am not going to put your credit card number in plain text on the page. My domain has these values required for saving a new credit card because you give them to me, but my edit model doesn't even include the card number or cvv.
Another benefit to so many layers is that if architected correctly, you can use structuremap or another IoC container and swap out pieces without detrimentally affecting your application.
In my opinion, controller code should only be code targeted at the view. Show this, hide that, etc. The service layer should house the business logic for your app. I like having all of it in one place so it's easy to change or tweak a business rule. The repository layer should be relatively dumb - devoid of business logic and only query your data and return your domain objects. By separating the view models from the domain model, you have much more flexibility when it comes to custom validation rules. It also means you don't have to dump every piece of data into your view in hidden fields and push it back and forth between the client and server (or rebuild it on the backend). Your view model will then house only the information relevant to the view - and it can be customized to have bools for view logic or counts or enums so that the view itself isn't cluttered up with complicated logic statements like
<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && Model.SomeObject.SomeInt == 3 && ...) { %>
While everything seems spread out and over-layered, it has a purpose for being architected this way. Is it perfect? not really. But I do prefer it to some past designs of calling repositories from the controller and having business logic mixed in the controller, repository, and model.
I too often wondered how exactly the MVC elements fit in a traditional web application structure, where you have views (pages), controllers, services, and data objects (model). As you said, there are many versions of that.
I believe the confusion exists because of the above stated, widely accepted architecture, which uses the "anemic domain model" (alleged)-anti pattern. I won't go into much details about the "anti-patternness" of anemic data model (you can look at an effort of mine to explain things here (Java-based, but relevant for any language)). But in short, it means that our model holds only data, and business logic is placed in services/managers.
But let's assume we have domain driven architecture, and our domain objects are the way they are expected to be - having both state and business logic. And in this domain-driven perspective things come into place:
I guess that answers your main questions. Things get complicated when we add some more layers, like the repository layer. It is often suggested that it should be invoked by the business logic placed in the model (and hence each domain object has a reference to a repository). In the article of mine that I linked I argue that this is not quite a best practice. And that in fact it is not a bad thing to have a service layer. By the way, domain-driven design does not exclude the service layer, but it is supposed to be 'thin', and only coordinating domain objects (so no business logic there).
For the anemic data model paradigm, which is widely adopted (for good or for bad), the model would be both the service layer and your data objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With