¿Se debe colocar la lógica de clasificación en el modelo, la vista o el controlador? [cerrado]

157

Tengo una lista desplegable que muestra los valores de una tabla al usuario final. Me gustaría ordenar estos valores alfabéticamente.

Según el diseño adecuado de MVC, ¿en qué capa debo colocar mi lógica de clasificación: el modelo, la vista o el controlador?

EDITAR : En respuesta a la pregunta de LarsH, "¿Te refieres al código que determina qué orden de clasificación se desea? ¿O al código que realiza la clasificación?", Originalmente me refería al código que determina qué orden de clasificación se desea.

Ryan Kohn
fuente
66
Para resolver el desacuerdo en los comentarios, sería útil decir lo que quiere decir con "lógica de clasificación". ¿Te refieres al código que determina qué orden de clasificación se desea? o código que realiza el ordenamiento?
LarsH
9
El diseño de MVC no es nada especial o mágico, es realmente solo un punto de partida. haga que se ajuste a sus necesidades y recuerde que puede refactorizar en cualquier momento. Me he dado cuenta de que diferentes proveedores redifinarán lo que entra en el controlador o la vista en función de las necesidades de su kit de herramientas, por lo que es difícil encontrar un acuerdo. Lo importante es separar su Modelo de su Vista / Controlador. También puede obtener más kilometraje del patrón MVP, creo que es un poco más específico exactamente en esta área.
Bill K
9
Tal vez esto debería migrarse a los programadores.
Alfredo Osorio
57
Definitivamente en el controlador. O eso o el modelo. O la vista.
mafia
2
Definitivamente nunca, nunca, nunca, nunca en la vista.
contactmatt

Respuestas:

49

(Nota: esta cita y cita están tomadas de la respuesta de @ dasblinkenlight , pero no estamos de acuerdo con nuestra interpretación. Lea su publicación y decídase ).

Según la descripción de MVC ,

Un controlador puede enviar comandos a su vista asociada para cambiar la presentación de la vista del modelo (por ejemplo, desplazándose por un documento). Puede enviar comandos al modelo para actualizar el estado del modelo (por ejemplo, editar un documento).

La lógica de clasificación (p. Ej., El comparador de clasificación / algoritmo de clasificación) pertenece al modelo ya que contiene reglas comerciales y datos de estado. Dado que la alteración de la forma en que se ordenan los datos del modelo cae directamente en la categoría "cambiar la presentación de la vista del modelo", el controlador es responsable de "hacer la clasificación" llamando al método model.changeSortedState ().

KyleM
fuente
8
¿Qué sucede si los mismos datos se mostrarán en dos vistas diferentes, ordenadas de manera diferente?
s4y
Eso también debe hacerse de la misma manera, model.SortAscending () y model.SortDescending () y llamado por Controller.
Brij
1
@Brij En MVC adecuado, ¿pueden dos vistas no compartir el mismo modelo?
KOVIKO
@Sidnicious Si tiene sentido tener un método de clasificación que tome un parámetro diferente. Por ejemplo public void Sort(bool sortByDescending = false), si es falso, se ordena ascendiendo. O simplemente tenga dos métodos de clasificación diferentes si la lógica es muy diferente.
MattMcGowan
@Sidnicious tiene dos modelos diferentes que delegan todo menos la lógica de clasificación a un solo tercer modelo. docs.google.com/drawings/d/…
plegado a la derecha el
62

¿Quién controla el orden de clasificación?

Diagrama MVC simple(De Wikipedia )

1) Orden natural dentro de los datos en sí:

El orden es parte del Modelo, por lo que debe ir allí. Una extracción sin formato de "todos los datos" devolvería los datos en el orden ordenado, y no hay interfaz para elegir el orden de clasificación.

2) El usuario debe controlar cómo ven los datos:

La Vista proporcionaría una interfaz (como flechas ascendentes / descendentes) que interactúa con el Controlador, y el Modelo comprende los datos lo suficientemente bien como para hacer la clasificación solicitada en los datos. Sin embargo, una extracción sin procesar de los datos no necesariamente tiene que ser ordenada, a diferencia de (1).

En cualquier caso,

