En primer lugar, he visto muchas preguntas sobre esto, pero no hay suficientes razones detrás de eso. Si mi pregunta no es lo suficientemente buena y debe eliminarse, lo entenderé.
He echado un vistazo, por ejemplo, a esto y una respuesta votada a más de 45 dice que le aconseja que coloque la lógica empresarial en el modelo, lo que suena bastante lógico.
Sin embargo, mi primer proyecto grande lo hice con todo mi BL completamente en los controladores, porque no cuestioné estas cosas y miré cómo se hace en el AccountController
que se agrega automáticamente si elige MVC con autenticación de formulario. Todos los métodos se ven bastante llenos de BL. ¿O tal vez es la menor cantidad de código que se pudo agregar y estoy pasando por alto algunas cosas?
Una persona en youtube me preguntó si tenía razón al poner toda la lógica en sus modelos y al principio yo estaba ¡no! ¡Entonces comencé a pensar que tal vez él tenía razón !?
Entonces, después de todo, ¿dónde pongo mi lógica empresarial? Si está en clases de modelos, entonces, ¿cuánto código debe considerarse una cantidad saludable en un método que está en el controlador? ¿Una línea para llamar a algún método del modelo en un controlador como máximo y luego volver a la vista?
fuente
Respuestas:
Prefiero poner lógica de dominio en el modelo por un par de razones.
El modelo no debe tener código de interfaz de usuario y, por lo tanto, debe ser más fácil de probar. Siempre que sea posible, me gusta tener un modelo que funcione completamente (es decir, una cobertura de prueba completa) antes de escribir cualquier código de IU. El controlador puede confiar en que el modelo está haciendo lo correcto y solo ocuparse de las preocupaciones de la interfaz de usuario.
Si coloca la lógica de dominio en un controlador, no es tan fácil de compartir entre diferentes aplicaciones, o incluso entre diferentes controladores.
fuente
#2
porque me resultó difícil compartir entre controladores (tuve que usar métodos como estáticos).Me gusta mantener limpios mis modelos, es decir, solo con propiedades y sin lógica empresarial. Siempre creo que es bueno inyectar dependencias en el controlador y estas dependencias contienen la lógica que realizo en mis modelos. Me gusta adherirme al principio de responsabilidad única siempre que sea posible y encuentro que los modelos con toneladas de métodos se hinchan muy rápidamente. Hay ventajas y desventajas para ambos, inyectar muchas dependencias tiene una sobrecarga pero permite probar de forma aislada y mantiene las clases simples y terminará teniendo controladores más eficientes. A pesar de que mi lógica no existe realmente en mi modelo como miembros de la clase, sigue siendo lógica empresarial. Tiendo a no tener la lógica de negocios definida en el controlador, ya que burlarse de cosas como Httpcontext es un poco una pesadilla e innecesaria.
fuente
La lógica de negocios pertenece al dominio del problema y todo lo que pertenece al dominio del problema va al modelo en MVC.
El controlador debe ser responsable de pasar los datos del modelo a la vista y de la vista al modelo. Por lo tanto, el controlador es el puente entre lo que interactúa el usuario y cómo el programa modela y almacena el estado del problema. La fontanería , por así decirlo.
La clave aquí es la distinción entre la lógica empresarial y la lógica de plomería. En mi opinión, lo que hace el controlador de cuenta generado automáticamente es principalmente plomería, no realmente lógica comercial. Tenga en cuenta que la lógica de la plomería no es necesariamente corta en absoluto, por lo que no es necesario imponer límites artificiales (como "X número de llamadas como máximo en el controlador").
fuente
Mi equipo cuando se trasladó a mvc desde webforms (asp.net) investigó mucho y se le ocurrió la siguiente estructura. Según yo, no se trata de cuán grande o pequeña sea la aplicación. Se trata de mantener el código limpio y claro.
Proyecto DAL
AccountsDAL.cs --- > Calls SP or any ORM if ur using any
BLLProyecto
Proyecto Web
Los controladores deben ser responsables del paso de datos entre el modelo y la vista. Aparte de eso, no debería haber ningún código innecesario. Por ejemplo, si está registrando, debe hacerlo a nivel de modelo en lugar de controlador.
fuente
Parece haber cierta confusión en torno a este tema. En general, parece que las personas tienden a confundir el patrón MVC con la arquitectura de N niveles como una situación de una u otra. La realidad es que los dos enfoques se pueden utilizar juntos, pero uno no depende del otro y no se requiere ninguno.
La arquitectura de N niveles se ocupa de separar una aplicación en varios niveles. Un ejemplo simple es donde la aplicación se divide en una capa de presentación, una capa de lógica empresarial y una capa de acceso a datos.
MVC es un patrón de diseño que se ocupa de la capa de presentación de una aplicación. Es totalmente posible diseñar una aplicación siguiendo un enfoque MVC sin separar la lógica de negocios y la lógica de acceso a datos de la capa de presentación y, por lo tanto, terminar con un diseño de un solo nivel.
El resultado, si está siguiendo un enfoque MVC sin separar también la aplicación en niveles, es que terminará con Modelos, Vistas y Controladores que tienen partes de reglas comerciales y lógica de acceso a datos mezcladas con el resto de la lógica.
Por definición, en una arquitectura de N niveles, se supone que el nivel de presentación solo puede comunicarse con la capa de lógica empresarial, por lo que debe mantener que cualquiera de los componentes MVC solo puede comunicarse con la capa de lógica empresarial.
Si está creando una aplicación que no incluye presentación y, por lo tanto, no es una capa de presentación, no debería tener que preocuparse por el patrón MVC. Sin embargo, es muy posible que aún pueda dividir su aplicación en varios niveles y, por lo tanto, seguir un diseño de N niveles aunque no haya una capa de presentación involucrada.
fuente
En términos generales, la lógica empresarial no debería residir en ninguno de los jugadores MVC; solo debe ser consumido por las acciones de su controlador.
Como muchos han mencionado, es mejor crear una biblioteca para alojar la lógica empresarial como un conjunto de componentes reutilizables independientes del cliente.
Cuando se hace de esta manera, aumentamos enormemente la capacidad de reutilización, compatibilidad, escalabilidad y capacidad de prueba con nuestro software. También reducimos nuestra dependencia de ciertas características del marco, lo que facilita la migración a tecnologías más nuevas / diferentes.
Resumir nuestra lógica empresarial en un ensamblaje (o ensamblajes) independiente nos ha sido de gran utilidad a lo largo de los años. Nuestra lógica empresarial puede ser consumida por prácticamente cualquier tecnología .NET (ASP.NET MVC / API / Core, WPF, Win Forms, WCF, UWP, WF, Console, etc.).
Además, nos gusta que nuestro nivel intermedio maneje las reglas comerciales y la lógica de validación para reducir nuestras dependencias en .NET MVC Framework. Por ejemplo, evitamos usar los ayudantes de validación de .NET MVC y, en cambio, confiamos en los nuestros. Este es otro factor que nos permite consumir fácilmente nuestra lógica empresarial desde cualquier tecnología .NET.
El diseño lógico de nuestro nivel medio de esta manera nos ha permitido lograr fácilmente esta arquitectura física:
Fue escrito con Peasy.NET y nos ha servido bien a lo largo de los años. Tan bien de hecho que decidimos abrirlo.
Si alguien tiene curiosidad sobre cómo es nuestro nivel medio, aquí hay una muestra de una capa empresarial independiente del cliente. También muestra el consumo de varios clientes .NET (ASP.NET MVC, Web Api y WPF).
¡Espero que esto ayude a alguien!
fuente
La lógica empresarial no debe ir en sus Vistas de modelos o Controladores. Debería haber una capa de lógica empresarial separada ; el único propósito de esta capa es manejar su lógica empresarial. Esto está más en línea con SOLID .
Si pusiera su lógica de negocios en MV o C, terminaría con un código que es difícil de probar / reutilizar.
Esa es una mala solución.
Terminarás en un infierno de dependencia donde los objetos dependen de los objetos.
Incluso si tiene una función simple muerta, aún tendrá que satisfacer todas las dependencias para llamarla.
También hará que se pasen datos innecesarios y no utilizados sin ningún motivo. Esto también podría afectar el rendimiento dependiendo de qué tan mal se ponga.
También debo mencionar que las pruebas unitarias se vuelven un dolor de cabeza porque tienes que simular varios objetos solo para probar una función simple.
Se aplican los principios del código limpio
Controladores
En su controlador, debería poder usar la inyección de dependencia para inyectar la capa de lógica empresarial . Asegúrese de que su controlador solo se utilice para enrutar información a la capa de lógica empresarial. El controlador NO debe tener lógica comercial directamente en él. Cualquier validación debe ser manejada por
IValidatable
el modelo. Cualquier lógica empresarial debe enrutarse a una capa separada.fuente
Payment
yProduct
como variable de instancia? ¿Cómo llamas a ese objeto? Si un modelo no se usa en una vista, ya no es un modelo. Es parte de una capa separada. Idealmente, esa clase que haga solo debe tomar lo que necesita de Pago y Producto para hacer su trabajo. Si solo necesita elproductName
y elprice
, solo debe tomar esos dos parámetros, no todo el objeto.La respuesta general que tengo es que la lógica empresarial normalmente encaja en dos categorías:
Lógica empresarial orientada a objetos: se modela como objetos (en el modelo), generalmente inyectados como repositorios.
Lógica empresarial procedimental: entra en un servicio con una interfaz que se puede inyectar en un controlador.
Controller Logic: Lógica que controla cómo se reciben los comandos y cómo se pasan a los modelos / servicios, luego cómo esos resultados se pasan a la vista.
Los controladores no deben tener lógica comercial , es una parte muy específica de un patrón de diseño para controlar cómo una interfaz de usuario transfiere la entrada a los modelos que manejan la lógica comercial (o servicios si sus problemas son de naturaleza más procedimental).
fuente
También me gusta mantener limpios mis modelos (ref: @Mark Walsh). El problema de no poder reutilizar la lógica incrustada en los controladores puede superarse fácilmente mediante la inyección de dependencias o, si cree que habría demasiado de eso, exponga la lógica de su negocio / dominio a través de interfaces y utilice el patrón de fachada en los controladores. De esa manera, obtiene la funcionalidad que necesita, pero mantiene tanto los controladores como el modelo en buen estado y limpio.
fuente
También preferiría mantener limpios los modelos. Los controladores MVC deben usarse solo para realizar llamadas y también deben mantenerse limpios. Entonces, dependiendo de su reutilización, sensibilidad y relevancia, la lógica empresarial se puede escribir en
1.WebApi Controller: La ventaja de usar un controlador webapi es que puede exponerlos como servicios más tarde a otros dispositivos, haciendo que su código sea reutilizable.
2. BAL / componente común: hay algunas lógicas que tienen un uso específico y no se pueden exponer como una API, se pueden insertar en esta clase.
3. Repositorio: Todas las consultas relacionadas con la base de datos se agregan a un repositorio. Puede haber un repositorio genérico que implemente todas las funciones (operaciones CRUD) o repositorios específicos para cada tabla. Dependiendo de las operaciones a realizar.
fuente
Como escribió ahanusa, debe poner la lógica de su negocio en una DLL separada o en un directorio separado.
A menudo uso un directorio llamado Logics en el mismo nivel de Modelos y Controladores donde pongo clases que hacen lógica de negocios.
De esta forma dejo que tanto los modelos como los controladores se limpien.
fuente
Sé que es una pregunta sobre MVC, pero creo que el ejemplo que estoy dando (API web) será útil.
Estoy desarrollando mi primera API web y estoy reutilizando la lógica empresarial de otras aplicaciones. Para ser específico, proviene de una DLL externa, por lo que mi API se usa solo para "hablar" con una solución SAP, recibir solicitudes de PO y enviar respuestas.
¿Cómo podría poner mi lógica (ya implementada) en mi controlador? No lo necesito Mi controlador solo recibirá, validará solicitudes y redactará respuestas para devolver datos.
Estoy trabajando con clases de ViewModel y todo lo que deben tener es una función de mapeo, solo para leer información de TransferObjects (que proviene de la DLL externa) y traducir a un ViewModel.
No me siento cómodo con mi aplicación (en este caso la API web) manteniendo la lógica empresarial, creo que la reutilización se perderá de esta manera.
Estoy tratando mi lógica empresarial como una dependencia que inyecto en el controlador.
He realizado muchas refactorizaciones en el legado para proporcionar una solución de prueba unitaria, tuve que crear muchas interfaces e implementar algunos patrones de diseño en el legado para proporcionar esta solución.
En mi punto de vista, la capa empresarial debe estar separada de la aplicación, preferiblemente en otra biblioteca de clases. Así tendrás implementado un concepto de separación real en tu aplicación.
Por supuesto, si su CORE (negocio) es su aplicación (API / WebSite) , las reglas de negocio se implementarán en sus clases MVC. Pero en el futuro, si desea desarrollar una nueva aplicación y algunas reglas comerciales son las mismas, apuesto a que tendrá muchos problemas solo para mantener la misma lógica implementada en ambas aplicaciones.
fuente