PowerCMS™
2025年1月1日購入分よりライセンスの価格を改定いたします。
[ブログ] PowerCMS 6 でのアップデートまとめ を追加しました。
[よくあるご質問] システムログに「タスクを実行するために必要なロックを獲得できませんでした」というログが残っている を追加しました。
[よくあるご質問] 特定のシステムログに絞って確認できますか? を追加しました。

PowerCMS ブログ

ホーム > PowerCMS ブログ > テンプレート作成Tips > よいテンプレートとわるいテンプレート

2020年12月25日

よいテンプレートとわるいテンプレート

テンプレートのよしあしを決めるものは何でしょうか。

人によって答えが違うと思いますが、よいテンプレートについては、多くの場合は早いテンプレートやサーバーへの負荷が少ないテンプレートを、わるいテンプレートは逆に時間がかかったりサーバーの負荷が高いテンプレートをあげられると思います。(期待する出力が得られるテンプレートや再構築を行うとエラーが発生するテンプレートは、よしあし以前の問題です)

しかし今回とりあげる「よいテンプレート / わるいテンプレート」は少し視点が異なります。

PowerCMS 製品サポートではテンプレートの書き方はサポートの範囲外となりますが、サポート対応の過程で多くのテンプレートを拝見します。 多くのテンプレートを拝見してきた中で培った「よいテンプレート / わるいテンプレート」は下記の二点です。

  • 適切なテンプレート / 適切でないテンプレート
  • メンテナンスが行いやすいテンプレート / メンテナンスが行いにくいテンプレート

見出しにぴんと来ない方もお付き合いください。

適切なテンプレート / 適切でないテンプレート

適切なテンプレートとは「記事の一覧を出力したいので MTEntries タグを使う」ということ意味ではありません。ここでいう適切なテンプレートは状況や場面に最適なテンプレートです。

例えば記事の一覧 5 件を下記のような HTML で出力する要件の場合、どのようなテンプレートを記述しますか?

<$MTTemplateNote value="出力例"$>
<ul>
    <li>記事1</li>
    <li>記事2</li>
    <li>記事3</li>
    <li>記事4</li>
    <li>記事5</li>
</ul>

次のテンプレートを書きました。

<$MTTemplateNote value="テンプレートの記述例"$>
<MTEntries limit="5">
    <MTEntriesHeader>
        <ul>
    </MTEntriesHeader>
        <li><$MTEntryTitle$></li>
    <MTEntriesFooter>
        </ul>
    </MTEntriesFooter>
</MTEntries>

※ 視認性を高めるためインデントを調整しています

いいですね。万能な記述、どこへ出しても恥ずかしくないテンプレートです。新人が書いてきたら誉めてあげてください。

しかし、もし下記の要件があった場合はどうでしょうか。

  • ウェブサイト(ブログ) には記事が最低1件、常に公開されている
  • 運用で記事の削除や非公開化は行わない

この要件を前提とした場合、テンプレートの記述は次のように修正できます。

<ul>
    <MTEntries limit="5">
    <li><$MTEntryTitle$></li>
    </MTEntries>
</ul>

※ 視認性を高めるためインデントを調整しています

修正前のテンプレートでは 記事が 1 件も公開されていない状況を想定して MTEntriesHeader と MTEntriesFooter タグを使い ul タグだけが出力される状況を回避していますが、記事が 1 件も公開されていない状況が存在しないのであれば ul タグは常に出力される前提で書くことができます。

これが状況や場面に最適なテンプレートです。

いやいやそんな要件ばかりでない、そのような意見の方が多いと思います。たしかに修正前の記述は万能でどこでも使えるテンプレートだと思いますが、出力したい内容が複雑なケースを考えてみましょう。

例えばカテゴリとそれに属する記事の一覧を出力したい場合、カテゴリがないときや記事がない時を考慮すると次のようなテンプレートを書くと思います。