La Vista no entiende que está ocurriendo un tipo, aparte de la capacidad de mostrar qué dirección de clasificación se ha elegido. No pongas la lógica allí.

Pequeña advertencia

La funcionalidad de clasificación podría ir puramente en la Vista, bajo una circunstancia (que se me ocurra por casualidad; puede haber más):

Una clasificación "tonta" donde todos los datos ya están en la vista y no tiene que usar ningún conocimiento de dominio para hacer la clasificación. Cadena muy simple o comparación de números, por ejemplo. Esto no es posible, por ejemplo, en los resultados de búsqueda en una página web cuando es probable que los resultados se dividan en varias páginas.

Izkata
fuente
59
¿La vista puede ver al usuario?
Farzher
41
¿El modelo actualiza la vista?
deceze
13
Ese artículo de wikipedia apesta: la sección "Interacción de componentes" entra en conflicto con el diagrama que se muestra a la derecha (que acaba de publicar aquí). En segundo lugar, el modelo no "actualiza" la vista. NOTIFICA la vista cuando ha habido un cambio de estado. La vista decide cómo actualizar. Ugh Te preguntas por qué hay 1000 respuestas diferentes a esta pregunta cuando hay tanta información poco clara flotando.
KyleM
44
@cHao claro. Podemos estar de acuerdo en que el gráfico de Wikipedia es bastante extraño, ¿verdad? :)
deceze
66
@StephenSarcsamKamenar y todos los demás: No, la imagen tiene mucho sentido: muestra el flujo de datos , no las conexiones de código.
Izkata
18

Según la descripción de MVC ,

Un controlador puede enviar comandos a su vista asociada para cambiar la presentación de la vista del modelo (por ejemplo, desplazándose por un documento). Puede enviar comandos al modelo para actualizar el estado del modelo (por ejemplo, editar un documento).

De acuerdo con esto, la lógica de clasificación pertenece al controlador, porque la alteración de la forma en que se ordenan los datos del modelo cae directamente en la categoría "cambiar la presentación del modelo de la vista".

EDITAR: Para aclarar múltiples malentendidos expresados ​​en los comentarios, la "lógica de clasificación" no es el código que realiza la clasificación; Es el código que define el tipo. La lógica de clasificación compara elementos individuales entre sí para establecer un orden (por ejemplo, a través de una instancia de IComparator<T>) o contiene una lógica que construye un objeto para ser utilizado para ordenar por un sistema externo (por ejemplo, a través de una instancia de IOrderedQueryable<T>). Esta lógica pertenece a su controlador, ya que necesita conocimientos relacionados con el lado "comercial" de su aplicación. Es completamente suficiente para realizar el ordenamiento, pero está separado del código que realmente realizaeso. El código que se ordena puede estar en su vista, en su modelo o incluso en la capa de persistencia que respalda su modelo (por ejemplo, su base de datos SQL).

revs dasblinkenlight
fuente
12
-1 ¿Cómo lograste concluir esto a partir de esa cita? ¿Se dijo en alguna parte que el controlador debe recuperar información del modelo? El controlador envía comandos para cambiar el estado. No se dice nada sobre la extracción o manipulación de la información.
tereško
3
@ tereško ¿Cómo logró concluir de mi respuesta que el controlador necesita recuperar información del modelo? Por "lógica de clasificación" me refiero solo a la lógica que es necesaria para establecer un orden, en términos de C #, que proporciona una implementación de IComparer<T>. La "mecánica de calderería" restante de la clasificación, incluida la recuperación de datos del modelo, depende de la vista.
dasblinkenlight
3
"... la lógica de clasificación pertenece al controlador ..." , ¿qué más significa esto?
tereško
3
"Un controlador puede enviar comandos a su vista asociada para cambiar la presentación de la vista" realmente suena como si la vista hiciera la clasificación, en respuesta al comando del controlador.
Samuel Edwin Ward
1
@KyleM Pero la vista no siempre tiene el conocimiento suficiente para contener la lógica de clasificación. Por ejemplo, considere un campo que tiene un código numérico correspondiente a una de las enumeraciones {Unknown, Pass, Fail}. Además, suponga que Unknownsiempre debe ordenar al final, independientemente del orden ascendente o descendente que haya elegido el usuario. Al colocar esta lógica en la vista, su opinión se vería demasiado acerca de la naturaleza comercial de los datos dentro del codecampo. La vista no debería saberlo: todo lo que sabe es que el usuario realizó un gesto de "clasificación" (por ejemplo, hizo clic en un encabezado); el resto depende del controlador.
dasblinkenlight
10

