Pregunta

En primer lugar, antes de que nadie gritos víctima, que tenía un tiempo difícil resumir en un simple título. Otro título podría haber sido "¿Cuál es la diferencia entre un modelo de dominio y el modelo MVC?" o "¿Qué es un modelo?"

Conceptualmente, entiendo un modelo a los datos utilizados por los puntos de vista y controlador. Más allá de eso, parece que hay una gran cantidad de opiniones diferentes sobre lo que constituye el modelo. ¿Qué es un modelo de dominio, frente a un modelo de aplicación, frente a un modelo de vista, frente a un modelo de servicio, etc ..

Por ejemplo, en una reciente pregunta pregunté por el patrón de repositorio, me dijeron rotundamente que el depósito es parte del modelo. Sin embargo, he leído otras opiniones que el modelo debe ser separado del modelo de persistencia y la capa de lógica de negocio. Después de todo, no es el patrón de repositorio supone que desacoplar el método de persistencia concreto del modelo? Otras personas dicen que hay una diferencia entre el modelo de dominio y el modelo MVC.

Vamos a dar un ejemplo sencillo. El AccountController que se incluye con el proyecto predeterminado MVC. He leído varias opiniones que el código de cuenta incluido es de un mal diseño, viola SRP, etc .. etc .. Si uno tuviera que diseñar un modelo "correcto" Membresía para una aplicación MVC, ¿cuál sería?

¿Cómo separar los servicios de ASP.NET (proveedor de pertenencia, proveedor de funciones, etc ..) desde el modelo? O ¿verdad en absoluto?

A mi modo de ver, el modelo debe ser "puro", tal vez con la lógica de validación .. pero debe ser separada de reglas de negocio (que no sean de validación). Por ejemplo, digamos que usted tiene una regla de negocio que dice que alguien debe ser enviado por correo electrónico cuando se crea una nueva cuenta. Que en realidad no pertenecen en el modelo, en mi opinión. Entonces, ¿dónde pertenece?

Cualquier atención a arrojar alguna luz sobre este tema?

¿Fue útil?

Solución

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.

Otros consejos

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:

  • the view is the UI
  • the controller gathers the inputs of the UI, invokes methods on the model, and sends back a response to the UI
  • the model is our business components - holding the data, but also having business logic.

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.

In my opinion,

Model -

Should not contain business logic, it should be pluggable(WCF like scenario). It is used to bind to view so, it should have properties.

Business Logic -

It should be placed at "Domain Services Layer", it is separate layer altogether. Also, will add one more layer here "Application Services".

App Services talks to Domain Services layer to apply business logic and then lastly return the Model.

So, Controller will ask Application Service for Model and the flow will go like,

    Controller->Application Services(using domain services)->Model

The MVC pattern and the Asp.net framework makes no distinction on what the Model should be.

MS's own examples include persistence classes in the model. Your question about membership being in the model. This depends. Are classes in your model owned by something? Is there a link between who logs in and what data is displayed? Is there filtering of data part of a permissions system that is editable? Is who last updated or edited an object part of your domain as in somebody else needs to see it or something for backend support?

The email example is also it depends. Are you familiar with domain eventing or eventing in particular? Do you have a separate service to send emails? Is the act of sending an email part of your domain or is it a application level concern outside of the scope of your system? Does the UI need to know if an email was sent successfully or not? Do emails that fail to send need retries? Does the content of the email sent need to be stored for support or customer service requirements?

These types of questions are overly broad and subjective but I'm answering so you and everybody who voted you up can understand this.

Your requirements/timelines/resources all bleed into your system's architecture. Even the revenue model can have an effect. You also have to consider the pattern you are shooting for. DDD is much different than persistence-as-model applications and all the slop in between are also valid for certain apps. Are you shooting for testing the app? All of this has an effect.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top