<MTCategories show_empty="1">
    <MTIf name="__first__">
        <ul>
    </MTIf>
    <MTIf tag="CategoryCount" ge="1">
            <li><a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a>
            <MTEntries>
                <MTEntriesHeader>
                    <ul>
                </MTEntriesHeader>
                    <li><$MTEntryTitle$></li>
                <MTEntriesFooter>
                    </ul>
                </MTEntriesFooter>
            </MTEntries>
            </li>
    <MTElse>
            <li><$MTCategoryLabel$></li>
    </MTIf>
    <MTIf name="__last__">
        </ul>
    </MTIf>
</MTCategories>

※ 視認性を高めるためインデントを調整しています

いいですね。万能な記述、どこへ出しても恥ずかしくないテンプレートです。新人が書いてきたら誉めてあげてください。
このテンプレートの利用ケースに下記の要件がある場合はどうでしょうか。

  • カテゴリは1件以上存在する
  • カテゴリには記事が最低1件、常に公開されている
  • 運用で記事の削除や非公開化は行わない

この要件を前提とした場合、テンプレートの記述は次のように修正できます。

<ul>
    <MTCategories>
    <li><a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a>
        <ul>
    <MTEntries>
            <li><$MTEntryTitle$></li>
    </MTEntries>
        </ul>
    </li>
    </MTCategories>
</ul>

※ 視認性を高めるためインデントを調整しています

だいぶすっきりした記述になりました。

これはあくまで要件があってこそできる記述であり常にこのように書くことがその場面にあったテンプレートではありません。 例外に対応しなければならない要件もあると思いますが、修正前と後ではどちらのテンプレートが早く書けるでしょうか。 早く書ければ早く納品でき、コストは抑えられリリースまでにかかる時間も抑えられます。

出力結果は求めるもので、早く納品できるテンプレートはよいテンプレート だと思います。
要件にないためわからない場合も、クライアントと話してみると、例外を考慮して複雑なテンプレートを書くより短い時間ですむかもしれません。

メンテナンスが行いやすいテンプレート / メンテナンスが行いにくいテンプレート

先の適切なテンプレートに比べてとてもわかりやすく、見出しの通りです。書いた担当しか理解できないようなテンプレートはメンテナンスが行いやすいとは言えません。
メンテナンスが行いにくいテンプレートは色々な問題を巻き起こします。

  • 出力結果に問題が起きた場合、修正が難しく、問題の状態が長く続く
  • テンプレートに対して複雑な仕様書が必要
  • 限られた担当しか保守が行えない、保守担当を変更できない

メンテナンスが行いにくいテンプレートの条件はいろいろありますが、目立ったものとしては下記の二種類になります。

誤解しないで欲しいのはテンプレート変数とテンプレートモジュールを使うことが問題ではありません。それぞれにはきちんとしたメリットがあります。
しかしデメリットもあるため、メリットとデメリットのバランスをとって書きませんとメンテナンスが行いにくいテンプレートになります。

メンテナンスを行いにくくするテンプレート変数

次のテンプレートはメンテンナンスが行いにくい記述の一例ですがどこが問題でしょうか。

<$MTVar name="html_block"$>

問題はテンプレート変数 html_block が何を出力するのか、この記述だけではわからないことです。

え、そんなのどんなテンプレート変数だって同じだろう、はい、どのテンプレート変数にも共通して言えることです。テンプレート変数はそういうものと言ってしまえばそれまでですが。 例えば MTEntryTitle タグを使って記事のタイトルを出力している場合、だれが見ても MTEntryTitle タグが出力していると理解できます。

<h1><$MTEntryTitle$></h1>

テンプレート変数の場合、その値を自由に設定できますが、設定と出力が完全に分離するため、その両方を把握してようやく動作を理解できます。

<$MTEntryTitle setvar="entry_title"$>

<h1><$MTVar name="entry_title"$></h1>

仮に変数の名前が entry_title であってもその値が記事のタイトルであるかは変数の設定次第です。それでも下記のような記述に関してはさすがに怒ってよいでしょう

<MTSetVarBlock name="title_core"><$MTEntryTitle$><$/MTSetVarBlock>

<MTSetVarBlock name="h1_title"><h1><$MTVar name="title_core"$></h1><$/MTSetVarBlock>

<$MTVar name="h1_title"$>