Ninguna de las anteriores. La clasificación es lógica de negocios, y la lógica de negocios no pertenece a ninguno de los tres. No todas las piezas de código en su aplicación serán un modelo, vista o controlador.

Lo que generalmente hago en mis aplicaciones MVC es que tengo una capa de servicio que realiza toda la lógica de negocios. Los métodos en la capa de servicio deben tener una API limpia y simple con parámetros bien nombrados. Luego puede invocar esos métodos desde su controlador para manipular los datos en los modelos.

En ese sentido, la ordenación está "en el controlador", pero el código mismo que realiza la ordenación no debe implementarse en el controlador, solo debe invocarse desde allí.

nont
fuente
55
Recientemente me han informado que algunas personas consideran que una "capa de servicio" (lógica de negocios) es parte del modelo.
Marvo
@Marvo Creo que hay algunos casos en los que ciertas lógicas están tan íntimamente ligadas a su tipo de datos que tiene sentido encapsularlas juntas en una clase. (funciones de fecha y hora, por ejemplo). Sin embargo, en general, creo que funciona mejor cuando los objetos modelo no hacen más que contener datos.
no el
Entonces, ¿dónde "vive" la lógica de negocios en el patrón MVC?
Marvo
2
El hecho de que una aplicación use un patrón MVC no significa que cada parte del código de la aplicación sea un modelo, vista o controlador. Eso está tomando patrones de diseño demasiado literalmente. Por ejemplo, su aplicación probablemente tenga un archivo de configuración de algún tipo. Ese archivo de configuración no modela datos de usuario, ni presenta vistas, ni controla el flujo de datos a través de modelos a vistas. Es un archivo de configuración, que es su propio tipo de cosas.
no el
Uno podría considerar fácilmente una parte del archivo de configuración del modelo. El modelo no tiene que ser una base de datos. No digo que tengas razón o no. Solo estoy sugiriendo que usted, como lo hice recientemente (porque tenía la misma opinión que usted) googleó el tema un poco y vio lo que otros dicen.
Marvo
8

Definitivamente no es el controlador: envía mensajes para ver y modelar, pero debe hacer el menor trabajo posible. Si el usuario puede cambiar la clasificación, el controlador maneja esa solicitud informando al modelo o la vista al respecto.

Tal vez la Vista si es una cosa pura de la Vista. Si la aplicación funciona igual de bien sin clasificar, la clasificación es solo parte de la representación y debe ir en la vista.

Si el orden es parte inherente del dominio, debe ir en el modelo.

Jens Schauder
fuente
¿"Proporcionar un comparador o un descriptor de clasificación" cuenta como "hacer trabajo"? Debido a que una lógica de clasificación se encapsula en un comparador o un descriptor de clasificación, incluso si el "trabajo de clasificación" se realiza en el método de clasificación o en el back-end del modelo.
dasblinkenlight
Depende de lo que quieras decir con proporcionar: pasar está bien. Pero el Comparador debe ser parte del modelo o vista, no el controlador.
Jens Schauder
6
  • Las vistas son la parte de MVC que se supone que contiene la lógica de presentación.
  • La capa del modelo es donde está contenida la lógica de negocios.
  • Los controladores solo cambian el estado de ambos, según la entrada del usuario.

Entonces, la elección es: ¿cree que esto es parte de la lógica de negocio del dominio o de la lógica de presentación?

Si estuviera implementando un MVC Model2 apropiado o un patrón MVC clásico, entonces diría que el pedido de datos proporcionados por la capa del modelo debe ser activado por la solicitud de la vista a la capa del modelo. Ver solicita datos ordenados, la capa del modelo lo proporciona.

