コンポーネント名を明名するときに考えたこと
ニコニコ生放送でフロントエンドを担当している misuken です。
今回はコンポーネント名を並べたときに感じた小さな気付きから視野を広げ、最終的に周辺領域も含めて詳細に明らかにするまでの様子を書きます。
この記事で行われているのは、一般的な 命名 ではなく BCD Design における 明名 (名前は決めるものではなく決まるもの)の工程になると言えます。
コンポーネント名を明らかにするためにどのように捉え、どのように考えていくのかのヒントになれば幸いです。
前提
この記事は BCD Design を基礎とし、以下の記事で紹介した理論を踏まえた内容となっています。
わからない点があったら BCD Design 及び上記二つの記事を参考に読み進めてみてください。
Field
と InputField
の違い
以前の記事 共通部分をスマートに管理するディレクトリ構成 で Field
というコンポーネントを例に挙げましたが、記事を書いている初期段階では Field
という名前ではなく InputField
としていました。
理由は "入力フィールド" は "入力" の単語に対応する Input
が必要になるためです。
しかし、他のコンポーネントと一緒に並べたとき、InputField
とすると若干異物感があります。
Button
Form
Icon
Input
InputField 🤔
Dialog
Label
Link
以下であればとても自然に並んでいると言えます。
Button
Field ✅
Form
Icon
Input
Dialog
Label
Link
これはほんの些細な違いに思えるかもしれませんが、大規模なシステムの場合、小さな歪みが次の歪みを生み、連鎖的に歪みが大きくなるので、基礎に近い部分の歪みを解消することは意外と重要です。
そのため日頃からこのような小さな歪みは何が原因で生まれているのか?歪みを無くして成立する形にするにはどうすれば良いのか?といったことを意識しています。
これまでの知見を踏まえると、上記の部分だけでも以下のことが言えます。
-
InputField
はField
の派生である -
InputField
だとInput
側にまとまって関心の千切りになってしまう - UI層では後方一致のUI名でまとめたほうが望ましい
これはアンチパターンを理解して package by feature への記事を読むとしっかり理解できます。
BCD Design において InputField は Base Case どっち?
InputField
は入力する状況に依存した Input
という単語から始まっているので Case ではないかと思うかもしれません。
しかし、ここで扱っている Input
は TextBox
等の総称としての単語であり、 Input
という抽象的なUIを表しているため Base に該当します。
CheckBox
SelectBox
PulldownMenu
などもUI自体を表す名前であるため、 Base に該当するのと同じ原理です。
ここからは Field
とその派生について分析し、それらの関係性を深掘りすることで、最終的な結論に達するまでの流れを書いていきます。
Field
とその派生について分析する
なぜ InputField
を検討するかと言うと、最初にも述べたように入力UIと連携するものだからです。
また、なぜ人が「入力フィールド」や「入力欄」と言うかといえば、それは入力以外の "フィールド" や "欄" が存在していて、無意識に識別していることを示唆しています。
入力系以外のUIと連携するフィールドがあれば XxxField
となるはずで、 InputField
とは違う系統になります。
そこで、AIに「入力以外のフィールドはありますか?」と尋ねると、代表的なものとして "表示フィールド" DisplayField
というものを挙げてきます。
入力目的ではなく、情報を表示することを目的としたフィールドです。
この時点で InputField
と DisplayField
の中立的な抽象が Field
であるべきで、 Field
自体が "入力" に依存したり "入力" に寄った存在になっていると、対称性や依存関係などの観点から整合性が取れなくなることが想像できます。
DisplayField
を分析する
新たに現れた DisplayField
を分析してみましょう。
DisplayField
は何らかの情報等を表示するコンポーネントと考えられるため、何らかの入力UIと連携する InputField
と似ていると言えます。
しかし、InputField
とは違いがあります。
InputField
の場合は TextBox
と連携して TextBoxField
を作るなど、具体的な入力方法を固めることに意味があるため、UIのみの世界でも具体的なコンポーネントを定義できましたが、 DisplayField
の場合そうはいきません。
LabelField
LinkField
など UI + UI でコンポーネントを定義しようとしても、利用価値のあるものにはならないのです。
DisplayField
は何を表示するかを表そうとすると、ほとんどの場合 BCD Design における Case Common Domain のいずれかに属する単語と連携することになり、UIのみの世界で具象コンポーネントを定義する意味がありません。
つまり、BCD Design の Base に DisplayField
を具体化したコンポーネントはほぼ現れないということを意味します。
DisplayField
の責務を分析する
次に DisplayField
というコンポーネントがどのような責務を持つべきかを分析してみましょう。
DisplayField
は Field
が持つ基本構成に加え、メインの表示部分で children
が渡せるコンポーネントになるはずです。
ここで改めて考えてみるとコンポーネントという存在は常に何かを表示するための存在なので、DisplayField
の Display
に意味はあるのか?という疑問が生まれてきます。
すると DisplayField
は Field
コンポーネントに統合できる可能性が浮上してきます。
例えば DisplayField
に入力系コンポーネントを表示したらそれは InputField
の具象になるのではないかということです。
DisplayField
は Field
なのか?
もしも DisplayField
が Field
自体であると仮定した場合、どのようになるか分析してみます。
DisplayField = Field
ということは、ディレクトリで言うと base/Field/_base = base/Field/DisplayField
ということになります。 (ディレクトリ構成の意味は 共通部分をスマートに管理するディレクトリ構成 を参照)
base
Field
_base // DisplayFieldと同じ
DisplayField // _baseと同じ
base/Field/_base
の children
に TextBox
を連携させたら base/Field/TextBoxField
になります。
base
Field
_base // DisplayFieldと同じ
DisplayField // _baseと同じ
TextBoxField // TextBox + _base
説明を表示する領域として、説明フィールド DescriptionField
というコンポーネントが必要になったとします。
この場合の "説明" はデータ(処理される対象)なので、Common に所属します。"検索" などと違い、それが "説明" という処理自体を行うものではないので Case にならないという解釈になります。(詳細は Case と Common の使い分け を参照)
base/Field/_base
の children
に説明に関する依存を連携したら common/DescriptionField
になります。
base
Field
_base // DisplayFieldと同じ
DisplayField // _baseと同じ
TextBoxField // TextBox + _base
common
DescriptionField // 共通の関心 + base/Field/_base
具体的な説明内容(データ)はより具体的な使用箇所で決まることになりますが、説明フィールド特有のスタイルは DescriptionField
で一元管理できます。
結果、 base/Field/_base
があれば表示フィールドを具体化した説明フィールドを作れることがわかります。
分析の結果
分析の結果はこうなります。
-
DisplayField
の具象が Base 内に現れることは考えにくい -
DisplayField
に入力系UIを組み合わせたらInputField
の具象になり得る -
DisplayField
という概念は存在するものの、それは事実上Field
のことである
この結果を踏まえると以下のように Field
内で InputField
や DisplayField
など複数系統のフィールドを分類する必要が無いことがわかります。
Field
_abstract
DisplayField
InputField
_abstract
CheckboxBoxField
TextBoxField
SelectBoxField
従って DisplayField
と InputField
というディレクトリは不要で、 Field
の直下に TextBoxField
を展開しても特に問題は生じません。
概念的には Field/InputField/TextBoxField
のほうが正しいかもしれませんが、Base の中に表示系フィールドの具象が現れることは考えにくく、上記の理由を理解した上で利便性を優先して Field/TextBoxField
で運用することは、実運用上問題にならないでしょう。
Field
_base
CheckboxBoxField
TextBoxField
SelectBoxField
Field
と InputField
の関係を深掘りする
ここまでの正確性を検証するため Field
と InputField
の関係を深掘りしてみましょう。
もし InputField
を作る必要が出てくるとしたら、決定打になるのは InputField
における Field
部分に入力系特有の依存が含まれるかどうかになります。
依存は主に3つ。
- 実装(定数やロジック)としての依存
- スタイルとしての依存 (入力UI部分は除く)
- DOMとしての依存 (入力UI自体は除く)
実装(定数やロジック)としての依存
入力フィールド系共通で使用する定数があれば Field/InputField/InputField.definition.ts
、 hooks
等のロジックがあれば、 Field/InputField/InputField.hooks.tsx
内に定義するとうまく整理できるはずです。
スタイルとしての依存
入力フィールドと、表示系フィールドで 、内容を除いたフィールド自体が構成する部分のスタイルに違いがあれば入力フィールドに依存したスタイルがあるということになるので Field/InputField/InputField.module.css
が必要になるでしょう。
DOMとしての依存
ここは非常に奥が深いので長くなりますが、重要なのでしっかり説明します。
DOMとしての依存とは、表示系のフィールドには概念上不要で、入力フィールドのみに存在するDOMがあるかどうかです。
- 共通で良さそうなもの
- ラベル
- 入力フィールドのみに依存しそうなもの
- エラーメッセージの表示
- 必須表現
ラベル以外はフィールドのメタ情報で、表示系フィールドと入力フィールドで共通ではないように思えます。
しかし、捉え方を変えるとパラダイムシフトが起こります。
エラーメッセージの捉え方
エラーメッセージとは、エラーのメッセージであり、メッセージの一種です。
他にどのようなメッセージがあるかを思い浮かべると以下が挙げられます。
- 警告を伝えるためのメッセージ
- 補足等の情報を伝えるためのメッセージ
エラーのメッセージと他のメッセージの違いは何があるでしょうか?一般的に考えられるのは以下です。
- 色が違う
- アイコンが違う
つまりこうなります。
DOM的にはアクセシビリティ的な部分でaria属性が違ってきますが、それ以外は構造的に共通で問題ないはずです。
構造的には同一で毛色が違うパターンは以下のように変換できることを意味します。
「エラーとはメッセージにおける属性の一種である」
エラーにはもう一つ面白い関連性があります。
エラーというのはログレベルでもよく使用されますが、そこには一般的に info
warning
error
があるように、メッセージに意味を持たせる上での良いモデル(事実上メッセージという概念の型)になります。 これらはまさにログの属性です。
このモデルの親和性をさらに説明できる良いものがあります。
JavaScript でも console.log
に属性を付けられる以下の関数があり、色 アイコンだけに留まらず、メッセージという部分まで完全にリンクしていることがわかります。(これは人に情報を伝えるという根底で意味が繋がっている根拠になります)
関数(レベル) | color | アイコン | MDNの説明 |
---|---|---|---|
console.info | 青 | i |
console.info() メソッドは、ウェブコンソールに情報メッセージを出力します。 |
console.warn | 黄 | ⚠ |
console.warn() メソッドは、ウェブコンソールに警告メッセージを出力します。 |
console.error | 赤 | x |
console.error() メソッドは、エラーメッセージをウェブコンソールに出力します。 |
※ ブラウザやバージョンによって info が青やアイコンを使わなくなっている場合もあります
これにより、エラーは属性の種類の一つであり、コンポーネントとしては Message
で表現できることがわかりました。
これを踏まえた上で、表示系フィールドにおける Message
の役割を考えてみましょう。
例えば、設定状態を確認できるページがあるとします。
そこには設定としては有効であるものの、何かしらの注意を促したい項目があるとします。
このようなとき、表示系のフィールドとして、設定内容と共に警告レベルのメッセージを表示できると便利です。
他にも、ある設定がオーバースペックな設定な設定となっており「改善が可能です」という情報を提供したい項目があれば情報メッセージを表示できると、きめ細やかなサービスを実現できます。
必須表現の捉え方
次に必須表現です。
入力フィールドでは必要不可欠な必須表現も、表示系フィールドにおいて利用価値があるものとして捉えられます。
例えば、何かのイベント参加に関する注意書きがあるとします。
その注意書きには当日持参が必要なもののリストが項目(フィールド)として表示されていて、説明とともに、あるものは必須で、あるものは必要に応じてと表現されています。
このように、入力欄がなかったとしても必須表現を使う可能性はありえます。
これはまさに説明フィールドに該当する使用例です。
捉え方のまとめ
一見 "入力" に依存しているように見えたエラーメッセージや必須情報も、"表示" の観点から捉えたときに何に該当するのか、意味や役割、世の中に存在するモデルや利用シーンと照らし合わせることで適切な抽象化の着地点が見えてきます。
"入力内容に対するエラーメッセージ" という考え方から、 "フィールドの内容に対するメッセージ" のように適切に抽象度をコントロールし、エラーはメッセージの属性として存在するものと捉えることで、 基底の Field
が持つべき真のスペックが明確になりました。
このように考えてみると、入力フィールドの入力に依存していると思われていた要素のほとんど or 全ては表示系のフィールドでも意味のある存在であることを理解でき、より凝集度が高く情報表現豊かな設計が可能になります。
また、DOMとしても同じものを使用できることから、実装や保守面で見ても効率アップに繋がりますし、HTML表現やCSS表現としてもスマートになるので、一石二鳥以上の効果が期待できます。
これらを踏まえると、DOM的な依存によって InputField
が必要になることはあまりないのではないかと思われます。
結論
ほとんどの構成物は基底の Field
に持つべきで、Field
を事実上表示フィールドとして使用できることから、 DisplayField
は不要であることがわかりました。
InputField
は依存するものの有無によって以下の2パターンに分けられます。
InputField
に依存するものがない場合
入力フィールドは Field/_base
をそのまま使用して入力UIと連携すればよく、 InputField
というディレクトリは必要ありません。
また、表示系フィールドで Field
の基底コンポーネントを利用できるよう、 Field/_abstract
ではなく Field/_base
としています。
Field
_base
Label
MessageList
...
index.ts
CheckBoxField
TextBoxField
SelectBoxField
index.ts
InputField
に依存するものがある場合
Field
の外部から見ると、 InputField
のディレクトリは隠蔽されていて存在を感じることはありませんが、入力フィールドに依存したものを InputField/_abstract
に置けるので Field
内は整理された状態になります。
Field
_base
Label
MessageList
...
index.ts
InputField
_abstract
CheckBoxField
TextBoxField
SelectBoxField
index.ts
index.ts
Field
が export
するものは index.ts
で管理されているため、途中で InputField
の有無を変更しても外部への影響が無いところも、責務を正しく閉じられていることを表しています。
まとめ
Field
と InputField
という名前の違いから分析を開始し、さらに深掘りを経ることで、 Field
周辺におけるディレクトリ構成だけでなく、それぞれの責務や関係性、エラーメッセージや必須表現のあり方までも詳細に明らかにすることができました。
これらは主観的に決めたものはなく単語の意味やUIの本質を正確に表現した結果であるため、意味と合致する部分で自然と整合性がとれ、納得感や理解のし易さにも繋がっていくものと考えられます。それはつまりプロジェクトやチームに依存しない永続的に利用可能な基礎になります。
このような世界観に魅力を感じた方は BCD Design の思想を参考に、単語一つ一つの意味を改めて見つめ直して見てはいかがでしょうか?
実践的な ニコニコ生放送のBCD Design導入事例 も公開しています。
命名から明名へと切り替えれば、きっと色々な気付きや発見に繋がり、将来への有益な投資になることでしょう。
参考
株式会社ドワンゴでは、様々なサービス、コンテンツを一緒につくるメンバーを募集しています。 ドワンゴに興味がある。または応募しようか迷っている方がいれば、気軽に応募してみてください。
Discussion