弁護士ドットコム株式会社 Creators’ blog

弁護士ドットコムがエンジニア・デザイナーのサービス開発事例やデザイン活動を発信する公式ブログです。

デザイナーに優しいHTMLテンプレートの開発方針をボトムアップで作った話

開発現場で起こっている問題を付箋で分析している様子。「起きていること」「原因」に分け、矢印で対応関係が示されている。起きている問題の例としては「viewにPHPが多い」「CHtml系がノイズ」など。原因の例としては「viewに書けちゃうから」「方針の欠如」などが挙げられている。

はじめに

こんにちは。弁護士ドットコム UX エンジニアの白井です。社名にもなっている 弁護士ドットコム というサービスを運営する専門家プラットフォーム事業本部に所属し、普段は開発業務やユーザーリサーチに携わっています。

この記事では、デザイナーとエンジニアが日々の開発を行ううえで課題となっていた HTML テンプレートの実装方法について、どのようなプロセスを通じて改善していったのかについて詳しくご紹介します。

HTML テンプレートとは

一般的に、Web アプリケーションから HTML を出力するにはHTMLテンプレートというものを用意します。

HTML テンプレートには通常の HTML の構文に加え、変数・繰り返し・条件分岐といった特別な構文が用意されています。 これらの機能を利用することで、同じテンプレートであっても異なるデータからさまざまな Web ページを動的に生成できます。

以下は HTML テンプレートの例です。

<!DOCTYPE html>
<html>
  <head>
    <title>{{ title }}</title>
    ...
  </head>
  <body>
    ...
    <ul id="menu">
      {% for menuItem in menuItems %}
      <li><a href="{{ menuItem.url }}">{{ menuItem.title }}</a></li>
      {% endfor %}
    </ul>
    ...
  </body>
</html>

この HTML テンプレートにデータを渡して出力させた HTML の例が以下です。

<!DOCTYPE html>
<html>
  <head>
    <title>ログイン画面</title>
    ...
  </head>
  <body>
    ...
    <ul id="menu">
      <li><a href="/apple">りんご</a></li>
      <li><a href="/banana">バナナ</a></li>
      <li><a href="/coconut">ココナッツ</a></li>
    </ul>
    ...
  </body>
</html>

{{ title }}{{ menuItem.url }} のような変数部分が実際の値に置き換わっているのがわかるかと思います。 また for 文による繰り返しが展開され、 <li> 要素が 3 個に増えています。

HTML テンプレートを利用すると、プログラムのロジックと HTML の記述を分離できます。特別な構文を少し学習する必要はあるものの、最終的に出力される HTML に近い形でテンプレートを記述できます。

HTML テンプレートを扱う仕組み

これらの HTML テンプレートを処理するツールとしてテンプレートエンジンと呼ばれるものがあります。

テンプレートエンジンはアプリケーションから渡されたデータを HTML テンプレートに埋め込んだり、繰り返しや条件分岐などの構文を解釈したりして最終的な HTML を生成するソフトウェアです(通常、テンプレートエンジンごとに異なる構文が使われます)

また多くのテンプレートエンジンは HTML エスケープ処理(※ HTML 構文が壊れないように、特定の文字を安全な文字で置き換える処理)を自動的に行ってくれるため、エスケープの漏れが防げるというのも嬉しい点です。

昨今の PHP アプリケーションでは、 TwigBlade などのテンプレートエンジンが多く使われています。

一方、弁護士ドットコムではテンプレートエンジンを利用しておらず、生の PHP ファイル(.php ファイル)を HTML テンプレートとして利用しています。

弁護士ドットコムでは PHP のアプリケーションフレームワークとして Yii 1.1 を採用しているのですが、Yii 1.1 の標準構成ではテンプレートエンジンが利用できないためこのような構成になっています。

生の PHP で記述した HTML テンプレートは以下のようなイメージです。

<!DOCTYPE html>
<html>
  <head>
    <title><?= CHtml::encode($title) ?></title>
    ...
  </head>
  <body>
    ...
    <ul id="menu">
      <?php foreach ($menuItems as $menuItem): ?>
      <li><a href="<?= CHtml::encode($menuItem->url) ?>"><?= CHtml::encode($menuItem->title) ?></a></li>
      <?php endfor ?>
    </ul>
    ...
  </body>
</html>

通常だとテンプレートエンジンが自動的に行なってくれる HTML エスケープ処理を自前で行う必要があるため Yii の CHtml::encode() 関数を利用しており、少し記述量が増えています。

