特定のコンテンツのためのコンポーネントとそうでないコンポーネント

CSS Utility Classes and "Separation of Concerns"というTailwind CSS作者の記事を読んだ。そこでは「セマンティック」なコンポーネントと「コンテンツに依存しない」コンポーネントについて言及されていた。

セマンティックなコンポーネントは、

  • author-bio
  • article-preview

のように取り扱うコンテンツの種類をそのまま命名に反映させたものだ。コンポーネントの用途は特定のコンテンツのためだけに限定される。これを特定のコンテンツのためのコンポーネントと呼ぼう。

コンテンツに依存しないコンポーネントは、

  • media-card
  • card-list
  • button

のようにUIパターンを区別するだけの命名がされる。コンポーネントの用途として取り扱うコンテンツの種類を制限しない。これはUIパターンとしてのコンポーネントと呼ぼう。

以下私見

普通は特定のコンテンツのためのコンポーネントの方が専用的だ。同じ種類のコンテンツの表示を別々のコンポーネントで行うことはあまりない。というかそうなるように分ける。たとえば商品詳細と商品属性概要だと、productproduct-teaserのようにそれぞれ別コンポーネントにする。

デザインの個別性が高いサイトほど特定のコンテンツのためのコンポーネントが増える。それは何かしらの理由により共通化が進められていない状態とも言える。だから影響範囲が予測しやすく捨てやすい。反面新しいページで再利用できるコンポーネントは少なくなる。言うまでもなく、実情を見ずにUIパターンとしてのコンポーネントを増やしてしまったりすると、結果的には名前通りの使い方ができない嘘の設計になってしまう。

一方でUIパターンとしてのコンポーネントは汎用的だ。media-cardを使えば、商品でも著者でも記事でも好きなコンテンツを表示できる。

デザインの共通化が進むとUIパターンとしてのコンポーネントが増える。すると再利用できるコンポーネントが増える一方で、個別の違いを持たせるのが難しくなる。汎用性を目的としたUIフレームワークはUIパターンとしてのコンポーネントを中心に構成されていることが多く、スケールさせやすい。逆に特定のプロダクトに特化したPrimerのようなUIフレームワークは特定のコンテンツのためのコンポーネントも多く含む(ただしできるだけ避けるべきと言っている)。

両者には優劣があるわけではなく、必要に応じて併有するものだ。そうしてコンポーネントの役割を明らかにする。やがてサイトが成長するにつれて(あるいは実装が進むにつれて)、それぞれのコンポーネント本当のところはどちら側なのかが浮き彫りになってくる。その段階で改めて命名し直す。この作業によりガイドが適切に引き直される。最初に戻る。

多くの場合、早すぎる共通化は失敗する。つまり特定のコンポーネントが、UIパターンとしてのコンポーネントであるかは慎重に判断すべきだ。

間違った共通化は意図しない再利用を生む。意図しない再利用は非合理的な拡張のきっかけになり、不必要に複雑性を高める。さらには使用箇所を把握しにくくなる。

通化はすぐにできても、個別化は適切な影響範囲の理解と構成要素の分解を要する。それなら安直な共通化は避けるべきだ。

だから僕は必要と思えるタイミングまで、UIパターンとしてのコンポーネントの作成を見送ることが多い。