entry_title の例はシンプルなので理解することもそれほど難しくないですが、変数の中に変数が入ってくると一変、メンテナーの眉間の皺も本数が増えてきます。

以上の内容はテンプレート変数の利用を否定するものではありません。 テンプレート変数は負荷の軽減はスニペットなど過去の資産の流用によって、コーディングを短時間済ませたり、再構築の負荷を軽減するなど様々な効果がありますが、 テンプレート変数におけるテンプレートの見通しを悪くするデメリットを意識して使うとあなたのテンプレートは「わかりやすくて直しやすい」という評判をえられるでしょう。 面と向かって言われなくても「読みにくくて直しにくいから○○さんのテンプレートには関わりたくない」と避けられることはなくなりますね。

テンプレートモジュール使って共通化している

テンプレートモジュールは主にサイト、テンプレートの共通部分をまとめるために利用するでしょう。

ウェブサイト(ブログ)の垣根を越えて使えることもテンプレートモジュールのメリットの一つで、サイトの規模が大きく複数のウェブサイト(ブログ)で同じ共通化できるとメリットはより大きくなると思います。

しかし、共通する内容が少ないものをテンプレートモジュールにして共用するため、テンプレートモジュールの内容が煩雑になったケースを見かけます。

下記は極端な例ですが、100 のウェブサイト一つのテンプレートモジュールを利用し、そのテンプレートモジュールの中に 100 ウェブサイト分の分岐を設けたケースがあります。

※ テンプレートモジュールの内容

<MTIf name="blog_id" eq="1">
    blog_id=1 用の記述
<MTElsif eq="2">
    blog_id=2 用の記述
<MTElsif eq="3">
    blog_id=3 用の記述
<MTElsif eq="4">
    blog_id=4 用の記述
<MTElsif eq="5">
    blog_id=5 用の記述
(省略)
<MTElse>
    例外の記述
</MTIf>

これは共通部分をまとめていると言ってよいのでしょうか。 たしかに修正するテンプレートは一つへ共通化できていますが、その中にウェブサイトの数だけ分岐があってはウェブサイトごとにテンプレートモジュールがあるのとあまりかわりません。また、分岐がなかった場合でも 100 ウェブサイトで同じテンプレートモジュールを利用しているためテンプレートを修正する場合の影響範囲は 100 ウェブサイト、1 ウェブサイト分の修正を行うために残り 99 ウェブサイト分のリスクを背負って作業しなければなりません。

また、複数のウェブサイト(ブログ)を跨いでテンプレートモジュールを利用する場合、テンプレートモジュールを修正できない場合もあります。 例えばウェブサイトA(blog_id=1)に作られたテンプレートモジュールを、ウェブサイトB(blog_id=2)で利用する場合、ウェブサイトAとウェブサイトBの両方に対してテンプレートを編集する権限がないとメンテナンスは行えず、ウェブサイトBの権限しかない担当者はメンテナンスが十分に行えません。

テンプレートモジュールを利用する際は、その範囲やテンプレートモジュールの内容をよく考えてまとめる必要がありますが、まとめた後のことも考える必要があります。

まとめ

今回、よいテンプレート / わるいテンプレートとして、その場面に最適なテンプレートとメンテナンスの行いやすさについて紹介いたしました。 こんなことは当たり前の方もいらっしゃるでしょうし、今回初めて気づいた方もいらっしゃればよいと考えております。 立ち位置や視点がかわれば異なる気づきがあります。 色々な視点から、自分なりのよいテンプレートやわるいテンプレートを見つけ、よきテンプレートライフ、コーディングライフをおくられますように。

また、本記事の異論反論オブジェクションもお待ちしております。

それでは最後に、記事執筆者が個人的に「悪魔の所業」「親の敵も同然」と思う「わるいテンプレート」を紹介して終わりたいと思います。

<MTIncludeBlock name="$module_name" blog_id="$module_blog_id">
<$MTVar name="$module_contents"$>
</MTIncludeBlock>

まだ数日残っておりますが2020年はありがとうございました。

2021年も何卒よろしくお願い申し上げます。


カテゴリー
サポート
テンプレート作成Tips
トラブルシューティング

Recent Entries