Sollte ein komplexer EL-Ausdruck durch einen einzelnen Javabean-Getter ersetzt werden?


10

Wenn ich in JSF eine Komponente habe, die basierend auf einer Reihe von Variablen bedingt gerendert wird, wie kann die Render-Anweisung am besten behandelt werden ... sollte die Logik in der Komponentendeklaration oder in einer Form von Hilfsklasse vorhanden sein?

Der Text-Schuss wird nur angezeigt, wenn ein Tier ein Elefant oder ein Hund ist und das Tier nicht stumm ist.

Option 1:

Implementierung in der Ansicht:

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

oder Option 2:

Verkapselung:

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

mit Umsetzung:

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

Also funktionieren beide ... aber wie geht man mit dem Szenario richtig um?


Für dieses spezielle Beispiel würde ich el verwenden. Es scheint nur um verwandte Daten zu sein. Wenn Sie eine Logik in Ihrem Java-Code haben, barking animalswürde ich diese Methode natürlich aufrufen, da sie bereits existiert. Wenn es sich um eine Ansichtslogik handelt, die Sie an mehreren Standorten verwenden, können Sie daraus eine el-Funktion erstellen.

Die Ausdruckssprache wurde ursprünglich als einfachste mögliche Ausdruckssprache bezeichnet, damit sie auf die beabsichtigte Verwendung hinweisen kann. Meine eigene Ansicht: Wenn es Ansichtslogik ist, kann EL angemessen sein; Wenn es Geschäftslogik ist, ist es nicht.
McDowell

Antworten:


5

In den meisten Fällen ist es einfach Geschmackssache. Wenn Ihr Anliegen darin besteht, die Bedingung einfach wiederzuverwenden, können Sie auch Folgendes tun:

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

Dies ist häufig nützlich, wenn der Ausdruck, den Sie schreiben müssen, mehr als nur ein Objekt umfasst, z. B.:

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

Ich denke, viele Leute bevorzugen es, diese Art von Logik in Java anstatt in EL zu schreiben, da der Java-Compiler die Typprüfung im Java-Code durchführen kann (außerdem haben die meisten IDEs eine bessere automatische Vervollständigung für Java als für .XHTML-Dateien), was ein Problem darstellt für einige.

Wenn es sich jedoch um Informationen über das Modell handelt, die eines Tages an einem anderen Ort verwendet werden könnten (nicht nur auf einer anderen Facelets / JSF-Seite), wäre dies ein guter Grund, dies in Ihrem Java-Code tun zu lassen. In dem von Ihnen angegebenen Beispiel isBarkingAnimal()liefert die Methode einige Informationen über das Modell ( Animal), die eines Tages nützlich sein können, wenn ein anderes Objekt (nicht nur eine andere Facelets-Seite) wissen muss, ob ein bestimmtes Tier bellt. Also würde ich wahrscheinlich damit gehen.


3

Versuchen Sie als Faustregel, die .xhtml-Dateien so logikfrei wie möglich zu halten, damit sie sich nur mit der Präsentation befassen. Entscheiden Sie sich also eindeutig für Option 2.


2
Ist es die Logik, um die sich das Modell kümmern muss? Wenn es mehr als einmal verwendet wird, warum sollte ein Aliasing mit <c:set>oder <ui:param>nicht eine Option sein?

Dieses Beispiel hat keine Modelllogik. Sie würden die Ansichtslogik in die Modelllogik verschieben, die Java-Code generiert, der in Java nicht einmal aufgerufen wird. Wenn sich die Klasse Animalin einer anderen Umgebung (Remote) befindet oder von Programmierern übergeben wird, ist dies für sie nur irrelevant.

1

Persönlich würde ich Option 2 verwenden. Obwohl ich weiß, dass es sehr gut möglich ist, das Problem mit EL zu lösen und mithilfe von Funktionen oder ui: params ein wenig Wiederverwendung in xhtml-Dokumenten zu erreichen, scheint es wirklich an Portabilität, Wartbarkeit und Testbarkeit der Java-Bean-Implementierung zu mangeln.

Wenn ein Entwickler sowohl EL als auch Java fließend beherrscht und sowohl die xhtml- als auch die Java-Beans besitzt, erscheint es nicht sinnvoll, EL für JEDE bedingte Bewertung mit einer Größe> 1 zu verwenden.

Die Implementierung auf der Java-Seite scheint einfach zu viele Vorteile zu haben:

  • Möglichkeit, sich auf den IDE + -Compiler zu stützen
  • Verwenden Sie Konstanten oder Aufzählungen (für "Hund" und "Rinde"). Möglicherweise werden sie auch an anderer Stelle im Code für Vergleiche verwendet. Wenn sich der String-Wert ändert, macht es wirklich Spaß, jedes Vorkommen manuell zu ersetzen Codebasis
  • Anstatt mit den entsprechenden Daten zu der betreffenden Seite navigieren zu müssen, kann ich mithilfe von Komponententests Logik üben

Eines der Hauptargumente, die ich (außerhalb von Stack) für Option 1 gehört habe, ist:

"Es ist viel einfacher zu erkennen, wann eine Komponente gerendert wird, wenn Sie diese Logik in der Ansicht behalten."

Ich habe festgestellt, dass dies für eine Anwendung in der Anfangsphase ihres Lebens der Fall sein könnte, in der sie leichter und weniger kompliziert ist. Die Anwendung dieser Praxis in größerem Maßstab und wenn eine kleinere Anwendung reift, kann jedoch dazu führen, dass ein Rattennest von Bedingungen erhalten bleibt und ein Albtraum wird. Hier sind einige Beispiele, die denen ähneln, die ich in freier Wildbahn gesehen habe:

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

Oder mein Favorit, der mehrere Komponenten mit Renderbedingungen verwendet, die sich gegenseitig ausschließen, um die verschiedenen Werte darzustellen, die angezeigt werden könnten:

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

Können bis zu 4 Texte gleichzeitig angezeigt werden? Auf den ersten Blick kann man nicht sagen, dass eine Überprüfung jeder Bedingung erforderlich ist. Als Randnotiz stelle ich fest, dass dieses Beispiel auch ein schlechtes Design ist, da diese in ac gesetzt werden könnten: wählen ... aber ich habe das schon einmal gesehen.

Letztendlich ist dies theoretisch immer noch eine "Ansicht" -Logik, da sie bestimmt, was tatsächlich angezeigt wird, sodass es ein konzeptionelles Argument gibt, das im xhtml enthalten sein sollte. Das Problem, das ich festgestellt habe, ist, dass das Einfügen einer solchen Logik in die Ansichtsvorlage das Layout auf lange Sicht viel schwieriger verständlich machen kann, und ich habe noch nicht gesehen, dass diese Methode zur Lösung des Problems einen echten Vorteil gegenüber der Verwendung von Java bietet Bean-Implementierung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.