React(に限らずフロントエンド)コンポーネントの命名規則
要約
コンポーネント命名規則の大切さについて説明します。
Reactコンポーネントの命名規則について"Object", "Action", "Type"を連結した命名が良いと主張します
コンポーネント命名規則の大切さと役割
Reactコンポーネントの命名、どのようにしていますか。前提として複数人で開発する場合、コンポーネントの命名規則を設けるべきだと思います。
ここでいう命名規則とはスネークケースかパスカルケースかといったものではなく、同じコンポーネント設計であればチームの皆が同じ(あるいは同じような)命名ができるような規則があった方が良いです。
適切なコンポーネント命名規則があることによって、以下のような効果が得られます。
- コンポーネントの一覧性の確保
- コンポーネントが適切にソートできることで、今どういうコンポーネントがあるかがわかりやすくなります。コンポーネントが見つかることで適切な再利用に繋がります。
- コンポーネントの肥大化の抑止
- 名前によってコンポーネントのスコープを定めることができれば、コンポーネントの肥大化を防ぐことができます。
- コンポーネントの重複の排除
- 名前がバラバラだと同じようなコンポーネントが作られてしまうことがありますが、同じ機能のコンポーネントが同じ名前で作られるようになっていれば重複する前に気づくことができます。
気をつけなければならない点として、命名規則があればなんでもいいわけではなく、適切な命名規則でない場合はデメリットも生じます。例えば、命名に過剰にコンテキスト(親ページ名とか)を含めてしまうと、似たようなコンポーネントでコードクローンが発生することがあります。本当は同じコンポーネントにできるのに、名前が違う(親ページ名が異なる)ので違うコンポーネントを作らざるをえない、といった状況です。
良い命名規則のためには、わかりやすく、同じものを同じく、異なるものを異なるように分類できる、最小限の命名規則である必要があります。
提案する命名規則 - 「ユーザが (1)何を (2)どうする (3)どんなもの」
"Object", "Action", "Type"を連結した形が必要十分で良いと考えています。具体例としてはUserEditForm
, ProfileUpdateButton
, PostPublishDialog
のようなものです。
これらの名前を見てどのようなコンポーネントか想像できるのではないでしょうか。そして命名が必要な情報のみから成り立っていることがわかっていただけるのではないでしょうか。そうであれば筆者のこの企ては順調です。
"Object", "Action", "Type"は、日本語で書くと、「ユーザが (1)何を (2)どうする (3)どんなもの」の(1),(2),(3)を連結したものと言えます。それぞれのフラグメントについてより詳しく見てみましょう。
Object (Optional) (1)何を
「ユーザが (1)何を (2)どうする (3)どんなもの」の 何を にあたる部分です。
OOUIでいうObjectのことを指します。コンポーネントが操作・表示する対象を指します。修飾する必要があるときは後置修飾します(例: Accountに関するカードコンポーネントで、アクティブなAccountとアーカイブされたAccountを区別しなければならないときに、"AccountCard" "AccountArchivedCard"のように後置修飾によってAccountを修飾します)。これは前置修飾した場合、コンポート名でソートした時の(=Storybookで見た時の)並び順がオブジェクトで入り乱れてしまい一覧性が下がるため、後置修飾の方が好ましいと考えています。
コンポーネントの中は、特定のObjectを対象としていない場合があります。シンプルなボタンやフォームのパーツなどです。そのような場合は、このフラグメントは省略できます。
Action (Optional) (2)どうする
「ユーザが (1)何を (2)どうする (3)どんなもの」の どうする にあたる部分です。
ユーザがObjectに対して行うActionです。Create, Edit, Delete, Update, Archive, Confirm, Submit, Select, ... などがあります。(Objectに対して行うActionなので、ClickとかTypeとかはここでいうActionではありません)
表示だけを担うコンポーネントの場合、ActionはViewなどになりますが、Viewの場合は冗長なので省略可能としています。
「このコンポーネントは2つ(以上)のアクションをしているが、どのように命名したら良いか」という場面があるかもしれません。そんな時がこの命名規則が真価を発揮する時です。この命名規則ではそのような名前をつけることはできないのです。「なんだ使えないなあ」と思わないでください。そうではなく、そもそもコンポーネントはそれぞれ単一の責務を持つべきです。二つのアクションを持つコンポーネントの設計を見直して、分解してください。そうすればこの命名規則に沿った名前が付けられ、結果的に再利用可能なコンポーネントが生まれているはずです。
Type (3)どんなもの
「ユーザが (1)何を (2)どうする (3)どんなもの」の どんなもの にあたる部分です。
Button, Icon, Input, Form, Section, Card, Tab, Modal, Dialog, Alert, Page, などそれが何なのかを表す名前を付けます。修飾する場合は前置修飾します(ClickableIcon, XLCard,などのように)。
この命名規則で名付けづらい場合は、コンポーネント設計自体を見直すことを推奨しています。
終わりに
ChatGPTにこの記事の内容を批判させました。
この記事の命名規則は理論的には合理的ですが、現実的な開発現場においては柔軟性が求められる場面も多く、すべてのケースに適用できるわけではないという点を強調すべきです。また、命名規則を厳格に守りすぎることで、逆に冗長で分かりにくい名前が増え、開発の効率が落ちることもあります。コンポーネントの命名には一貫性が重要である一方で、プロジェクトの規模や性質に応じた柔軟なアプローチが必要です。
ということでこの規則を採用する際は柔軟性を持って迎え入れてあげてください。
とはいえ筆者が開発をリードしていたSaaSでは、うまく行っていた(N=1)ので、命名規則策定の叩き台にでもしていただいて、各チームに最適なアプローチを探っていただきたいですね。
Discussion
ChatGPT は断言を避けたがるのか、慎重な言い方をしていますが、僕はこの命名法に大賛成です!
名前が冗長すぎて困ることは少なくても、言葉足らずな名前のせいでコードベースの全体像を捉えづらくなって困ることは確実なので。
特に Section とか View とかを末尾に付けるのは「このコンポーネントが、ページの中のどのような位置づけなのか」が迷子にならないとか、取り扱うデータそのもの型の名前と名前被りするのを回避できる、という利点がかなり大きいと思います。