Un'espressione EL complessa dovrebbe essere sostituita da un singolo getter javabean?


10

In JSF se ho un componente che esegue il rendering condizionato in base a un numero di variabili qual è il modo ottimale per gestire l'istruzione render ... la logica dovrebbe vivere nella dichiarazione del componente o in qualche forma di classe helper?

La trama del testo viene visualizzata solo quando un animale è un elefante o un cane e l'animale non è muto.

Opzione 1:

Implementazione nella vista:

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

o Opzione 2:

incapsulamento:

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

con implementazione:

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

Quindi entrambi funzionano ... ma qual è il modo giusto di gestire lo scenario?


Per quel particolare esempio userei el. Sembra solo visualizzare i dati correlati. Se hai qualche logica nel tuo codice Java per barking animalscausa, chiamerei questo metodo, dal momento che esiste già. Se si tratta di una logica di visualizzazione utilizzata su più siti, è possibile creare una funzione el da esso.

Il linguaggio delle espressioni era originariamente chiamato il linguaggio delle espressioni possibili più semplice in modo da poter suggerire l'uso previsto. Il mio punto di vista: se si tratta di una logica di visualizzazione, EL potrebbe essere appropriato; se è una logica aziendale, non lo è.
McDowell,

Risposte:


5

Nella maggior parte dei casi, è semplicemente una questione di gusti. Se la tua preoccupazione è semplicemente il riutilizzo della condizione, puoi anche fare:

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

Questo è spesso utile quando l'espressione che devi scrivere coinvolge più di un solo oggetto, ad esempio:

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

Penso che molte persone preferiscano scrivere questo tipo di logica in Java anziché in EL perché il compilatore Java può fare il controllo del tipo nel codice Java (inoltre, la maggior parte degli IDE ha un completamento automatico migliore per Java rispetto ai file .XHTML), il che è un problema per alcuni.

Detto questo, se si tratta di un'informazione sul modello che un giorno potrebbe essere utilizzata in un altro posto (non solo in un'altra pagina Facelets / JSF), ciò costituirebbe un buon motivo per farlo nel proprio codice Java. Nell'esempio che hai fornito, il metodo isBarkingAnimal()fornisce alcune informazioni sul modello ( Animal), che un giorno potrebbe rivelarsi utile quando un altro oggetto (non solo un'altra pagina Facelets) deve sapere se un determinato animale abbaia. Quindi, probabilmente ci andrei.


3

Come regola generale, cerca di mantenere i file .xhtml il più logici possibile, in modo che gestiscano solo la presentazione. Quindi, opta chiaramente per l'opzione 2.


2
È la logica di cui il modello deve preoccuparsi? Se viene usato più di una volta, perché alias usarlo <c:set>o <ui:param>meno sarebbe un'opzione?

Quell'esempio non ha una logica modello dietro di esso. Sposteresti la logica della vista in quella del modello, che genera codice java che non viene nemmeno chiamato all'interno di java. Se la classe si Animaltrova in un altro ambiente (remoto) o se i programmatori lo considerano irrilevante.

1

Personalmente, userei l'opzione n. 2. Mentre so che è molto possibile risolvere il problema usando EL e ottenere un po 'di riutilizzo su documenti xhtml usando funzioni o ui: params sembra davvero mancare della portabilità, manutenibilità e testabilità dell'implementazione del bean Java.

Se uno sviluppatore parla fluentemente EL e Java e possiede entrambi i bean xhtml e Java, non ha molto senso usare EL per fare QUALSIASI valutazione condizionale con una dimensione> 1.

Sembrano esserci troppi vantaggi nell'implementazione sul lato Java:

  • Capacità di appoggiarsi al compilatore IDE +
  • Usa costanti o enumerazioni (per "cane" e "corteccia"), è probabile che vengano utilizzati anche altrove nel codice per i confronti ... se il valore di String cambia è molto divertente dover sostituire manualmente ogni sua occorrenza in un base di codice
  • Invece di dover accedere alla pagina in questione con i dati appropriati, posso esercitare la logica usando i test unitari

Uno degli argomenti principali che ho ascoltato (al di fuori di Stack) a favore dell'opzione 1 è:

"È molto più facile vedere quando viene eseguito il rendering di un componente se si mantiene questa logica nella vista."

Ho scoperto che questo potrebbe essere il caso di un'applicazione nella fase iniziale della sua vita in cui è più leggera e meno complicata. Tuttavia, applicando questa pratica su una scala più ampia e man mano che un'applicazione più piccola matura, può causare un ratto nido di condizionali e diventare un incubo da mantenere. Ecco un paio di esempi simili a quello che ho visto in natura:

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

O il mio preferito, utilizzando più componenti con condizioni di rendering esclusive l'una dell'altra per rappresentare i diversi valori che potrebbero essere visualizzati:

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

È possibile visualizzare fino a 4 testi contemporaneamente? A prima vista non si può dire, sarà necessario un controllo di ogni condizione. Come nota a margine, mi rendo conto che questo esempio è anche un design scadente, in quanto potrebbero essere messi in pratica: scegli ... ma l'ho già visto prima.

Alla fine, questa è ancora teoricamente "vista" logica poiché determina ciò che viene effettivamente visualizzato, quindi c'è un argomento concettuale che dovrebbe vivere nel file xhtml. Il problema che ho riscontrato è che includere una logica come questa nel modello di visualizzazione può rendere il layout molto più difficile da capire a lungo termine e non ho ancora visto che questo metodo di risoluzione del problema comporta vantaggi reali rispetto all'uso di Java implementazione del bean.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.