また PHP ブロック(<?php 〜 ?>)には任意の PHP コードを記述できます。そのため、テンプレートエンジンの枠を超えたさまざまな機能が利用可能になっています(良くも悪くも)。極端な話、HTML テンプレートからデータベースにアクセスするといったお行儀の悪いこともできてしまいます。

HTML テンプレート開発上の課題

この HTML テンプレートの開発においてどのような問題が起こっていたのか見ていきましょう。

弁護士ドットコムの日々の開発では、以下のような手順で HTML テンプレートの実装を行う場合が多いです(チームにもよります)

  • 【デザイナー】 HTML マークアップを行う
  • 【デザイナー】 CSS コーディングを行う
  • 【エンジニア】 PHP や JavaScript(TypeScript) でロジックを組み込む

デザイナーがデザインから HTML/CSS の実装まで一貫して行うため、巷でよく聞く「デザイナーから実現不可能なデザインが上がってくる」であるとか「デザイナーの意図通りにデザインが実装されない」といった問題は起こっていません。

一方 HTML テンプレートとして生の PHP ファイルを利用しているため「エンジニアが HTML テンプレートに気軽に PHP コードを書きすぎてしまい、デザイナーが修正しづらくなっている」という問題が頻発していました。

例えば、以下のような <img> タグを出力することを考えます。

<img src="/img/icon.png" alt="アイコン">

これを Yii 1.1 のヘルパー関数を使って PHP で書くと以下のようになります。

<?= CHtml::image('/img/icon.png', 'アイコン') ?>

このコードに新たに class 属性を追加したい場合、どうすればよいかわかるでしょうか。 実は src, alt 以外の属性は第3引数で渡す仕様になっており、以下のように記述する必要があります。

<?= CHtml::image('/img/icon.png', 'アイコン', ['class' => 'icon-class']) ?>

HTML テンプレートにこのような記述が多く使われていると、HTML の知識しかないデザイナーにとっては

  • PHP の知識が要求される(<?= 〜 ?><?php 〜 ?>が PHP のコードであることを知っている必要がある)
  • Yii 1.1 の知識が要求される(CHtml::image() の仕様を知っている必要がある)

という状況になっており、修正するには詳しいエンジニアにその都度質問する必要が生じてしまっていました。

またデザイナーだけでなく、新しく入ってくるエンジニアも Yii 1.1 を使った経験のない人ばかりなので、修正に戸惑う場合がありました。

上記の例では Yii のヘルパー関数を使う積極的な理由はないため、単に <img> タグを書けば良いはずです。 しかし、実際の現場ではエンジニアがなんとなく Yii のヘルパー関数を使っているケースが多く、そのテンプレートを修正するデザイナーやエンジニアの認知負荷向上や作業効率の低下に繋がってしまっていたのでした。

なぜ HTML テンプレートが重要か

個人的に、このような HTML テンプレート開発の現状を以前から問題視していました。理由はいくつかあるのですが、大きくは以下のふたつが挙げられます。

(1) HTML マークアップの品質に悪影響がある

HTML マークアップの品質が高いと以下のようなメリットがあります。

  • スクリーンリーダーなどのアクセシビリティ支援技術が正しくページを解釈できるようになる
  • 検索エンジンのクローラーが正しくページを解釈できるようになる

PHP コードにまみれた理解しにくい HTML テンプレートでは、適切な文書構造を定義しようにも見通しが悪かったり、タグの閉じ忘れなどの単純なミスが起こる確率も高まると考えられます(もちろん、linter や validator などの適切なツールを利用することで多くのミスは防げると思います)

(2) 開発効率への影響が大きい

弁護士ドットコムは一般の利用者向け機能・弁護士の先生向け機能・社内向け機能も含め、PHP コードだけでも 6,000 ファイル・ 50 万行超えのアプリケーションとして構成されています。その中でも HTML テンプレートは約 20 %という多くの割合を占めています。

また開始して 10 年以上経つ成熟したサービスですので、大規模な新機能を日々追加していくというよりは、既存の機能をブラッシュアップしていくケースの方が多くなります。 となると、日々の開発の中でもフロントエンド部分の開発にかける時間はかなりの比率にのぼります。 したがって、HTML テンプレートの開発効率が改善されることは全体の開発効率の向上にもつながると考えました。

