web-dev-qa-db-ja.com

ロジックレステンプレート(口ひげなど)の利点は何ですか?

最近、私は mustache に遭遇しました。これは論理なしテンプレートと主張されています。

ただし、ロジックなしで設計されている理由の説明はありません。別の言葉で、ロジックのないテンプレートの利点は何ですか?

97
Morgan Cheng

言い換えれば、足で自分自身を撃つことを防ぎます。昔のJSPでは、JSPファイルにJavaコードが散在していることが非常に一般的でした。これにより、コードが散在していたため、リファクタリングがはるかに困難になりました。

テンプレートでロジックを防止する場合設計上(口ひげのように)、ロジックを他の場所に配置する必要があるため、テンプレートは整理されます。

別の利点は、懸念事項の分離に関して考えることを余儀なくされることです:データを送信する前に、コントローラーまたはロジックコードがデータmassagingを実行する必要がありますUI。後でテンプレートを別のテンプレートに切り替えた場合(別のテンプレートエンジンを使用するとしましょう)、UIの詳細を実装するだけでよいため、移行は簡単です(テンプレートにロジックがないため、覚えておいてください)。

103
Miguel Ping

私は自分の意見ではほぼ一人だと感じていますが、反対の陣営にしっかりといます。テンプレートにビジネスロジックを混在させることは、プログラミング言語の力をフルに活用しない十分な理由だとは思いません。

ロジックレステンプレートの通常の議論は、プログラミング言語に完全にアクセスできる場合、テンプレート内に場所がないロジックを混在させる可能性があるということです。これは、ナイフを使うと自分で切ることができるので、スプーンを使って肉をスライスする必要があるという推論に似ています。これは非常に真実です。しかし、後者を使用する場合、慎重ではありますが、はるかに生産的です。

たとえば、 mustache を使用する次のテンプレートスニペットを検討します。

