É possível que a lógica de negócios não penetre na visualização?


31

Eu desenvolvi para vários projetos de aplicativos da web nos últimos 3 anos, tanto pessoais quanto no trabalho, e não consigo descobrir se é possível que pelo menos alguma lógica de negócios não acabe na camada de visualização do aplicativo.

Na maioria dos casos, haverá problemas como "Se o usuário selecionou a opção x, o aplicativo deve permitir que ele forneça informações para y; caso contrário, ele deve fornecer as informações z". Ou faça alguma operação AJAX que aplique algumas alterações ao modelo, mas NÃO as confirme até que o usuário solicite explicitamente. Esses são alguns dos problemas mais simples que encontrei e não consigo descobrir como é possível evitar lógica complexa na exibição.

A maioria dos livros que li descrevendo o MVC geralmente mostra alguns exemplos muito triviais, como operações CRUD que apenas atualizam dados no servidor e os exibem, mas CRUD não é o caso nos aplicativos mais avançados.

É possível obter uma visão sem lógica de negócios?


2
Dê uma olhada nas derivações MVC MVP e MVVM (consulte en.wikipedia.org/wiki/Model_View_Presenter e en.wikipedia.org/wiki/Model_View_ViewModel ), elas podem ser o que você está procurando.
Doc Brown

relacionados (possivelmente uma duplicata): A dissociação entre as classes da interface do usuário
mosquito

2
A visualização é a manifestação externa visível de seus dados e lógica. Não é possível para a exibição NÃO apresentar lógica de negócios. Ou você está dizendo que a visualização não deve conter nenhum código? Você certamente pode criar visualizações somente em HTML.
BobDalgleish

Você pode olhar para a animação do modelo ; Embora isso provavelmente não erradique toda a lógica da camada de visualização , parece que deve levar a uma separação um pouco melhor das coisas.
20249 paul

Penso que uma pergunta melhor é se é melhor para os dados de exibição poluírem o modelo ou é melhor para a exibição conter lógica de exibição que está relacionada à lógica de negócios? Esse é o cenário mais real. Sua pergunta é essencialmente defender a poluição do modelo para apoiar as visualizações, pois essa seria a única maneira de realizar o que você está perguntando.
Dunk

Respostas:


22

É possível obter uma visão sem lógica de negócios?

Acho que essa é uma pergunta enganosamente difícil de responder. (Pergunta instigante!)

Teoricamente, sim, dependendo do que definimos como lógica de negócios. Na prática, a separação estrita se torna muito mais difícil e talvez até indesejável.

A separação de preocupações é uma ótima maneira de pensar na criação de software: fornece idéias sobre onde colocar o código e fornece aos mantenedores uma boa idéia sobre onde procurar o código. Argumentarei que é basicamente impossível para os humanos criar software de trabalho sem separação de preocupações. Nós precisamos disso.

Mas, como em todas as coisas, existem trade-offs. A melhor localização conceitual pode não ser a melhor localização por outros motivos. Talvez exista muita carga no seu servidor da Web, então você adiciona algum javascript às suas páginas da Web para detectar erros de entrada fáceis antes que eles atinjam o servidor; agora você tem alguma lógica de negócios em sua opinião.

A visão em si, por si só, não tem valor sem a lógica de negócios. E para ser eficaz no uso e exibição, implícita ou explicitamente, a exibição terá algum conhecimento dos processos de negócios que estão por trás dela. Podemos limitar essa quantidade de conhecimento e isolar partes dele, mas considerações práticas muitas vezes nos forçarão a "romper" a separação de preocupações.


2
The best conceptual location may not be the best location for other reasons: Bravo !!
Magno C

8

Eu costumo fazer isso: se o usuário selecionou a opção x, a visualização chama

controller->OptionXChanged()

Em seguida, o controlador ativa y na exibição:

view->SetEnableInfoY(True) // suppose False=SetDisable

A visualização notifica o controlador do que acontece sem decidir nada.


+1. Problemas triviais do OP normalmente ser tratada como este em um aplicativo não-trivial
dev_feed

A colocação dessa lógica no controlador tem dois problemas: 1) complica o teste de unidade e é impossível oferecer suporte a várias visualizações dos mesmos dados.
Kevin cline

4

Eu questiono se os exemplos que você descreve são realmente lógica de negócios. Os exemplos que você descreve são operações que podem ser executadas no sistema. Foi assim que você escolheu apresentar as opções ao usuário que talvez pareçam estar executando a lógica de negócios na exibição.

Do ponto de vista "View", ele fornece apenas InfoY ou InfoZ ao sistema. Só porque sua implementação de interface do usuário está fazendo algumas atualizações dinâmicas com base na escolha de um operador (por exemplo, ativar o InfoY ou o InfoZ) não torna a funcionalidade lógica de negócios. É realmente ver a lógica de implementação. Você poderia muito bem ter simplesmente dado ao operador a opção de inserir o InfoY ou o InfoZ sem toda a ativação. Nesse contexto, você ainda consideraria a lógica de negócios? Caso contrário, o mesmo se aplica para ativar / desativar dinamicamente os campos de informações.