何より、同じチームで働くデザイナーさんたちが苦労するのを間近で見ていたため「なんとかしてあげたい」という気持ちが強かったのも理由のひとつです。

そこで、実際に改善に向けて動くことにしました。

"Tech Focus Day" のテーマとして改善活動を開始

当初、前述のような状況が起こる原因は「生の PHP ファイルを HTML テンプレートとして利用しているため、エンジニアが自由に PHP コードが書けてしまう」ことだと考えました。

エンジニアの観点からすると、それが適切なアーキテクチャなのかはさておき、HTML 出力に関わるロジックは HTML テンプレートに直接書いてしまうのが一番楽ではあります。それを長年繰り返した結果、PHP コードだらけの HTML テンプレートが生まれてしまったと考えたのです。

そこで、まず考えたのがテンプレートエンジンの導入です。多くのテンプレートエンジンでは PHP コードを直接記述できません。 テンプレートエンジンを導入すれば気軽に PHP コードが書かれることがなくなり、素の HTML に近いテンプレートになるのではと考えたのです。 (※テンプレートエンジンによっては、PHP コードが記述できる構文を用意しているものもあります)

ちょうど、私の所属する専門家プラットフォーム事業本部には Tech Focus Day と呼ばれる制度があり、毎週金曜日に技術的負債や開発効率向上に着目した改善が行われていました。 そこで「弁護士ドットコムへのテンプレートエンジン導入」を Tech Focus Day のテーマのひとつとして取り組むことを提案しました。

Tech Focus Dayでテンプレートエンジンの導入を提案した資料の概観
テンプレートエンジンの導入を提案した際の資料

テーマは無事採択され、提案した私に加え、サーバサイドエンジニアの小宮山がメンバーとしてアサインされました。

小宮山は 入社直後に約50個の不要なテーブルを断捨離したりメタプログラミングを駆使して大規模な静的解析を導入したりとレガシーコードの改善で成果を上げているエンジニアです。 (実はこのブログも小宮山が中心となって立ち上げたものです)

この二人でテンプレートエンジン導入に向けて動き出すことになりました。

いきなりのピボット。そして本当に必要だったもの

早速ふたりでテンプレートエンジンの技術選定を開始しました。

技術選定の要件を整理する中で、弊社のテクニカルアドバイザーであり BEAR.Sunday フレームワークの開発者でもある郡山ともディスカッションを実施しました。

その中で、郡山から以下のような指摘を受けました。

  • テンプレートエンジンは数多くあるが、開発コミュニティごとに開発方針は異なる。例えば、文字列の HTML エスケープひとつをとっても「暗黙的にテンプレートエンジン側がやってくれるべき」派と「明示的に開発者がエスケープの種類や適用箇所を指定すべき」派がある
  • どのテンプレートエンジンを導入するかは、弁護士ドットコムの開発方針や開発に関わるエンジニア陣の意見に従って選んだほうが良い

この指摘を受け、私と小宮山が感じたのは 「そもそも弁護士ドットコムの開発を行ううえで、明確な開発方針というものが存在しないのではないか」 ということでした。

弁護士ドットコムの開発には常時 20 人前後のエンジニアが関わっていますが、明文化された開発方針はほとんど存在せず、日々のコードレビューによってコード品質を担保している状況でした。また長年運営しているサービスですので、リポジトリ内に複数のアーキテクチャやコーディングスタイルが混在しています。そのため、新しく入ったメンバーがどの書き方を参考にして良いかわからない、という問題もたびたび発生していました。

このような状況ではどのテンプレートエンジンが適切かわかりません。無理やり何らかのテンプレートエンジンの導入を進めても他のエンジニアに問題意識が共有できず、日々の開発で利用されない可能性がありました。

一方、既存コード移行の問題もあります。テンプレートエンジンに移行するためには従来の HTML テンプレートに大量に記述された PHP コードを剥がしていく必要がありますが、開発方針なしには移行方法についてエンジニア間で意見が割れることも考えられました。

そこで、開発方針の欠如も含め、何が問題となっているのかあらためて分析することにしました。

あらためて問題定義

まず、私と小宮山でエンジニアとしての視点での問題分析を実施しました。

開発の現場や実際のコードに見られる問題点を洗い出し、その原因と対策案を整理しました。

起こっている問題・原因・対策案を書き出した図。たくさんの付箋が並べられ、その対応関係が分析されている
問題・原因・対策案を書き出した図

