複雑なEL式を単一のJavaBeanゲッターで置き換える必要がありますか?


10

JSFで、いくつかの変数に基づいて条件付きでレンダリングするコンポーネントがある場合、レンダーステートメントを処理するための最適な方法は何ですか。

テキストwoofは、動物が象または犬であり、動物がミュートになっていない場合にのみ表示されます。

オプション1:

ビューでの実装:

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

またはオプション2:

カプセル化:

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

実装あり:

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

どちらも機能します...しかし、シナリオを処理する正しい方法はどれですか?


その特定の例では、elを使用します。単にビュー関連データのようです。Javaコードに何らかのロジックがある場合barking animals、そのメソッドはすでに存在しているので、そのメソッドを呼び出します。複数のサイトで使用するビューロジックの場合、そこからel関数を作成できます。

式言語は、もともとと呼ばれていた最も簡単な表現言語をそれがその使用目的を示唆するようにします。私自身の見解:それがビューロジックであれば、ELが適切かもしれません。ビジネスロジックの場合はそうではありません。
McDowell 2013年

回答:


5

ほとんどの場合、それは単に好みの問題です。あなたの懸念が単に状態を再利用することであるなら、あなたもそうすることができます:

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

これは、記述する必要のある式が1つ以上のオブジェクトを含む場合に役立ちます。たとえば、

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

JavaコンパイラはJavaコードで型チェックを実行できるため(多くのIDEは.XHTMLファイルよりもJavaのオートコンプリートの方が優れているため)、ELではなくJavaでこのタイプのロジックを記述することを好む人は多いと思います。いくつかのための。

そうは言っても、いつか別の場所(別のFacelets / JSFページだけでなく)で使用される可能性があるモデルに関する情報である場合、Javaコードでそれを実行するのに十分な理由になります。あなたが与えた例では、このメソッドisBarkingAnimal()はモデル(Animal)に関する情報を提供します。これは、特定の動物が吠えるかどうかを(別のFaceletsページだけでなく)別のオブジェクトが知る必要があるときに役立つかもしれません。だから、私はおそらくそれで行きます。


3

経験則として、.xhtmlファイルをできるだけロジックフリーにして、プレゼンテーションのみを処理するようにしてください。ですから、明らかにオプション2に進んでください。


2
モデルが気にする必要のあるロジックですか?それが複数回使用されている場合、なぜそれを使用してエイリアスを付けるのか、<c:set>それとも<ui:param>オプションにならないのですか?

その例の背後にはモデルロジックがありません。ビューロジックをモデルロジックにシフトすると、Java内でさえ呼び出されないJavaコードが生成されます。クラスAnimalが他の環境(リモート)にある場合、またはプログラマーがクラスと無関係である場合。

1

個人的には、オプション#2を使用します。ELを使用して問題を解決し、関数またはui:paramsを使用してxhtmlドキュメント全体で少し再利用することは非常に可能であることはわかっていますが、Java Bean実装の移植性、保守性、およびテスト性に欠けているようです。

開発者がELとJavaの両方に堪能で、xhtmlとJava Beanの両方を所有している場合、ELを使用してサイズが1より大きい条件付き評価を行うことはあまり意味がないようです。

Java側に実装するメリットは多すぎるようです。

  • IDE +コンパイラに頼る能力
  • 定数または列挙型(「dog」と「bark」の場合)を使用します。比較のためにコードの他の場所でも使用されている可能性があります...文字列の値が変更された場合、発生したすべての出現箇所を手動で置き換える必要があります。コードベース
  • 適切なデータを使用して問題のページに移動する代わりに、単体テストを使用してロジックを実行できます

オプション1を支持して私が聞いた(Stack以外の)主な引数の1つは次のとおりです。

「このロジックをビューに保持しておくと、コンポーネントがいつレンダリングされるかがはるかにわかりやすくなります。」

これは、アプリケーションの軽量化と複雑さの軽減の初期段階のアプリケーションに当てはまる可能性があることがわかりました。ただし、この方法を大規模に適用し、小規模なアプリケーションが成熟すると、条件付きのネズミの巣が発生し、維持するのが悪夢になる可能性があります。以下は、私が実際に目にしたものに似た例です。

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

または、私のお気に入り、互いに排他的なレンダリング条件を持つ複数のコンポーネントを使用して、表示される可能性のあるさまざまな値を表す:

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

一度に最大4つのテキストを表示できますか?一見できませんが、各状態のチェックが必要になります。余談ですが、この例はデザインが貧弱であることに気づきました。これらはac:chooseに入れられる可能性があるからです...しかし、これは以前に見たことがあります。

結局のところ、これは実際には何が表示されるかを決定するため、理論的には「表示」ロジックであり、xhtmlに含める必要のある概念的な引数があります。私が見つけた問題は、ビューテンプレートにこのようなロジックを含めると、レイアウトを長期的に理解することがはるかに困難になる可能性があり、問題を解決するこの方法がJavaを使用するよりも実際の利点を持っていることをまだ見ていませんBeanの実装。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.