Pero, dado que está utilizando la interpretación de ASP.NET MVC del patrón MVC, que es un poco diferente a su MVC estándar: la instancia de ViewModel debe solicitar información ordenada de la capa del modelo (por alguna razón, el marco de ASP.NET cree que las plantillas deberían llamarse "vistas" y vistas deberían llamarse "modelos de vista" ... es extraño).

tereško
fuente
12
Seguiste votando varias respuestas aplicando tu propia suposición de lo que significan por "lógica de clasificación". Su suposición es completamente incorrecta: la lógica de clasificación no incluye, y nunca lo hizo, la recuperación.
dasblinkenlight
1
@dasblinkenlight, sí, rechazo varios temas porque todos implican que el controlador debe realizar la clasificación. Cuál está mal. Y ... gente ... por favor, dejen de marcar mis comentarios solo porque no están de acuerdo.
tereško
Para ser claros: no rechacé su respuesta porque no es incorrecta, y nunca marqué ninguno de sus comentarios, porque no encuentro que sea abusivo de ninguna manera. Honestamente, no sé cómo su respuesta logró obtener tantos votos negativos: creo que están mal concebidos.
dasblinkenlight
@dasblinkenlight naah ... estaba furiosa por mis comentarios que en este tema se desvanecieron.
tereško
5

Por lo general, lo haría en el controlador para permanecer en línea con el patrón según las otras respuestas. Ver abajo para razonamiento.

He estado reflexionando sobre esto y leyendo las respuestas y el material relacionado y hablando pragmáticamente, diría que dependería de su aplicación, por ejemplo:

¿Es una aplicación mediana / grande y / o tiene múltiples IU asociadas (es decir, una aplicación de Windows, una interfaz web y una interfaz de teléfono)?

  • En este caso, probablemente construiría una capa de servicio y la pondría en el objeto comercial y luego llamaría al método apropiado desde el controlador.

Si se trata de un sitio web de interfaz de usuario único bien definido y está utilizando algo como EF Code First y no tiene o no tiene la intención de crear una capa de servicio y planea utilizar un método de extensión simple para obtenerlo:

  • En este caso, probablemente lo pondría en el controlador, ya que pragmáticamente es la mejor opción con respecto al tiempo / presupuesto.

Si es lo mismo que el anterior PERO no se puede implementar con un método de extensión listo para usar.

  • Bien puedo elegir hacer estallarlo en la clase Modelo (si es realmente a medida para ese tipo único) ya que sería más apropiado aquí que en un controlador. Si el orden se pudiera aplicar a más de una clase, lo implementaría en un método de extensión y luego lo llamaría en el controlador.

Para resumir:

Respuesta dogmática: capa de servicio

Respuesta pragmática: por lo general, el controlador

Luke Baughan
fuente
¿En qué controlador de definición es responsable de "preparar los datos para la vista"?
tereško
1
@ tereško: donde el modelo es "pasivo" como se describe aquí msdn.microsoft.com/en-us/library/ff649643.aspx en la sección de variaciones. Consulte "HTTP es un ejemplo de esto". Si bien un purista puede cuestionar esto, puede ser más fácil para los principiantes que comienzan en MVC donde pueden estar usando EF u otros modelos directamente en el controlador y no a través de un BAL para pensar de esta manera, reduciendo la barrera para comprender aún más el patrón.
Luke Baughan
1
de lo que estás hablando es de "modelo anémico".
tereško
Punto señalado, he eliminado las descripciones ofensivas como usted sugirió. Saludos por la entrada!
Luke Baughan
3

Sugeriría ordenar los datos de una tabla (los datos que son lo suficientemente pequeños como para ser útiles en una lista desplegable) deberían provenir de la base de datos ya ordenada a través de la consulta. Para mí, eso hace que el modelo sea el lugar donde se aplica la clasificación.

Si está decidido a hacer la clasificación a mano, creo que hay buenos argumentos para usar el modelo o el controlador como su lugar preferido para la lógica. La limitación sería su marco particular. Prefiero administrar los datos únicamente en el modelo. Utilizo el controlador para casar datos (modelo) y presentación (vista) como me han enseñado.

B0nk3r
fuente
2

