A lógica de classificação deve ser colocada no modelo, na vista ou no controlador? [fechadas]

157

Eu tenho uma lista suspensa que exibe valores de uma tabela para o usuário final. Eu gostaria que esses valores fossem classificados em ordem alfabética.

De acordo com o design adequado do MVC, em que camada devo colocar minha lógica de classificação: o modelo, a visualização ou o controlador?

Edição : Em resposta à pergunta de LarsH, "Você quer dizer código que determina qual ordem de classificação é desejada? Ou código que executa a classificação?", Eu estava originalmente me referindo ao código que determina qual ordem de classificação é desejada.

Ryan Kohn
fonte
6
Para resolver discordâncias nos comentários, seria útil se você disser o que quer dizer com "lógica de classificação". Você quer dizer código que determina qual ordem de classificação é desejada? ou código que executa a classificação?
precisa saber é
9
O design do MVC não é nada de especial ou mágico - é realmente apenas um ponto de partida. ajuste-o às suas necessidades e lembre-se de que pode refatorar a qualquer momento. Percebi que diferentes fornecedores redefinirão o que entra no controlador ou a visualização com base nas necessidades do kit de ferramentas, por isso é difícil encontrar um acordo. O importante é separar seu modelo do seu View / Controller. Você também pode obter mais milhas do padrão MVP, acredito que seja um pouco mais específico exatamente nessa área.
Bill K
9
Talvez isso deva ser migrado para programadores.
Alfredo Osorio
57
Definitivamente no controlador. Ou isso ou o modelo. Ou a vista.
mob
2
Definitivamente nunca, nunca, jamais, jamais na visão.
contactmatt

Respostas:

49

(Nota: esta citação e citação é retirada da resposta de @ dasblinkenlight , mas discordamos de nossa interpretação. Leia o post dele e decida -se).

De acordo com a descrição do MVC ,

Um controlador pode enviar comandos para sua visualização associada para alterar a apresentação da visualização do modelo (por exemplo, rolando um documento). Ele pode enviar comandos ao modelo para atualizar o estado do modelo (por exemplo, editar um documento).

A lógica de classificação (por exemplo, o comparador de classificação / algoritmo de classificação) pertence ao modelo, pois contém regras de negócios e dados de estado. Como alterar a maneira como os dados do modelo são classificados se enquadra na categoria "alterar a apresentação da visualização do modelo", o controlador é responsável por "fazer a classificação" chamando o método model.changeSortedState ().

KyleM
fonte
8
E se os mesmos dados forem exibidos em duas visualizações diferentes, classificadas de maneira diferente?
S4y 22/08/12
Isso também deve ser feito da mesma maneira, model.SortAscending () e model.SortDescending () e chamado pelo Controller.
Brij
1
@Brij No MVC adequado, duas visualizações não podem compartilhar o mesmo modelo?
KOVIKO
@ Sidnicious Se faz sentido ter um método de classificação que usa um parâmetro diferente. Por exemplo public void Sort(bool sortByDescending = false), onde, se falso, classifica por ascensão. Ou apenas tenha dois métodos de classificação diferentes se a lógica for muito diferente.
precisa saber é o seguinte
O @Sidnicious tem dois modelos diferentes que delegam tudo, exceto a lógica de classificação, para um único terceiro modelo. docs.google.com/drawings/d/…
rightdold 11/12/15
62

Quem controla a ordem de classificação?

Diagrama MVC simples(Da Wikipedia )

1) Ordem natural dentro dos próprios dados:

O pedido faz parte do modelo, portanto deve ir para lá. Uma solicitação bruta de "todos os dados" retornaria os dados na ordem de classificação e não há interface para escolher a ordem de classificação.

2) O usuário deve controlar como eles vêem os dados:

A Visualização forneceria uma interface (como setas ascendentes / descendentes) que interagem com o Controlador, e o Modelo entende os dados suficientemente bem para fazer a classificação solicitada nos dados. No entanto, uma atração bruta dos dados não precisa necessariamente ser classificada, ao contrário de (1).

Em ambos os casos,

