Uma expressão EL complexa deve ser substituída por um único getter javabean?


10

No JSF, se eu tiver um componente que é processado condicionalmente com base em várias variáveis, qual é a melhor maneira de lidar com a instrução render ... a lógica deve estar na declaração do componente ou em alguma forma de classe auxiliar?

O texto em woof é exibido apenas quando um animal é um elefante ou cachorro e o animal não é mudo.

Opção 1:

Implementação na visão:

<h:outputText id="text" value="woof" 
  rendered="#{animal.type == 'elephant' 
                  or animal.type == 'dog' and not(animal.mute)}"/>

ou Opção 2:

Encapsulamento:

<h:outputText id="text" value="woof" rendered="#{animal.barkingAnimal}"/>

com implementação:

public class Animal {
     public boolean isBarkingAnimal() {
         return ("dog".equals(getType()) || "elephant".equals(getType())) && !isMute();
     }
...

Então, ambos funcionam ... mas qual é o caminho certo para lidar com o cenário?


Para esse exemplo em particular, eu usaria el. Parece apenas visualizar dados relacionados. Se você tem alguma lógica no seu código java, barking animalseu chamaria esse método, pois ele já existe. Se você usar uma lógica de visualização em vários sites, poderá criar uma função a partir dela.

O idioma da expressão foi originalmente chamado de idioma de expressão possível mais simples, para que possa sugerir o uso pretendido. Minha opinião: se for lógica de exibição, EL pode ser apropriado; se é lógica de negócios, não é.
McDowell

Respostas:


5

Na maioria dos casos, é simplesmente uma questão de gosto. Se sua preocupação é simplesmente reutilizar a condição, você também pode:

<ui:param name="animalCanBark" value="#{animal.type == 'elephant' 
              or animal.type == 'dog' and not(animal.mute)}" />
...
<h:outputText id="text" value="woof" rendered="#{animalCanBark}"/>

Isso geralmente é útil quando a expressão que você precisa escrever envolve mais do que apenas um objeto, digamos:

<ui:param name="showBarking" value="#{animal.type == 'elephant'
              and not facesContext.validationFailed" />

Eu acho que muitas pessoas preferem escrever esse tipo de lógica em Java, em vez de no EL, porque o compilador Java pode fazer a verificação de tipo no código Java (também, a maioria dos IDEs tem um preenchimento automático melhor para Java do que para arquivos .XHTML), o que é uma preocupação. para alguns.

Dito isto, se for uma informação sobre o modelo que um dia possa ser usada em outro local (não apenas em outra página do Facelets / JSF), seria um bom motivo para fazê-lo em seu código Java. No exemplo que você deu, o método isBarkingAnimal()fornece algumas informações sobre o modelo ( Animal), que um dia podem acabar sendo úteis quando outro objeto (e não apenas outra página do Facelets) precisar saber se um determinado animal late. Então, eu provavelmente iria com isso.


3

Como regra geral, tente manter os arquivos .xhtml o mais livres de lógica possível, para que eles lidem apenas com a apresentação. Então, vá claramente para a opção 2.


2
É a lógica com a qual o modelo precisa se preocupar? Se for usado mais de uma vez, por que usar o alias usando <c:set>ou <ui:param>não uma opção?

Esse exemplo não tem lógica de modelo por trás dele. Você mudaria a lógica de exibição para a lógica de modelo, que gera código java que nem é chamado dentro de java. Se a classe Animalestá em outro ambiente (remoto) ou os programadores entregam isso é irrelevante para ela.

1

Pessoalmente, eu usaria a opção 2. Embora eu saiba que é muito possível resolver o problema usando o EL e obter um pouco de reutilização nos documentos xhtml usando funções ou ui: params, parece que realmente falta a portabilidade, a manutenção e a testabilidade da implementação do Java bean.

Se um desenvolvedor é fluente em EL e Java e possui os xhtml e Java beans, não parece fazer muito sentido usar o EL para fazer QUALQUER avaliação condicional com tamanho> 1.

Parece haver muitos benefícios na implementação no lado Java:

  • Capacidade de se apoiar no compilador IDE +
  • Use constantes ou enumerações (para "cachorro" e "latido"), é provável que eles também estejam sendo usados ​​em outras partes do código para comparações ... se o valor da String mudar, é realmente divertido ter que substituir manualmente todas as ocorrências dele em um base de código
  • Em vez de ter que navegar para a página em questão com dados apropriados, posso exercitar a lógica usando testes de unidade

Um dos principais argumentos que ouvi (fora do Stack) a favor da opção 1 é:

"É muito mais fácil ver quando um componente é renderizado, se você mantiver essa lógica em vista".

Descobri que esse pode ser o caso de um aplicativo no estágio inicial de sua vida, onde é mais leve e menos complicado. No entanto, aplicar essa prática em uma escala maior e à medida que uma aplicação menor amadurece, pode causar um ninho de condicionais em ratos e tornar-se um pesadelo para manter. Aqui estão alguns exemplos semelhantes ao que eu vi na natureza:

<h:outputText value="grrr" 
    render="#{animal.type == 'dog' or animal.type == 'cat' or animal.type == 'horse' 
        or animal.type == 'pony' or animal.type == 'mule' or animal.type == 'lion'
        or animal.type == 'tiger' or (animal.type == 'bird' 
        and animal.subType == 'macaw') or .... continue this for another line or two}"
/>

Ou o meu favorito, usando vários componentes com condições de renderização exclusivas um do outro para representar os diferentes valores que podem ser exibidos:

<h:outputText value="grr" render="#{theMonstrosityFromPreviousExample} />
<h:outputText value="cry" 
    render="#{animal.type == 'human' and animal.subType == 'baby'}" />
<h:outputText value="yo" 
    render="#{animal.type == 'human' and animal.subType == 'teenager'}" />
<h:outputText value="hello" 
    render="#{animal.type == 'human' and animal.subType == 'adult'}"/>

Podem ser exibidos até 4 textos de uma vez? À primeira vista, você não pode dizer, será necessária uma verificação de cada condição. Como uma observação lateral, eu percebo que este exemplo também é um design ruim, pois eles podem ser colocados em ac: escolha ... mas eu já vi isso antes.

No final do dia, isso ainda é teoricamente uma lógica de 'visualização', pois determina o que realmente é exibido, para que exista um argumento conceitual que ele deva viver no xhtml. O problema que eu descobri é que incluir uma lógica como essa no modelo de exibição pode tornar o layout muito mais difícil de entender a longo prazo, e ainda tenho que ver que esse método de resolver o problema tem qualquer benefício real em usar o Java implementação de bean.

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.