こんにちは、CHILLNN CTOの永田です。
弊社では1ヶ月ほど前から、エンジニアインターンを採用していて、作った自分もたじろぐほどに非常に過酷な研修をこなしてもらっています。インターン生からは脳がちぎれそうだとご好評をいただいています。
弊社で行っている研修には、明確なロードマップが存在していて、最終的にアプリケーションを0→1で作りあげることをゴールにしています。自分なりの判断軸を内在化してもらうことを目的にしているため、研修の中で取り組む全ての課題は非常に抽象度が高いものになっています。
その研修の中で、
フロントエンドのコンポーネント分割は
どのようにすべきなのかを考えよ。
という課題を出していて、インターン生にFBをする中で、自分が今考えている内容を記事としてまとめておこうと思ったのがこの記事を書こうと思った背景です。
Atomic Designを含む、あらゆるアーキテクチャに関する説明は、特に初学者向けには帰納的にその性質が語られることが多いかと思います。帰納的な分類は理解しやすく、無思考で誰でも行える一方で、背景の理解が曖昧になり、不要に複雑化してしまったり、複雑な事象に対して適用させることが困難になってしまうことがあります。
今回の記事は、エンジニア向けに、UIパーツ分割の戦略を演繹的に説明することを目的にしています。
Atomic Designとは、簡単にいうとUIパーツを以下の5つのパーツに分割して組み立てるという考え方です。
1. Atoms
2. Molecules
3. Organisms
4. Templates
5. Pages
5年ほど前からAtomic Designに関する記事は無限に出ているので、ググってもらえるとたくさん出てくると思います。原典を貼っておきます。
Atomic Design Hey there! I wrote a book called Atomic Design that dives int
Atomic Designの運用上の難しさは、以下の特徴によってもたらされていると考えています。
1. 一見してコンセプトがわかりやすいこと
2. 厳密なルールは自分で決めなくてはならないこと
Atomic Designが素晴らしい部分は、コピーライティングだと思っています。化学の用語を使うことによって、なんとなくイメージが湧きやすく、初学者にとって非常にとっかかりやすいコンセプトになっています。
一方で、Atomic Designには厳密なルールは決まっておらず、個別にカスタマイズして運用する必要があります。このルールは、非常に意匠を必要とするもので、表層的な分離はむしろ混乱を生んでしまいます。
自分が会社を始めてから、すごく高名な方にプロダクトのデザインに関してFBをいただく機会が何度かあり、その中で非常に印象に残っているFBが
UIパーツは、説明的でなくてはならない
というものでした。
当初、デザイン的に尖っているものを作りたくて、完全に独自のUIを構築していました。たしかにカッコいいのですが、一見して使い方はわかりにくく、特に年配の方に触ってもらった時に、うまく操作できないということが多々ありました。
ユーザーがアプリケーションを触るときは、特定の解決したい課題(Job)があるはずです。そのJobをストレスなくこなすための補助をすることがUIに求められる役割です。
この役割を達成するためには、Jobを達成するためにそれぞれのUIパーツとどのようなインタラクションをすればよいかを一瞬で判断できる必要があります。一瞬で判断できるUIを作るにはどうしたらいいのでしょうか?答えはシンプルで、ユーザーがすでに知っているUIパーツを使えばいいのです。
Input, Buttonなど、あらゆるインタラクションを伴うUIパーツはできる限り一般的なものを使うべきです。
Atomic DesignはUIパーツをコンテキストによって分類することで、UIの再利用性と保守性を高めるということを一つの目的としています。
また、共通のコンポーネントを利用するということは、アプリケーション内でのUIの一般化を促し、ユーザーの学習コストを下げるという効果があります。デザインやUXの一貫性を保つことで、UIの表現力を高め、不要な説明を省くことができます。
そして弊社では、むしろ後者のメリットを享受するためにデザインシステムを採用しています。
弊社では、Atomic Designのルールを以下のように設定しています。
Atoms:
・ユーザーにプリミティブなアクションを想起させるもの
ex) 画像をアップロードする、文字を入力する
Organisms:
・ドメインコンテキストに依存するもの
ex) ブログのメタデータを入力する、ブログのカード
Templates:
・一般にアプリケーションで扱うドメインに対するアクションを想起させるもの
ex) 一覧表示する、編集する
※ デザインシステムとしては、Molecules, Pagesは利用していません。
順に説明していきます。
Atomsの責務は、ユーザーにプリミティブなアクションを想起してもらうことにあります。文字を入力したり、画像をアップロードしたり。このようなプリミティブな操作は、コンテキストに依存させないことで、アプリケーションの各項目に対する学習コストを下げることが期待できます。つまり、アクションとドメインコンテキストの両側からページの役割を理解できるようになります。
Templatesの責務は、ドメインに対するCRUD操作が、アプリケーションで扱う複数のドメインで行われる場合に同一のUXを提供することです。例えばドメインをテーブル表示したり、ドメインの編集画面のレイアウトを規定したり。同一の目的を持つページをコンテキストに依存させないことによって、あるページに対するユーザーのインタラクションの学習コストを下げることが期待できます。フォントの大きさや、カラーはここで規定しています。
Organismsの責務は、ドメインコンテキストに依存する全てです。
まとめると、AtomsとTemplatesはアクションを想起させること、
Organismはアクションにドメインコンテキストを流し込むことを責務としています。
AtomsとTemplatesの違いは、Atomsがプリミティブなアクション(押す、入力する、など)を想起させるのに対して、Templatesは、ドメインコンテキストを流し込むことを想定したアクション(編集する、作成する、など)を想起させています。
前章で説明した通り、アクションベースでの分割の目的は、ユーザーの学習コストを下げることでした。
一方でOrganismの分割では、開発者の保守コストを下げることを目的としています。
コンポーネントは分割しすぎても、分割しなさすぎても保守コストが上がります。
ではそのちょうど良い塩梅はどのように見出すべきでしょうか?
Organismの役割は弊社での定義上、ビジネスロジックとUIを紐づけることです。
自分は、「UIコンポーネントとは、ユーザーを引数にもつ関数」であると認識しており、SOLID原則に基づいて設計することが基本であると考えています。
特に、「単一責任の原則」を重視しており、UIに紐付けられた関数が、単一の目的を達成するためのものであるかどうかが分割の良し悪しを判断する基準になると考えています。
具体的な指針をあげるなら、
UIに、複数の関数が紐付けられており、それらの目的が異なっているなら、分割すべきです。
UIに、一つも関数が紐付けられていないのであれば、分割しすぎな可能性があります。
親の抽象度をあげ、子になるにつれて具体性が上がっていくようにコンポーネントを設計することで、このような分割が実現が可能です。Organismsは、ドメインコンテキストを流し込んでいるが故に、異なるドメインモデル間での共通化を自分は考えません。それゆえ、コンポーネントの親子関係は、ファイル構造をネストさせて表現することが多いです。
エンジニアの開発体験の向上は、お客様に提供可能な最終的なUXに大きく影響を及ぼします。
そして、UIの正解は、形而上学的議論では収束せず、実際に使いやすいのかどうかでしか判断できません。
デザインは、ユーザーの知識を前提とするので、前提知識が変わるごとに正解は変わります。
使いにくいものの改善は簡単ですが、使いやすい時ほど、その理由を探り、再現性を持たせることが重要です。
弊社のコンポーネント分割戦略は、いかにユーザーにとって学習コストの低いUIを構築できるかという観点に終始しています。
エンジニアによる保守コストの低減も結果的には使いやすいUIへの修正コストの低下を目的にしています。
あらゆる本やブログをみた時、そこにあるのはある組織にとっての現時点でのアウトプットです。そこで書かれている正解通りにやることに意味はなく、自らの組織の生産性が最も上がるように情報を咀嚼し判断していける能力を伸ばしていかなくてはなりません。
あるコーディング規約やなんらかの戦略、またはパラダイムを採用する際には、その目的を自ら語れない限りはやる必要がないと思っています。特にエンジニアは、ビジネスの達成ではなく、コード上の理想の実現が目的になってしまうことが多々あるので、注意しましょうという話でした。