A Visualização não entende que há uma classificação em andamento, além da capacidade de mostrar qual direção de classificação foi escolhida. Não coloque a lógica lá.

Advertência pequena

A funcionalidade de classificação pode ser puramente visualizada, sob uma circunstância (que eu possa pensar de antemão; pode haver mais):

Uma classificação "burra" em que todos os dados já estão na exibição e não precisa usar nenhum conhecimento de domínio para fazer a classificação. Comparação de números ou seqüências muito simples, por exemplo. Isso não é possível, por exemplo, nos resultados de pesquisa em uma página da Web quando é provável que os resultados sejam divididos em várias páginas.

Izkata
fonte
58
A vista pode ver o usuário !?
precisa saber é o seguinte
41
O modelo atualiza a visualização !?
deceze
13
Esse artigo da Wikipedia é péssimo: a seção "Interação de componentes" entra em conflito com o diagrama mostrado à direita (que você acabou de postar aqui). Em segundo lugar, o modelo não "atualiza" a visualização. NOTIFICA a visualização quando houve uma alteração de estado. A visualização decide como atualizar. Ugh. Você se pergunta por que existem 1000 respostas diferentes para essa pergunta, quando há tantas informações pouco claras por aí.
precisa saber é o seguinte
4
@cHao Claro. Podemos concordar que o gráfico da Wikipedia é bastante estranho, certo? :)
deceze
6
@StephenSarcsamKamenar e todos os outros: Não, a imagem faz todo o sentido: está mostrando o fluxo de dados , não as conexões de código.
Izkata
18

De acordo com a descrição do MVC ,

Um controlador pode enviar comandos para sua visualização associada para alterar a apresentação da visualização do modelo (por exemplo, rolando um documento). Ele pode enviar comandos ao modelo para atualizar o estado do modelo (por exemplo, editar um documento).

De acordo com isso, a lógica de classificação pertence ao controlador, porque alterar a maneira como os dados do modelo são classificados cai diretamente na categoria "alterar a apresentação da exibição do modelo".

EDIT: Para esclarecer vários mal-entendidos expressados ​​nos comentários, a "lógica de classificação" não é o código que executa a classificação; é o código que define a classificação. A lógica de classificação compara itens individuais entre si para estabelecer uma ordem (por exemplo, através de uma instância de IComparator<T>) ou contém lógica que constrói um objeto a ser usado para fazer pedidos por um sistema externo (por exemplo, através de uma instância de IOrderedQueryable<T>). Essa lógica pertence ao seu controlador, porque precisa de conhecimento relacionado ao lado "comercial" do seu aplicativo. É inteiramente suficiente executar a classificação, mas é separado do código que realmente executaisto. O código que classifica pode estar na sua visão, no seu modelo ou até na camada de persistência que apóia o seu modelo (por exemplo, seu banco de dados SQL).

dasblinkenlight
fonte
12
-1 Como você conseguiu concluir isso a partir dessa citação? Em algum lugar foi dito que o controlador deveria recuperar informações do modelo? O controlador envia comandos para alterar o estado. Não se diz nada sobre extração ou manipulação de informações.
tereško
3
@ tereško Como você conseguiu concluir pela minha resposta que o controlador precisa recuperar informações do modelo? Por "lógica de classificação", quero dizer apenas a lógica necessária para estabelecer uma ordem - em termos de C #, que fornece uma implementação de IComparer<T>. A "mecânica padrão" restante da classificação, incluindo a recuperação de dados do modelo, está de acordo com a visão.
precisa saber é o seguinte
3
".. lógica de classificação pertence ao controlador .." , o que mais isso significa?
tereško
3
"Um controlador pode enviar comandos para a visualização associada para alterar a apresentação da visualização" realmente parece que a visualização faria a classificação, em resposta ao comando do controlador.
Samuel Edwin Ward
1
@KyleM Mas a visão nem sempre tem conhecimento suficiente para conter a lógica de classificação. Por exemplo, considere um campo que tenha um código numérico correspondente a uma das enumerações {Unknown, Pass, Fail}. Além disso, suponha que Unknowndeve sempre classificar por último, independentemente da ordem crescente ou decrescente que o usuário escolheu. A colocação dessa lógica na visualização informaria muito a sua visão sobre a natureza comercial dos dados dentro do codecampo. A visualização não deve saber disso: tudo o que se sabe é que o usuário executou um gesto de "classificação" (por exemplo, clicou em um cabeçalho); o resto é com o controlador.
precisa saber é o seguinte
10

