2009-07-29 20 views
59

Estamos construyendo una aplicación de recursos humanos bastante grande en ASP.NET MVC, y hasta ahora nuestros controladores se están volviendo bastante grandes. Por ejemplo, tenemos un controlador de empleado y se incluyen todas las vistas de los empleados (información personal, deducciones de empleados, dependientes, etc.). Cada una de estas vistas puede tener múltiples acciones o subvistas (por ejemplo, CRUD). Cada acción es relativamente pequeña, pero los controladores pueden tener docenas de funciones.¿Es mejor tener controladores enormes o muchos controladores en MVC?

¿Existen mejores prácticas para dividir controladores? En lugar de tener un controlador de empleado con docenas de vistas, ¿sería mejor tener un controlador para cada subtipo (es decir, EmployeePersonalInfoController, EmployeeDeductionController, EmployeeDependentController)?

Y, por último, ¿importa?

Actualizado Aclaración

Mi preocupación original con las acciones CRUD. Por ejemplo, consideremos crear y eliminar ...

acciones actuales en EmployeeController:

CreateEmployee() 
    DeleteEmployee() 
    CreateEmployeeDeduction() 
    DeleteEmployeeDeduction() 
    CreateDependent() 
    DeleteDependent() 
    etc. 

Si los controladores se dividieron:

EmployeeController 
    Create() 
    Delete() 
    EmployeeDeductionController 
    Create() 
    Delete() 
    EmployeeDependentController 
    Create() 
    Delete() 
    EmployeeBenefitController 
    Create() 
    Delete() 
    etc. 

En la primera situación, nuestra ~ 100 las pantallas se dividen en 8-10 controladores grandes. En el segundo, probablemente tendría ~ 50 controladores.

Respuesta

12

En mi humilde opinión, si mantiene el código en sus controladores, entonces realmente no importa.

La mayor parte de su código estaría sucediendo en una capa de negocios en algún lugar ¿verdad? Si ese es el caso, entonces todo lo que realmente está haciendo en su controlador es devolver datos a la vista. Como debería ser.

No estoy seguro de si soy partidario de separar los controladores en subtipos. Si bien debe mantener la separación de las preocupaciones, creo que los subtipos van demasiado lejos.

Puede echar un vistazo a esta publicación para ver si ayuda. Same View Different Paths

Esa puede ser una solución mejor que utilizar un enfoque de subtipo que sugirió.

+0

No estoy seguro de si "subtipos" fue la mejor redacción de mi parte. No estaría implementando áreas (agrupándolas en carpetas), simplemente creando más de ellas. Actualizaré la pregunta con algún tipo de ejemplo para aclarar. Gracias. –

+0

La realidad, en la práctica, es que los controladores MVC hacen más que simplemente renderizar vistas. Por lo menos, necesita un manejador de envío y recepción por separado para cada página. Cada uno requiere diferentes entradas. Si tiene suerte, el modelo de vista que representa es el mismo modelo de vista que se publica. En una publicación, su controlador al menos tiene que descomprimir el modelo de vista en un DTO para pasar a su capa de lógica de negocios, y probablemente tendrá que hacer algún tipo de transformación en él, porque el desglose lógico de los datos provenientes del usuario no es necesariamente lo mismo que lo que se envía a la capa de lógica de negocios. – Triynko

+0

Después de pasar datos a la capa empresarial para su procesamiento, el controlador debe procesar una condición de éxito o falla. En caso de error, si tiene un modelo de datos personalizado (por ejemplo, representación de datos como una cadena JSON), entonces el estado del modelo incorporado es inútil, y deberá tomar otras medidas para asegurarse de que lo que el usuario publicó es -entregado en la pantalla. En caso de éxito, debe decidir a dónde enviar al siguiente usuario. Todo esto no es trivial, y aún sigue la regla básica de no poner lógica comercial en su controlador. Los controladores no son tan simples como las personas los están haciendo. – Triynko

3

¿Por qué no agruparlos?

Tener una estructura similar,

employee/payroll/ 
    employee/payroll/giveraise 
    employee/payroll/manage401k 

employee/general/ 
    employee/general/address 
    employee/general/emergencycontact 

Ahora usted puede tener un controlador de nómina manejo de las acciones relacionadas con la nómina y un controlador general que maneja datos regulares de un empleado.

+1

Nos encantaría, pero en el ASP.NET MVC estándar no existe el concepto de áreas (que creo que es lo que estás sugiriendo). Podríamos agregar una extensión que admita áreas, pero no me gusta agregar muchas cosas si no es necesario. –

+1

Creo que lo que Yogi Means es nómina es el controlador y giveraise/manage401k es la acción de aquellos. No es necesario tener ninguna extensión, solo agregue algunas reglas de enrutamiento más a global.asax funcionaría. – xandy

+1