その結果、問題は多岐に渡り、対策も多く考えられるものの、やはり「開発方針がない」という点が根本にあり、これを解決することがコスパが良いということが見えてきました。

一方、開発方針を立案していくには具体的にどのような問題が起こっているか把握する必要があります。 そこで弁護士ドットコムの開発に関わるデザイナー陣に協力してもらい、普段 HTML テンプレート開発を行ううえでの困りごとについてヒアリングを行いました。

あるデザイナーさんは、今までに困ったことを大量に Notion でまとめて提供してくださいました。

デザイナーさんがまとめてくれた困りごとの資料の一部。「aタグ内に画像を入れたいがCHtml::linkに阻まれる」「既存ページを参考にしようとすると色んな書き方があってどれが正解かわからない」といった具体的な例が記載されている。
デザイナーさんがまとめてくれた困りごと(一部)

ヒアリングの結果大小さまざまな困りごとが出てきましたが、冒頭でも述べたような「Yii 1.1 のヘルパー関数で作られた HTML タグを修正しづらい」といった点がやはりネックになっていることが確認できました。

HTMLテンプレート開発方針の策定

具体的な問題点が見えてきたところで、これらを解決するような HTML テンプレートの開発方針を策定することにしました。

テンプレートエンジンを導入しなくても、なるべく素の HTML に近くデザイナーにも理解しやすい HTML テンプレートが開発できることを目指し、以下のような具体的な内容を含めました。

  • PHP の高度な構文や演算子を利用しない
  • HTML タグを生成するためだけに、Yii 1.1 のヘルパー関数を使わない
  • 複雑なロジックは HTML テンプレートに直接書かず、適切なクラスに切り出す(そしてテストを書く)
  • 複雑な構造のデータを HTML テンプレートに渡さない
  • ほか多数

禁止事項を列挙するだけでなく、

  • なぜこのガイドラインが存在するのか(この書き方にはどのような問題があるか)
  • 代わりにどう書けば良いのか

といった内容を盛り込み、開発に関わるエンジニア陣が迷わずに実装できるように配慮しました。

また Key words for use in RFCs to Indicate Requirement Levels を参考に、 MUST NOT, SHOULD NOT などの要求レベルも明示することで「決してやってはいけない」ものなのか「理由があれば破って OK」なものなのか判断できるように工夫しました。

これらを弁護士ドットコムの全エンジニアが関わる会議に持っていき、エンジニア陣による意見募集や投票を行いました。

意見募集には匿名の Google フォームを利用しました。 この形式を選択したのは、多人数が参加する会議での発言のしにくさに配慮したのと、じっくり時間をかけて検討してほしかったためです。

意見募集に利用したGoogleフォームの画面。「PHPの高度な構文や演算子を利用しない」といった方針ごとに賛成か反対か表明できるようになっている。また、反対の場合にはその理由を記述できる。
投票に利用したGoogleフォーム

またフォームでは方針ごとに賛成か反対かを表明でき、反対の場合にはその理由を記述できるようにしました。 反対意見の中にも考慮すべきものが含まれていると考えたためです。実際、いくつかそういった意見があり、最終的な開発方針に反映できました。

このようなプロセスを数回繰り返し、無事にエンジニア陣の合意形成に至りました。

今回策定した開発方針はまだまだ発展途上ですが、日々の開発上の意思決定に寄与し、よりデザイナー・エンジニアの双方にとって開発しやすい HTML テンプレートの実現に貢献できればと願っています。

おわりに

今回は HTML テンプレートの開発を例に、ボトムアップで開発方針を策定した事例をご紹介しました。

個人的な反省点は、最初にテンプレートエンジンの導入という「手段」に飛びついてしまったことです。

私の好きな言葉に “There are no solutions. There are only trade-offs.” というものがありますが、あらゆる問題を綺麗に解決できる万能の手段はありません。そこには必ずトレードオフが存在します。

あくまで技術は手段に過ぎないため、何が問題なのかを見極めないことには正しい技術を選択できません。問題の種類によっては「あえて技術を導入しない」ということがベストである場合もあります。

今回は一度足を止めて問題定義をしっかりと行うことで、より効果の高い解決手段に辿り着くことができたと考えています。

これからも、デザイナー・エンジニアの双方にとって開発しやすい仕組みづくりを続け、ユーザーの方により多くの価値を届けていきたいと思います。

この事例が少しでも皆さんの日々の開発の参考になれば幸いです。