{{name}}:
<ul>
  {{#items}}
    <li>{{.}}</li>
  {{/items}}
</ul>

これは理解できますが、次の( アンダースコア を使用して)はるかに単純で直接的なことがわかります。

<%- name %>:
<ul>
<% _.each(items, function(i){ %>
  <li><%- i %></li>
<% }); %>
</ul>

そうは言っても、論理のないテンプレートには利点があることを理解しています(たとえば、変更なしで複数のプログラミング言語で使用できます)。これらの他の利点は非常に重要だと思います。私は彼らの論理のない性質がそれらの1つだとは思わない。

66
brad

口ひげにはロジックがありませんか?

これじゃないですか:

{{#x}}
  foo
{{/x}}
{{^x}}
  bar
{{/x}}

これにかなり似ていますか?

if x
  "foo"
else
  "bar"
end

そして、thatは、プレゼンテーションロジックとかなり似ている(読む:ほとんど定義されている)わけではありませんか?

27
pje

ロジックレステンプレートとは、埋める方法ではなく、埋めるための穴を含むテンプレートです。ロジックは他の場所に配置され、テンプレートに直接マップされます。この懸念の分離は理想的です。なぜなら、テンプレートは異なるロジックで、または異なるプログラミング言語で簡単に構築できるからです。

口ひげマニュアル から:

If文、else節、またはforループがないため、これを「ロジックレス」と呼びます。代わりにタグのみがあります。一部のタグは値で置き換えられ、他のタグは値なしで置き換えられ、他のタグは一連の値で置き換えられます。このドキュメントでは、さまざまな種類のMustacheタグについて説明します。

13
Jeremy

テンプレートをよりクリーンにし、適切に単体テストできる場所にロジックを保持することを強制します。

11
blockhead

コインの裏側は、ビジネスロジックをプレゼンテーションから締め出そうとする必死の試みでは、多くのプレゼンテーションロジックをモデルに配置することになります。一般的な例としては、テーブルの交互の行に「奇数」クラスと「偶数」クラスを配置したい場合があります。これは、ビューテンプレートで単純なモジュロ演算子を使用して実行できます。ただし、ビューテンプレートでそれができない場合は、モデルデータに奇数行または偶数行を格納するだけでなく、テンプレートエンジンの制限に応じて、モデルを汚染する必要があります実際のCSSクラスの名前。ビューはモデルとは別に、完全に停止する必要があります。ただし、モデルはViewに依存しない必要があります。これは、これらの「論理的でない」テンプレートエンジンの多くが忘れさせるものです。ロジックは両方の場所に行きますが、どこに行くかを正しく決定するために、ロジックが実際に何をするかについて慎重に判断する必要があります。それはプレゼンテーションの問題ですか、それともビジネス/データの問題ですか? 100%の自然のままの景色を得るために、汚染は目立たないが同様に不適切な別の場所にたどり着きます。

他の方向に戻っている動きがあります そして、うまくいけば、物事はより合理的な中盤のどこかに集中するでしょう。

11
mattmc3

この会話は、中年の僧ksがピンの端に何人の天使が収まるかについて議論するときのように感じます。言い換えれば、宗教的で、無益で、誤って集中していると感じ始めている。

ミニ暴言が続く(気軽に無視してください):

読み続けたくない場合..上記のトピックに対する私の短い応答は、「ロジックのないテンプレートに同意しません」です。私はそれを過激主義のプログラミング形式と考えています。 :-) :-)

今、私の暴言は本格的に続きます::-)

多くのアイデアを極端に取り入れると、結果は馬鹿げたものになると思います。そして時々(つまり、このトピック)問題は、「間違った」アイデアを極端に取るということです。

ビューからすべてのロジックを削除するのは「滑lu」であり、間違った考えです。

少し戻ってください。

自問する必要があるのは、なぜロジックを削除するのかということです。概念は、明らかに 懸念の分離 です。ビューの処理をビジネスロジックからできるだけ分離してください。どうしてですか?ビュー(さまざまなプラットフォーム:モバイル、ブラウザ、デスクトップなど)を入れ替えることができ、制御フロー、ページシーケンス、検証の変更、モデルの変更、セキュリティアクセスなどをより簡単に入れ替えることができます。ビュー(特にWebビュー)から削除されると、ビューがはるかに読みやすくなり、メンテナンスが容易になります。私はそれを得て、それに同意します。

しかし、最優先の焦点は懸念の分離にあるべきです。 100%ロジックなしのビューではありません。ビュー内のロジックは、「モデル」のレンダリング方法に関連する必要があります。私に関する限り、ビューのロジックは完全に問題ありません。ビジネスロジックではないビューロジックを使用できます。

はい、私たちがJSPを書いた当時、PHPまたはASPコードロジックとビューロジックの分離がほとんどまたはまったくないページ、これらのWebのメンテナンス-appsは絶対的な悪夢でした。信じられますが、私はこれらの怪物をいくつか作成し、維持しました。

したがって、高位(業界の専門家)からのdict令は、フロントビューコントローラー(ハンドラーまたはアクションにディスパッチする[Webフレームワークを選択])のようなものを使用してWebアプリを構築し、あなたのビューにはコードを含めないでください。ビューは愚かなテンプレートになるはずでした。

ですから、私は一般的に上記の感情に同意します。それはdict令の項目の詳細ではなく、むしろdict令の背後にある動機です。それは、見解とビジネスロジックの間の懸念の分離に対する欲求です。

私が関わったプロジェクトの1つで、ロジックのないビューのアイデアを馬鹿げた極端な方法で追跡しようとしました。モデルオブジェクトをhtmlでレンダリングできる独自のテンプレートエンジンがありました。シンプルなトークンベースのシステムでした。それは非常に単純な理由でひどいものでした。ビューの中で、この小さなHTMLスニペットを表示するかどうかを決定する必要がある場合があります。.決定します。通常、決定はモデルの値に基づいています。ビューにロジックがまったくない場合、どうしますか?できません。これについて私たちの建築家と大きな議論がありました。私たちのビューを書いているフロントエンドのHTMLの人々は、これに直面したとき完全にうんざりしており、そうでなければ単純な目的を達成することができなかったため、非常にストレスを感じていました。そこで、テンプレートエンジン内に単純なIFステートメントの概念を導入しました。安reliefとその後の落ち着きを説明することはできません。テンプレートのシンプルなIFステートメントのコンセプトで問題は解決しました!突然、テンプレートエンジンが正常になりました。

それでは、この愚かなストレスの多い状況にどうやって入ったのでしょうか?私たちは間違った目的に焦点を合わせました。ルールに従いました。ビューにロジックを含めることはできません。それは間違っていました。 「経験則」は、ビューのロジックの量を最小限に抑えるべきだと思います。そうしないと、ビジネスロジックが不注意にビューに忍び込んでしまい、懸念の分離に違反する可能性があるからです。

「ビューにロジックがないようにする必要がある」と宣言すると、いつ「良い」プログラマーになったのかが簡単にわかります。 (それがあなたの良さの尺度である場合)。上記のルールを使用して、中程度の複雑さのWebアプリを実装してみてください。それほど簡単にはできません。

私にとって、ビューのロジックのルールはそれほど明確ではなく、率直に言って、それが私が望むところです。

ビューに多くのロジックが表示されている場合、コードのにおいを検出し、ビューからロジックのほとんどを削除しようとします-ビジネスロジックが他の場所に存在するようにします-懸念を分離しようとします。しかし、私がmustと言う人とチャットを始めたとき、私には、すべてのロジックを削除します上記で説明したような状況になる可能性があります。

私は暴言で終わりました。 :-)

