Faut-il remplacer une expression EL complexe par un seul getter javabéen?


10

Dans JSF, si j'ai un composant qui effectue un rendu conditionnel sur la base d'un certain nombre de variables, quelle est la meilleure façon de gérer l'instruction de rendu ... la logique doit-elle vivre dans la déclaration du composant ou dans une certaine forme de classe d'assistance?

Le texte woof s'affiche uniquement lorsqu'un animal est un éléphant ou un chien et que l'animal n'est pas muet.

Option 1:

Mise en œuvre dans la vue:

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

ou Option 2:

Encapsulation:

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

avec mise en œuvre:

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

Donc, les deux fonctionnent ... mais quelle est la bonne façon de gérer le scénario?


Pour cet exemple particulier, j'utiliserais el. Il semble juste être de visualiser des données connexes. Si vous avez de la logique dans votre code java barking animalscar j'appellerais cette méthode, car elle existe déjà. Si c'est une logique de vue que vous utilisez sur plusieurs sites, vous pouvez créer une fonction el à partir de celle-ci.

Le langage d'expression était à l'origine appelé le langage d'expression le plus simple possible, ce qui peut faire allusion à son utilisation prévue. Ma propre opinion: s'il s'agit d'une logique de vue, EL peut être approprié; s'il s'agit d'une logique métier, elle ne l'est pas.
McDowell

Réponses:


5

Dans la plupart des cas, c'est simplement une question de goût. Si votre souci est simplement de réutiliser la condition, vous pourriez aussi bien faire:

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

Ceci est souvent utile lorsque l'expression que vous devez écrire implique plus d'un seul objet, par exemple:

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

Je pense que beaucoup de gens préfèrent écrire ce type de logique en Java plutôt qu'en EL car le compilateur Java peut vérifier le type dans le code Java (également, la plupart des IDE ont une meilleure autocomplétion pour Java que pour les fichiers .XHTML), ce qui est une préoccupation pour certains.

Cela dit, si c'est une information sur le modèle qui peut un jour être utilisée dans un autre endroit (pas seulement une autre page Facelets / JSF), cela ferait une bonne raison de le faire dans votre code Java. Dans l'exemple que vous avez donné, la méthode isBarkingAnimal()donne des informations sur le modèle ( Animal), qui pourraient un jour s'avérer utiles lorsqu'un autre objet (pas seulement une autre page Facelets) a besoin de savoir si un animal donné aboie. Donc, j'irais probablement avec ça.


3

En règle générale, essayez de garder les fichiers .xhtml aussi libres de logique que possible, afin qu'ils ne traitent que de la présentation. Alors, optez clairement pour l'option 2.


2
Est-ce la logique dont le modèle doit se soucier? S'il est utilisé plus d'une fois, pourquoi l'alias en utilisant <c:set>ou <ui:param>non une option?

Cet exemple n'a aucune logique de modèle derrière. Vous déplaceriez la logique de vue vers la logique de modèle, qui génère du code java qui n'est même pas appelé dans java. Si la classe Animalest dans un autre environnement (distant) ou si les programmeurs ne lui donnent rien de pertinent.

1

Personnellement, j'utiliserais l'option n ° 2. Bien que je sache qu'il est très possible de résoudre le problème en utilisant EL et de gagner un peu de réutilisation dans les documents xhtml en utilisant des fonctions ou ui: params, il semble vraiment manquer de portabilité, de maintenabilité et de testabilité de l'implémentation du bean Java.

Si un développeur parle couramment EL et Java et possède à la fois les beans xhtml et Java, il ne semble pas très logique d'utiliser EL pour effectuer N'IMPORTE QUELLE évaluation conditionnelle avec une taille> 1.

Il semble simplement qu'il y ait trop d'avantages à implémenter du côté Java:

  • Possibilité de s'appuyer sur le compilateur IDE +
  • Utilisez des constantes ou des énumérations (pour "chien" et "aboiement"), il y a de fortes chances qu'elles soient utilisées ailleurs dans le code pour des comparaisons également ... si la valeur de la chaîne change, c'est vraiment amusant de devoir en remplacer manuellement chaque occurrence à travers un base de code
  • Au lieu d'avoir à naviguer vers la page en question avec les données appropriées, je peux exercer la logique à l'aide de tests unitaires

L'un des principaux arguments que j'ai entendu (en dehors de Stack) en faveur de l'option 1 est:

"Il est beaucoup plus facile de voir quand un composant effectue un rendu si vous conservez cette logique dans la vue."

J'ai trouvé que cela pourrait être le cas pour une application au stade initial de sa vie où elle est plus légère et moins compliquée. Cependant, l'application de cette pratique à plus grande échelle et à mesure qu'une application plus petite arrive à maturité, elle peut provoquer un nid de conditionnels chez le rat et devenir un cauchemar à maintenir. Voici quelques exemples similaires à ce que j'ai vu dans la nature:

<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 mon préféré, en utilisant plusieurs composants avec des conditions de rendu exclusives les unes des autres pour représenter les différentes valeurs qui pourraient être affichées:

<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'}"/>

Peut-on afficher jusqu'à 4 textes à la fois? À première vue, vous ne pouvez pas le dire, une vérification de chaque condition sera nécessaire. En remarque, je me rends compte que cet exemple est également de mauvaise conception, car ceux-ci pourraient être mis en ac: choisissez ... mais je l'ai déjà vu auparavant.

À la fin de la journée, cela est toujours théoriquement une logique de «vue» car elle détermine ce qui est réellement affiché, il y a donc un argument conceptuel selon lequel elle devrait vivre dans le xhtml. Le problème que j'ai trouvé est que l'inclusion d'une logique comme celle-ci dans le modèle de vue peut rendre la disposition beaucoup plus difficile à comprendre à long terme et je n'ai pas encore vu que cette méthode de résolution du problème présente un réel avantage par rapport à l'utilisation de Java implémentation du bean.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.