O mesmo vale para o exemplo de confirmação. Estas são duas operações separadas que o sistema requer para funcionar corretamente. Sua visualização deve poder iniciar as ações adequadas para executar a funcionalidade desejada. Saber usar o sistema significa que a lógica de negócios está vazando? Posso ver como alguém pode dizer sim, mas se você acredita dessa maneira, a realidade é que não existe separação entre lógica de negócios e nada. Você precisa saber com o que o sistema está fazendo / trabalhando para realizar algo significativo. Caso contrário, seria fácil criar um único View and Controller genérico que funcione com todos os aplicativos MVC concebíveis. O que sabemos é impossível.

Resumindo, acho que sua definição de lógica de negócios não é a mesma que a de outros.


1

Eu trabalho desta maneira (Struts2 + Hibernate):

O My Struts Actions é responsável apenas por mostrar informações no navegador da web. Não estou pensando.

Usuário -> Ação -> Serviço -> Repositório -> Acesso a Dados

Ou:

Quero ver -> Como ver -> O que fazer -> Como obter -> Onde obter

Então, na primeira camada (a visualização), tenho algo como:

public String execute ()   {
    try {
        CourseService cs = new CourseService();
        Course course = cs.getCourse(idCourse);
    } catch (NotFoundException e) {
        setMessageText("Course not found.");
    } catch (Exception e) {

    }
    return "ok";
}

Como você vê, minha "visão" não pensa. Ele está solicitando um serviço (para gerenciar cursos), um curso específico. Esse serviço pode fazer muito mais, como relatórios, seraches e assim por diante. Os resultados são sempre uma lista ou um objeto específico (como o exemplo). Os serviços são a máquina real, aplicam regras e acessam o Repositório (para gerenciar os dados).

Portanto, se eu colocar meus Serviços, Repositórios e DAOS em diferentes bibliotecas, posso usá-lo mesmo em um programa baseado em texto ou em um sistema de desktop baseado em Windows sem alterar nada.

O serviço sabe o que fazer, mas não sabe como mostrar. A exibição sabe como mostrar, mas não sabe o que fazer. O mesmo acontece com Serviço / Repositório: O serviço envia e solicita os dados, mas não sabe onde os dados estão e como levá-los. O repositório "compõe" os dados brutos para objetos de negócios, para que o Serviço possa trabalhar.

Mas o Repositório não sabe nada sobre o banco de dados. O tipo de banco de dados (MySQL, PostgreSQL, ...) refere-se ao DAO.

Você pode alterar o DAO se desejar alterar o banco de dados e ele não deve afetar as camadas superiores. Você pode alterar o repositório se desejar atualizar seu gerenciamento de dados, mas isso não deve afetar o DAO e as camadas superiores. Você pode alterar os Serviços se quiser alterar sua lógica, mas isso não deve prejudicar as camadas acima nem abaixo.

E você pode alterar qualquer coisa à vista, mesmo a tecnologia (web, desktop, texto), mas isso não implica em contato com nada abaixo.

A lógica de negócios é serviço. Mas como interagir com isso é ver. Qual botão para mostrar agora? O usuário pode ver este link? Pense que seu sistema é um programa baseado em console: você deve negar se o usuário errado escolher #> myprogram -CourseService -option=getCourse -idCourse=234ou parar com ele para pressionar as teclas para escrever este comando?

Conversando em sistemas baseados na Web (Struts + JavaEE) Eu tenho um pacote de controlador de GUI separado. Na exibição Ação, dou ao usuário logado e a classe me fornece os botões (ou qualquer elemento de interface que eu queira).

                <div id="userDetailSubBox">
                    <c:forEach var="actionButton" items="${actionButtons}" varStatus="id">
                        ${actionButton.buttonCode}
                    </c:forEach>
                </div>

E

private List<ActionButton> actionButtons;

Lembre-se de manter isso fora dos serviços. Isso é coisa do VIEW. Mantenha-o nas ações do Struts. Todas as interações da interface devem ser totalmente separadas do código comercial real; portanto, se você portar o sistema, será fácil cortar o que não será mais necessário.


1

Na maioria dos casos, haverá problemas como "Se o usuário selecionou a opção x, o aplicativo deve permitir que ele forneça informações para y, caso contrário, ele deve fornecer as informações z"