乾杯、

デビッド

6
David Balme

論理のないテンプレートについて私が思いついた最善の議論は、クライアントとサーバーの両方でまったく同じテンプレートを使用できるということです。しかし、あなたは本当にロジックレスを必要とせず、それ自身の「言語」を持っているものだけです。私は口ひげが無意味に制限していると不満を言う人々に同意します。感謝しますが、私は大きな男の子です。あなたの助けなしにテンプレートをきれいに保つことができます。

別のオプションは、クライアントとサーバーの両方でサポートされている言語を使用するテンプレート構文を見つけることです。つまり、node.jsを使用するか、therubyracerなどを介してjsインタープリターとjsonを使用してサーバー上のjavascriptを使用します。

次に、これまでに提供されたどの例よりもはるかにクリーンで優れた動作をするhaml.jsのようなものを使用できます。

5
eagspoo

1つの文で:ロジックレスとは、テンプレートエンジン自体がそれほど複雑でないため、フットプリントが小さく、予期しない動作をする方法が少ないことを意味します。

4
Kernel James

質問が古くて答えられていたとしても、私は2¢を追加したいと思います(これは暴言のように聞こえるかもしれませんが、そうではありません。

テンプレートの目標は、ビジネスロジックを実行するのではなく、何かをレンダリングすることです。現在、テンプレートで必要なことを実行できないことと、「ビジネスロジック」をテンプレートに含めることとの間には、細い線があります。口ひげに本当に前向きで、それを使用しようとしましたが、私は非常に簡単な場合に必要なことをすることができなくなりました。

(受け入れられた回答の単語を使用する)データの「マッサージ」は、実際の問題になる可能性があります-単純なパス(Handlebars.jsが対応するもの)でさえサポートされていませんビューデータがあり、テンプレートエンジンが制限しすぎているために何かをレンダリングするたびに微調整する必要がある場合、これは最終的には役に立ちません。そして、口ひげが主張するプラットフォーム独立の一部を打ち負かします。マッサージロジックをどこでも複製する必要があります。

とはいえ、いくつかのフラストレーションの後、他のテンプレートエンジンを試した後、.NET Razorテンプレートに触発された構文を使用する独自の(...まだ別の...)を作成しました。サーバーで解析およびコンパイルされ、シンプルな自己完結型のJS関数(実際にはRequireJSモジュールとして)を生成します。この関数は、テンプレートを「実行」して結果として文字列を返すために呼び出すことができます。 bradが提供するサンプルは、エンジンを使用すると次のようになります(私は個人的に、MustacheとUnderscoreの両方に比べて読みやすいという点ではるかに優れていると感じています)。

@name:
<ul>
@for (items) {
  <li>@.</li>
}
</ul>

Moustacheを使用してパーシャルを呼び出すと、別のロジックのない制限が発生します。 Mustacheはパーシャルをサポートしていますが、最初に渡されるデータをカスタマイズすることはできません。そのため、モジュラーテンプレートを作成して小さなブロックを再利用する代わりに、コードを繰り返してテンプレートを作成することになります。

JPathと呼ばれるXPathに触発されたクエリ言語を実装することでそれを解決しました。基本的に、子をトラバースするために/を使用する代わりに、ドットを使用します。文字列、数値、ブールリテラルだけでなく、オブジェクトと配列(JSONと同様)もサポートされます。この言語は副作用がありません(テンプレート化に必須です)が、新しいリテラルオブジェクトを作成することで、必要に応じてデータを「マッサージ」できます。

カスタマイズ可能なヘッダーと行のアクションへのリンクを持つ「データグリッド」テーブルをレンダリングし、jQueryを使用して動的に行を追加するとします。したがって、コードを複製したくない場合は、行をパーシャルにする必要があります。そして、レンダリングされる列などの追加情報がビューモデルの一部であり、各行のアクションについても同じ場合に問題が始まります。以下に、テンプレートとクエリエンジンを使用した実際の作業コードを示します。

テーブルテンプレート:

<table>
    <thead>
        <tr>
            @for (columns) {
                <th>@title</th>
            }
            @if (actions) {
                <th>Actions</th>
            }
        </tr>
    </thead>
    <tbody>
        @for (rows) {
            @partial Row({ row: ., actions: $.actions, columns: $.columns })
        }
    </tbody>
</table>

行テンプレート:

<tr id="@(row.id)">
    @for (var $col in columns) {
        <td>@row.*[name()=$col.property]</td>
    }
    @if (actions) {     
        <td>
        @for (actions) {
            <button class="btn @(id)" value="@(id)">@(name)...</button>
        }
        </td>
    }
</tr>

JSコードからの呼び出し:

var html = table({
    columns: [
        { title: "Username", property: "username" },
        { title: "E-Mail", property: "email" }
    ],
    actions: [
        { id: "delete", name: "Delete" }
    ],
    rows: GetAjaxRows()
})

ビジネスロジックは含まれていませんが、再利用可能で構成可能であり、副作用もありません。

3
Lucero

以下は、文字数を使用してリストをレンダリングする3つの方法です。最初の最短のもの以外はすべて、ロジックのないテンプレート言語です。

CoffeeScript( Reactive Coffee Builder DSLを使用)-37文字

"#{name}"
ul items.map (i) ->
  li i

ノックアウト-100文字

<span data-bind="value: name"/>
<ul data-bind="foreach: items">
   <li data-bind="value: i"/>
</ul>

ハンドルバー/口ひげ-66文字

{{name}}:
<ul>
  {{#items}}
    <li>{{.}}</li>
  {{/items}}
</ul>

アンダースコア-87文字

<%- name %>:
<ul>
<% _.each(items, function(i){ %>
  <li><%- i %></li>
<% }); %>
</ul>

ロジックレステンプレートの約束は、より幅広いスキルセットを持つ人々が足を踏み入れることなく、ロジックレステンプレートを管理できることだったと思います。ただし、上記の例で見られるのは、文字列ベースのマークアップに最小論理言語を追加すると、結果はより複雑ではなく、より少なくなるということです。また、古い学校のPHPを実行しているように見えます。

明らかに、「ビジネスロジック」(広範な計算)をテンプレートに入れないことに反対しません。しかし、第一級言語の代わりに表示ロジック用の擬似言語を提供することで、代価が支払われると思います。入力するだけでなく、誰かがそれを読む必要があるコンテキスト切り替えの凶悪な組み合わせ。

結論として、私はロジックのないテンプレートのロジックを見ることができません。そのため、それらの利点は私には無かったと思いますが、コミュニティの多くの人がそれを異なって見ることを尊重します:)

2
Dean Radcliffe

私はブラッドに同意します:underscoreスタイルの方が理解しやすいです。しかし、私は構文糖が皆に喜ばれないかもしれないと認めなければなりません。 __.each_がやや混乱している場合は、従来のforループを使用できます。

_  <% for(var i = 0; i < items.length; i++) { %>
    <%= items[i] %>
  <% } %>
_

forifなどの標準的な構造にフォールバックできる場合は、常に素晴らしいです。 <% if() %>または<% for() %>を使用するだけで、Mustacheは_if-then-else_に多少新語を使用します(ドキュメントを読んでいないと混乱を招きます)。

_{{#x}}
  foo
{{/x}}
{{^x}}
  bar
{{/x}}
_

ネストされたテンプレートを簡単に実現できる場合(underscoreスタイル)、テンプレートエンジンは優れています。

_<script id="items-tmpl" type="text/template">
    <ul>
        <% for(var i = 0; i < obj.items.length; i++) { %>
            <%= innerTmpl(obj.items[i]) %>
        <% } %>
    </ul>
</script>

<script id="item-tmpl" type="text/template">
    <li>
        <%= name %>
    </li>
</script>

var tmplFn = function(outerTmpl, innerTmpl) {
    return function(obj) {
        return outerTmpl({obj: obj, innerTmpl: innerTmpl});
    };
};

var tmpl = tmplFn($('#items-tmpl').html(), $('#item-tmpl').html());
var context = { items: [{name:'A',{name:'B'}}] };
tmpl(context);
_

基本的に、内部tmplをコンテキストのプロパティとして渡します。それに応じて呼び出します。甘い:)

ところで、興味のあるものがテンプレートエンジンだけである場合は、スタンドアロンのテンプレート実装を使用します。 900文字のみ縮小(4行):

https://Gist.github.com/marlun78/2701678

1
roland

ロジックレステンプレートを使用する主な利点は次のとおりです。

  • 厳密にモデルビューの分離を強制します。詳細については このペーパー を参照してください(強く推奨)
  • 非常に理解しやすく使いやすい、プログラミングロジック(および知識!)が不要で、構文が最小限であるため
  • (特定の口ひげ)非常にポータブルで、言語に依存せず、ほとんどすべてのプログラミング環境で修正なしで使用できます
1
rmuller