Nenhuma das acima. A classificação é lógica de negócios e a lógica de negócios não pertence a nenhum dos três. Nem todo código no seu aplicativo será um modelo, visualização ou controlador.

O que geralmente faço nos meus aplicativos MVC é que tenho uma camada de serviço que executa toda a lógica de negócios. Os métodos na camada de serviço devem ter uma API simples e limpa, com parâmetros bem nomeados. Em seguida, você pode chamar esses métodos do seu controlador para manipular os dados nos modelos.

Nesse sentido, a classificação está "no controlador", mas o próprio código que faz a classificação não deve ser implementado no controlador, apenas invocado a partir daí.

não
fonte
5
Recentemente, fui informado de que algumas pessoas consideram uma "camada de serviço" (lógica de negócios) como parte do modelo.
Marvo
@ Marvo Eu acho que há alguns casos em que certas peças de lógica estão tão intimamente ligadas ao tipo de dados que faz sentido encapsulá-las juntas em uma classe. (funções de hora e data, por exemplo). Em geral, porém, acho que funciona melhor quando os objetos de modelo não fazem nada além de reter dados.
nont
Então, onde a lógica de negócios "vive" no padrão MVC?
Marvo
2
Só porque um aplicativo usa um padrão MVC, não significa que cada parte do código no aplicativo será um modelo, visualização ou controlador. Isso está levando os padrões de design muito literalmente. Por exemplo, seu aplicativo provavelmente possui um arquivo de configuração de algum tipo. Esse arquivo de configuração não está modelando dados do usuário, nem apresentando visualizações, nem controlando o fluxo de dados através de modelos para visualizações. É um arquivo de configuração, que é o seu próprio tipo de coisa.
nont
Pode-se facilmente considerar um arquivo de configuração como parte do modelo. O modelo não precisa ser um banco de dados. Não estou dizendo que você está certo ou errado. Só estou sugerindo que você, como fiz recentemente (porque mantive a mesma opinião que você), pesquise um pouco no assunto e veja o que os outros estão dizendo.
Marvo
8

Definitivamente não é o controlador: ele envia mensagens para visualizar e modelar, mas deve fazer o mínimo possível de trabalho. Se o usuário puder alterar a classificação, a solicitação será tratada pelo controlador, informando o modelo ou a visualização sobre ele.

Talvez o View seja uma coisa pura do View. Se o Aplicativo funcionar tão bem sem classificação, a classificação é apenas parte da representação e deve ser exibida.

Se a ordem é parte inerente do domínio, ela deve ser inserida no modelo.

Jens Schauder
fonte
"Fornecer um comparador ou um descritor de classificação" conta como "fazendo trabalho"? Como uma lógica de classificação é encapsulada em um comparador ou em um descritor de classificação, mesmo se o "trabalho de classificação" for realizado no método de classificação ou no backend do modelo.
precisa saber é o seguinte
Depende do que você quer dizer com fornecer: a aprovação é aceitável. Mas o comparador deve fazer parte do modelo ou da vista, não do controlador.
Jens Schauder
6
  • As visualizações são a parte do MVC que deve conter a lógica de apresentação.
  • A camada de modelo é onde a lógica de negócios está contida.
  • Os controladores alteram apenas o estado de ambos, com base na entrada do usuário.

Portanto, a escolha é: você acha que isso faz parte da lógica de negócios do domínio ou da lógica de apresentação.

Se você estivesse implementando um padrão MVC Model2 ou MVC clássico adequado, eu diria que a ordem dos dados fornecidos pela camada do modelo deve ser acionada pela solicitação da visualização para a camada do modelo. O View solicita dados ordenados, a camada do modelo fornece.

