Como posso separar a interface do usuário da lógica de negócios, mantendo a eficiência?

19

Digamos que eu queira mostrar um formulário que represente 10 objetos diferentes em uma caixa de combinação. Por exemplo, quero que o usuário escolha um hambúrguer de 10 diferentes que contenham tomate.

Como eu quero separar a interface do usuário e a lógica, eu teria que passar para o formulário uma representação de string dos hambúrgueres para exibi-los na caixa de combinação. Caso contrário, a interface do usuário teria que cavar nos campos de objetos. Em seguida, o usuário pegava um hambúrguer na caixa de combinação e o enviava de volta ao controlador. Agora o controlador teria que encontrar novamente o referido hambúrguer com base na representação de string usada pelo formulário (talvez um ID?).

Isso não é incrivelmente ineficiente? Você já tinha os objetos dos quais queria escolher um. Se você enviou ao formulário os objetos inteiros e depois retornou um objeto específico, não seria necessário refizê-lo posteriormente, pois o formulário já retornou uma referência a esse objeto.

Além disso, se eu estiver errado e você realmente enviar o objeto inteiro para o formulário, como posso isolar a interface do usuário da lógica?

Uri
fonte
De que maneira seria ineficiente? Em todo o caso, você precisa mostrar uma representação de string para o usuário e mapear sua resposta para o objeto original.
Simon Bergot
O problema é que, para trabalhar com o referido objeto, tenho que buscá-lo novamente depois que o usuário o escolhe.
Uri

Respostas:

34

Primeiro de tudo, o exemplo que você forneceu não é incrivelmente ineficiente; é apenas um pouco ineficiente; sua ineficiência está abaixo do nível perceptível. Mas, de qualquer forma, vamos prosseguir com a pergunta.

Do jeito que eu entendo, quando falamos de separação entre UI e Logic , entendemos evitar o acoplamento próximo .

O acoplamento próximo refere-se à situação em que a interface do usuário conhece (e chama) a lógica e a lógica conhece (e chama) a interface do usuário. Para evitar o acoplamento estreito, não é necessário recorrer à abolição total do acoplamento. (É para isso que você parece estar procurando demolir a interface entre eles até uma interface de cadeia de denominadores menos comuns.) Tudo o que você precisa fazer é empregar acoplamentos frouxos .

Um acoplamento fraco significa que A conhece B, mas B não conhece A. Em outras palavras, as duas partes envolvidas desempenham funções distintas de cliente e servidor , onde o cliente conhece o servidor, mas o servidor não o conhece.

No caso de interface do usuário e lógica, a melhor maneira de organizar isso na minha opinião é vendo a lógica como um servidor e a interface do usuário como um cliente. Portanto, a interface do usuário é criada para a lógica, tem conhecimento da lógica e a invoca, enquanto a lógica não sabe nada sobre a interface do usuário e simplesmente responde às solicitações que recebe. (E esses pedidos vêm da interface do usuário, mas a lógica não sabe disso.)

Para colocá-lo em termos mais práticos, em nenhum lugar dos arquivos de código-fonte da lógica você deve encontrar instruções de inclusão / importação / uso que se refiram aos arquivos da interface do usuário, enquanto os arquivos de código-fonte da interface do usuário estarão cheios de inclusão / importação / uso instruções que se referem a arquivos lógicos.

Portanto, voltando ao seu caso, não há absolutamente nada de errado com o fato de que o código da interface do usuário que preenche a caixa de combinação conhece a classe de hambúrguer. Haveria um problema se a turma de hambúrguer soubesse alguma coisa sobre caixas de combinação.

Aliás, esse design permite outra coisa que você deve esperar de um sistema assim: deve ser possível conectar quantas UIs diferentes desejar à lógica, e a coisa toda ainda deve funcionar.

Mike Nakis
fonte
5

Você deve separar cada parte do Model, View & Controller, mas não há razão para que você não possa (por exemplo) passar objetos Model entre o Controller e a View.

Portanto, no seu caso, os Hamburgerobjetos fazem parte do modelo. Você, então, usa o seu Controller para buscar a lista necessária de Hamburgers e passa esses objetos para a View (a caixa de combinação) a ser exibida. Quando o usuário selecionar qual hambúrguer, você poderá passar o Hamburgerobjeto de volta ao Controlador novamente para processamento.

O ponto é que você ainda pode testar em unidade a Hamburgerlógica "buscar " e a lógica "processo Hamburger" separadamente da exibição real de hambúrgueres.

Dean Harding
fonte
Compreendo. No entanto, se eu modificar a classe Hamburguer, não precisarei modificar também o código do formulário que lida com os objetos Hamburguer? Onde está a separação UI-Logic então?
Uri
2
O hambúrguer faz parte do modelo. Quando você modifica o modelo, acaba modificando a visualização e o controlador. O modelo é a separação entre interface do usuário e lógica. Tocar nele tem um custo mais alto; portanto, você deve ter cuidado ao projetá-lo.
Simon Bergot