Essa é a lógica do modelo, não a visão. Pode ser um "modelo de exibição", criado especificamente para suportar a interface do usuário, mas ainda é a lógica do modelo. A sequência de controle é:

  • O controlador anexa um manipulador para exibir eventos
  • View anexa um manipulador para eventos de modelo
  • O usuário seleciona a opção X.
  • A exibição gera um evento "Opção X Selecionada"
  • O controlador recebe o evento e chama model.selectOptionX ()
  • O modelo gera um evento "Estado do modelo alterado"
  • A visualização recebe o evento alterado do modelo e atualiza a visualização para corresponder ao novo estado: inputY.enable(model.yAllowed()); inputZ.enable(model.zAllowed());

UI View Controller Model |.checkbox X checked.> | | | | | .. X selected ...>| | | | |-----> set X ------->| | | | | | |< .............state changed ............| | | | | | |-------------- Get state --------------->| | | | | | |<----------- new state ------------------| | <-- UI updates ------| Este é o padrão clássico do MVC. É possível testar completamente a lógica do modelo separada da interface do usuário. O controlador e a visualização são muito finos e fáceis de testar.

=== Em resposta a Dunk ===

O modelo em um padrão MVC da interface do usuário (geralmente) não é um modelo de objeto de negócios. É apenas o modelo para o estado da interface do usuário. Em um aplicativo de desktop, ele pode conter referências a vários modelos de negócios. Em um aplicativo Web 2.0, é uma classe Javascript que mantém o estado da interface do usuário e se comunica via AJAX com o servidor. É muito importante poder escrever testes de unidade sem interrupção do modelo de estado da interface do usuário, pois é onde a maioria dos bugs da interface do usuário é encontrada. A vista e o controlador devem ser conectores muito finos.


1
Eu acho que tudo se resume ao que você acredita que seja a definição de MVC. Esta versão definitivamente segue uma interpretação muito, muito rigorosa do MVC. O problema é que essa interpretação rigorosa raramente fornece um sistema útil ou sustentável na vida real. A razão é que, toda vez que você cria um novo elemento de interface do usuário / maneira de fazer algo, você precisa alterar o modelo. O modelo fica entulhado de propriedades inúteis relevantes apenas para a interface do usuário. Isso não tem nada a ver com o aplicativo que você está tentando criar, mas apenas como deseja apresentar os dados ao operador. RUIM!
Dunk

kevin, coloque suas respostas aqui na caixa de comentários, para que seja fácil respondê-lo. Eu concordo com você. Não é possível manter informações da interface (UI) sem nenhum tipo de estrutura, mas a nomenclatura "MODEL" pode ser confusa. Prefiro gerenciar as coisas da interface do usuário em um pacote intercambiável diferente para facilitar o que o @Dunk está falando. Veja minha resposta.
Magno C

@ MagnoC: Eu editei a resposta em resposta a Dunk porque achei que o texto adicionado melhorava a resposta. É disso que trata o site: perguntas e respostas. Modelo é um termo bastante geral e, no padrão MVC, significa "modelo de estado da interface do usuário".
Kevin cline 23/05

0

Uma lógica de negócios é mais parecida If X then return InfoType.Y; a interface do usuário exibirá campos com base no resultado retornado pelo domínio.

// Controller method pseudocode
option changed routine

    get selected option

    get required info type from domain routine based on selected option

    display fields based on required info type

Se a interface do usuário exigir uma lógica comercial, delegar a opção ao domínio. A interface do usuário simplesmente agirá de acordo com a decisão.


0

Se o usuário selecionou a opção x, o aplicativo deve permitir que ele forneça informações para y, caso contrário, ele deve fornecer as informações z ".

Existem entradas que têm valores obrigatórios com base condicional. Na maioria dos ambientes de GUI, há muitas opções de como lidar com entradas, especialmente o tempo. A opção selecionada (neste caso x) precisa ser processada, então envie-a para o controlador. Envie quando os usuários deixarem o campo de entrada. Espere até eles clicarem em outro objeto ou clicar em salvar. Não importa para a lógica de negócios. De uma forma ou de outra, o controlador tomará uma decisão e precisará informar a exibição "é necessário".

Como a visão interpreta ou implementa isso realmente não importa do ponto de vista da lógica de negócios. Faça o seu campo obrigatório. Faça um pop-up ou atire em um canhão e diga ao usuário para entrar em y ou apenas seja teimoso e não deixe o pobre usuário fazer nada até que ele descubra isso.

E pense: tudo isso pode ter ocorrido porque o controlador tentou salvar e não colocou um valor para um campo obrigatório no banco de dados e estava respondendo apenas a um erro no banco de dados. Não importa no que diz respeito à vista.

Algo como um valor obrigatório ou limitado para uma entrada pode ser tratado em muitos lugares. Se você "apenas" o abordar na visualização, muitos desenvolvedores verão isso como um problema quando houver várias interfaces com o usuário. É por isso que a lógica de negócios pode ser criada e testada sem muito da interface do usuário ou mesmo do banco de dados. Você nem precisa ter um site.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.