Porém, como você está usando a interpretação do padrão MVC do ASP.NET MVC, que é um pouco diferente do seu MVC padrão - a instância do ViewModel deve solicitar informações ordenadas da camada do modelo (por algum motivo, a estrutura do ASP.NET acha que os modelos devem ser chamados "views" e views devem ser chamadas de "viewmodels" (é estranho).

tereško
fonte
12
Você continuou votando várias respostas aplicando sua própria suposição do que elas significam por "lógica de classificação". Sua suposição é totalmente incorreta - a lógica de classificação não inclui, e nunca incluiu, recuperação.
precisa saber é o seguinte
1
@dasblinkenlight, sim, eu diminui o voto de vários tópicos porque todos implicavam que o controlador deveria realizar a classificação. O que está errado. E .. gente .. por favor pare de sinalizar meus comentários só porque você discorda.
tereško 15/08/12
Só para esclarecer: não neguei sua resposta porque ela não está incorreta e nunca sinalizei nenhum de seus comentários, porque não considero abusivo de nenhuma maneira. Sinceramente, não sei como sua resposta conseguiu tantos votos negativos: acho que são mal concebidos.
precisa saber é o seguinte
@dasblinkenlight naah .. eu estava furioso com meus comentários, que neste tópico desapareceram.
tereško 15/08/12
5

Eu normalmente faria isso no controlador para permanecer alinhado com o padrão conforme as outras respostas. Veja abaixo o raciocínio.

Estive refletindo sobre isso e lendo as respostas e o material relacionado, e falando pragmaticamente, eu diria que isso dependeria da sua aplicação, por exemplo:

É um aplicativo médio / grande e / ou possui várias UIs associadas (por exemplo, um aplicativo do Windows, interface da Web e interface do telefone).

  • Nesse caso, eu provavelmente construiria uma camada de serviço e a colocaria no objeto de negócios e depois chamaria o método apropriado do controlador.

Se é um site de interface do usuário única bem definido e você está usando algo como EF Code First e não tem ou não tem intenção de criar uma camada de serviço e planeja usar um método de extensão simples e imediato para obtê-lo:

  • Nesse caso, eu provavelmente o colocaria no controlador como pragmaticamente o melhor ajuste em relação ao tempo / orçamento.

Se for o mesmo que o anterior, MAS não pode ser implementado com um método de extensão pronto para uso.

  • Eu posso muito bem optar por colocá-lo na classe Model (se for realmente feito sob medida para esse tipo único), pois seria mais apropriado aqui do que em um controlador. Se a classificação pudesse ser aplicada a mais de uma classe, eu a implementaria em um método de extensão e a chamaria no controlador.

Resumindo:

Resposta dogmática: Camada de Serviço

Resposta pragmática: geralmente o controlador

Luke Baughan
fonte
Em qual definição o controlador é responsável por "preparar os dados para exibição"?
tereško 15/08/12
1
@ tereško: Onde o modelo é "passivo", como descrito aqui msdn.microsoft.com/en-us/library/ff649643.aspx na seção de variações. Veja o "HTTP é um exemplo disso". Embora um purista possa contestar isso, pode ser mais fácil para iniciantes que iniciam no MVC, onde podem estar usando EF ou outros modelos diretamente no controlador e não através de um BAL para pensar nisso dessa maneira, diminuindo a barreira para entender ainda mais o padrão.
precisa saber é o seguinte
1
o que você está falando é "modelo anêmico".
tereško
Ponto observado, removi as descrições ofensivas, como você sugeriu. Felicidades para a entrada!
precisa saber é o seguinte
3

Sugiro que classificar os dados de uma tabela - dados pequenos o suficiente para serem úteis em uma lista suspensa - devam vir do banco de dados já classificado por meio da consulta. Para mim, isso faz do modelo o local em que a classificação é aplicada.

Se você está determinado a fazer a classificação manualmente, acho que existem bons argumentos para usar o modelo ou o controlador como seu local preferido para a lógica. A limitação seria sua estrutura específica. Eu prefiro gerenciar dados apenas no modelo. Eu uso o controlador para casar dados (modelo) e apresentação (exibição), como aprendi (auto).

B0nk3r
fonte
2

Embora eu concorde, em princípio, com a idéia de que a classificação é Business Logic, porque, ao dividir sua origem, você terminaria com algo como "O cliente gostaria que a página do produto fosse exibida com as imagens classificadas por data", então fica claro que a ordem de classificação dos dados geralmente não é arbitrária - mesmo se não houver classificação, pois ainda é uma decisão comercial por omissão (uma lista vazia ainda é uma lista).

MAS ... Essas respostas parecem não levar em conta os avanços na tecnologia ORM, só posso falar em relação ao Entity Framework (vamos evitar uma discussão sobre se isso é verdadeiro ORM, esse não é o ponto) da Microsoft como é isso que eu uso, mas tenho certeza de que outros ORMs oferecem funcionalidade semelhante.

Se eu criar uma exibição fortemente tipada para uma classe de produto usando o MS MVC e o Entity Framework e houver um relacionamento de chave estrangeira entre a tabela Product e Image (por exemplo, FK_Product_Image_ProductId), seria possível classificar rapidamente as imagens durante a exibição usando algo parecido com isto na exibição:

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

Houve menção a uma camada específica de lógica de negócios, que eu também uso para executar 80% da minha lógica de negócios, mas não gravarei funcionalidade de classificação na camada de lógica de negócios que imite algo que vem pronto para uso do Entity Framework.

Acho que não há uma resposta correta para essa pergunta, além de dizer isso; você deve abstrair lógica de negócios complexa sempre que possível, mas não ao custo de reinventar a roda.

Roubar
fonte
Eu estava pensando a mesma coisa, as respostas aqui não parecem levar em consideração os ORMs e os métodos de extensão. Na maioria dos casos, a lógica de classificação será tão simples quanto myList.OrderBy(x => x.CreationDate)- realmente não há necessidade de introduzir nenhuma camada extra desnecessária apenas para fazer isso. Para adicionar isso, o que eles fariam se precisassem de dados paginados e classificados? Consulte a tabela inteira, classifique-a e mantenha o que eles precisam? Pode-se simplesmente ligar myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize)e nenhum dado desnecessário é recuperado.
Balázs
1