Si bien estoy de acuerdo en principio con la idea de que la clasificación es Business Logic porque al desglosarla en su origen, terminaría con algo como "Al cliente le gustaría que la página del Producto se muestre con las imágenes ordenadas por fecha", entonces queda claro que el orden de clasificación de los datos generalmente no es arbitrario, incluso si no hay clasificación, ya que sigue siendo una decisión comercial por omisión (una lista vacía sigue siendo una lista).

PERO ... Estas respuestas no parecen tener en cuenta los avances en la tecnología ORM, solo puedo hablar en relación con Entity Framework (evitemos una discusión sobre si esto es ORM verdadero, ese no es el punto) de Microsoft como eso es lo que uso, pero estoy seguro de que otros ORM ofrecen una funcionalidad similar.

Si creo una vista fuertemente tipada para una clase de producto usando MS MVC y Entity Framework y hay una relación de clave externa entre el producto y la tabla de imágenes (por ejemplo, FK_Product_Image_ProductId), entonces sería capaz de ordenar rápidamente las imágenes durante su visualización usando algo como esto en la vista:

@foreach(Image i in Model.Image.OrderBy(e => e.DisplayOrder)){ //etc etc... }

Se mencionó una capa de Business Logic específica, que también utilizo para realizar el 80% de mi lógica de negocios, pero no voy a escribir una funcionalidad de clasificación en mi capa de Business Logic que imite algo que viene de fábrica del marco de la entidad.

No creo que haya una respuesta correcta a esta pregunta, aparte de decir eso; debe abstraer la lógica empresarial compleja siempre que sea posible, pero no a costa de reinventar la rueda.

Robar
fuente
Estaba pensando lo mismo, las respuestas aquí no parecen tener en cuenta los ORM y los métodos de extensión. En la mayoría de los casos, la lógica de clasificación será tan simple como myList.OrderBy(x => x.CreationDate): realmente no hay necesidad de introducir ninguna capa adicional innecesaria solo para hacer esto. Para agregar a esto, ¿qué harían si necesitaran datos paginados y ordenados? ¿Consulta toda la tabla, la ordena y luego guarda lo que necesita? Uno podría simplemente llamar myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize)y no se recuperarán datos innecesarios.
Balázs
1

Suponga que tiene un sitio web de MVC, un sitio web de WebForms y una aplicación móvil.

Si desea que la ordenación sea coherente entre estas capas de presentación, entonces diría que ordenar fuera de la capa de presentación. El servicio sería un buen candidato.

De lo contrario, almacenaría esa lógica en un modelo de vista. ¿Por qué? Porque será reutilizable y fácilmente comprobable.


fuente
0

De los tres que ha enumerado, diría que pertenece al controlador. Sin embargo, realmente no me gusta colocar este tipo de lógica en el controlador. Por lo general, creo una capa de servicio con la que se comunica el controlador que será responsable de comunicarse con el almacén de datos y manejar la lógica de clasificación. Sin embargo, para aplicaciones pequeñas, está bien sentarse en el controlador.

Despido
fuente
2
Eso pondría la lógica más del lado del modelo, ¿correcto?
Ryan Kohn
Sí, mi comprensión de una "capa de servicio" es que es parte del modelo.
Marvo
0

Esta es una pregunta hecha con asp.net en mente, pero como alguien mencionó a Rails, pensé que sería interesante considerar el problema en ese contexto. En Rails, es natural y bastante común realizar la clasificación junto con la recuperación como una acción del controlador, ya que el marco y la API de ActiveRecord / ActiveQuery lo prevén. Por otro lado, es posible definir algún tipo de orden de clasificación personalizado para elementos estáticos y ponerlo en el modelo que utilizará el controlador, para que el modelo pueda desempeñar un papel en la lógica de clasificación aunque no se lleve a cabo. La operación directamente. Sea lo que sea, puede ser seguro decir que poner la lógica de clasificación en la vista generalmente está mal visto.

Me divierte un poco que algunas respuestas estén absolutamente en contra de poner el tipo en el controlador o en el modelo, y las encuentro demasiado pedantes para mi gusto, pero supongo que depende de la naturaleza del marco utilizado y las convenciones habituales asociadas con eso. También estoy de acuerdo con el comentario de Bill K de que tener la separación en primer lugar es más importante.

Prusswan
fuente