@Jess et al. Ya existe soporte para FYI para las áreas: http://msdn.microsoft.com/en-us/library/ee671793.aspx –

1

Los controladores están destinados a ser contenedores para acciones en un contexto. ES DECIR. un controlador de cliente tendría acciones relacionadas con el control de clientes. Esto es particularmente adecuado para CRUD. Me gustaría ir con menos controladores más grandes por esta razón. Dicho esto, depende de ti, como arquitecto de aplicaciones, elegir la forma que mejor se adapte a tu código y simplemente porque es más común hacerlo de una manera no significa que tengas que hacerlo.

Si tiene grandes cantidades de código, le sugiero que consulte las áreas ASP.NET MVC.Puede encontrar publicaciones excelentes sobre él Here in Scott Gu's blog y Here in Steve Sanderson's blog. Si tiene tantos controladores, podría ser adecuado para usted.

Solo pensé en volver a leer su publicación, sospecho que su ejemplo no se acerca al nivel de complicación que tiene en su código. Tal vez podría ser útil si publicó una situación en la que no estaba seguro de si era o no una buena idea dividir el controlador que es más específico (y menos CRUDO, porque CRUD es bastante sencillo).

27

Partial classes le permiten extender su clase en varios archivos. De esta forma, puede agrupar las áreas relevantes de su controlador en archivos separados y, sin embargo, todas seguirán siendo parte del mismo controlador. p.ej.

EmployeeDeductionController.cs

public partial class EmployeeController 
{ 
    public ActionResult Deduct() 
    { 
    } 
    // etc 
} 

EmployeeBenefitController.cs

public partial class EmployeeController 
{ 
    public ActionResult GiveBenefit() 
    { 
    } 
    // etc 
} 
+1

Esto puede funcionar bastante bien, es la única razón por la que me molestaría con una clase parcial. –

+4

Buena idea ... pero por curiosidad, ¿cómo es esto más beneficioso que dividir el controlador en muchos controladores? –

+17

Una idea interesante, pero creo que abusa un poco de la función de clase parcial. Las clases parciales se diseñaron principalmente para escenarios de generación de código, de modo que los desarrolladores pudieran agregar a una clase generada y conservar esos cambios durante una regeneración. A menos que malinterprete, creo que es mejor crear controladores separados con una clase base compartida que usar parciales. –

10

No me gustaría tener 50 controladores. En este momento tengo 16 en mi aplicación y se siente bien. Si tiene 50 controladores, también tendrá 50 carpetas de nivel para las vistas. Será difícil encontrar la vista y el controlador que necesita para trabajar. Como otros mencionaron, las acciones suelen ser cortas y no es tan malo tener un par de ellas en su controlador.

Intenté tener 1 controlador por parte del sistema. Defino una parte del sistema tomando el esquema de mi base de datos y dibujando una línea alrededor de las tablas que pertenecen juntas.

1

Organizaría los controladores más o menos en torno a los casos de uso y su agrupación lógica. P.ej. si tiene múltiples casos de uso administrativos/de tipo de recursos humanos que probablemente estén disponibles para un grupo limitado de personas, agrupe aquellos en un controlador. Se podrían organizar otros controladores alrededor de objetos de modelos de dominio específicos, p. gestión de permisos de autoservicio, consultas salariales, etc. No existe una regla rígida y rápida, hay que crear un equilibrio entre no poner demasiada responsabilidad en un único controlador frente a la reutilización de estructuras internas comunes.

Recuerde también que, en la medida de lo posible, no debe tener una lógica comercial central en sus controladores. Realmente implementan el comportamiento del front-end, mientras que las reglas del sistema real deben estar en su modelo de dominio y capa de servicio. Mientras mantenga las cosas aproximadamente dentro de la capa correcta y razonablemente desacopladas, no puede ir demasiado mal con la forma en que coloca las operaciones individuales dentro de sus controladores.

2

Otro enfoque que hemos estado utilizando es tener un ControllerBase para mantener las preocupaciones transversales en un lugar común para las operaciones de CRUD. Este controlador declara las operaciones comunes e incluye puntos de extensión para las cosas específicas de la entidad. Tuvimos demasiadas duplicaciones de código sin algo como esto.

Luego, hereda este controlador y crea uno por entidad. Y sí, hay muchos controladores pero teniendo tantas pantallas, no creo que sea el problema principal.

La mayoría de las acciones aceptan un Modelo complejo y jugamos con las carpetas modelo para eliminar el desorden de los controladores. Puedes ver una buena publicación sobre eso here.

Entonces, usar áreas como @Odd sugiere que es una buena idea, al menos para separar las vistas, porque cuando las hay muchas es un desastre.

Esperemos que ASP.NET MVC v2 nos traerá áreas y encapsulando vistas en diferentes ensamblajes (en realidad eso se puede hacer ahora extendiendo la clase VirtualPathProvider).

Cuestiones relacionadas