Suponha que você tenha o site MVC, o site WebForms e um aplicativo móvel.

Se você deseja que a classificação seja consistente entre essas camadas de apresentação, diria que você deve classificar fora da camada de apresentação. O serviço seria um bom candidato.

Caso contrário, eu armazenaria essa lógica em um modelo de exibição. Por quê? Porque será reutilizável e facilmente testável.


fonte
0

Dos três que você listou, eu diria que ele pertence ao controlador. Eu realmente não gosto de colocar esse tipo de lógica no controlador, no entanto. Normalmente, crio uma camada de serviço com a qual o controlador se comunica, que será responsável pela comunicação com o armazenamento de dados e pelo manuseio da lógica de classificação. Para pequenas aplicações, é bom ficar no controlador.

Dispensar
fonte
2
Isso colocaria a lógica mais do lado do modelo, correto?
Ryan Kohn
Sim, meu entendimento de uma "camada de serviço" é que faz parte do modelo.
Marvo
0

Esta é uma pergunta feita com o asp.net em mente, mas como alguém mencionou o Rails, pensei que seria interessante considerar o problema nesse contexto. No Rails, é natural e bastante comum executar a classificação juntamente com a recuperação como uma ação do controlador, uma vez que a estrutura e a API do ActiveRecord / ActiveQuery o fornecem. Por outro lado, é possível definir algum tipo de ordem de classificação personalizada para itens estáticos e colocá-la no modelo a ser usado pelo controlador, para que o modelo possa desempenhar um papel na lógica de classificação, mesmo que não execute a operação diretamente. Seja o que for, pode ser seguro dizer que colocar a lógica de classificação na visão geralmente é desaprovada.

Estou um pouco divertido porque algumas respostas são absolutamente contra colocar o tipo no controlador ou no modelo, e as acho muito pedantes para o meu gosto, mas suponho que isso dependa da natureza da estrutura usada e das convenções usuais associadas isto. Também concordo com o comentário de Bill K de que ter a separação em primeiro lugar é mais importante.

prusswan
fonte