👌

アトミックデザインの整理と再考

2022/10/21に公開

この記事で伝えたいこと

AtomicDesignは一般的に取り入れられている概念であるものの、人によって解釈が違うことが多い概念です。

また、厳密なAtomicDesignはコンポーネントの管理が大変なために、独自の改造を施した改造AtomicDesignもよく見かけます。

この記事ではAtomicDesignの概念を復習すると共に、自分の考える最強のAtomicDesignを考えていきます。

参考:Atomic Design ~堅牢で使いやすいUIを効率良く設計する | 五藤 佑典 |本 | 通販 | Amazon

コンポーネントとは

AtomicDesignの前にコンポーネントについて整理します。
コンポーネントには4つの特徴があります。

カプセル化されている

インターフェイスの使い方さえ知っていれば、内部実装を知っている必要がありません。

置換可能である

あるコンポーネントを別のコンポーネントに置き換えるときに、インターフェイスが同じであれば、置き換えが簡単にできます。
大規模な開発では、リファクタリングや同じ機能を持つ異なる見た目のUIと差し替えることが多くなります。
こういったときに効果を発揮します。

再利用可能である

コンポーネントが過不足なく責務を担っている場合、様々な箇所で再利用が可能です。
しかし、再利用可能なコンポーネントを作ることは難しく、ビジネス要件が入りがちです。
汎用的に使えるコンポーネントとビジネス的なコンポーネントは分離して再利用性を高めるべきです。

コンポーネントを別のコンポーネントに組み合わせて作成可能である

再利用性が高ければ、そのコンポーネント自体を他のコンポーネントで作るためにも使用することができます。
小さなコンポーネントでは小さな問題しか解決しませんが、小さなコンポーネントを組み合わせて大きなコンポーネントにすれば、大きな問題を解決できます。

AtomicDesignとは

概要

AtomicDesignは小さいUIコンポーネントを組み合わせて大きなコンポーネントを作るためのデザインフレームワークです。
AtomicDesignには以下の5つの粒度が存在します。

依存関係

AtomicDesignは小さいコンポーネントを組み合わせて大きいコンポーネントを作るので「小さなコンポーネントが大きなコンポーネントを含まない」という依存の方向性が存在します。
UIデザインに階層化アーキテクチャ(レイヤードアーキテクチャ)の概念があります。

関心事

レイヤー 関心 特徴
Pages プロダクトそのもの templatesを介してコンテンツやルーティングをコンポーネントに接続する -
Templates 画面全体のレイアウト ページの雛形、具体的なコンポーネントを持たない -
Organisms ユーザーの行動を促すコンテンツ 独立して存在できるスタンドアローンなコンテンツを提供 ヘッダー、フッター、コンテンツ
Molecules 行動を阻害しない操作性 ユーザーの関心事を提供 テキストフォーム
Atoms デザインの統一性 コンポーネントの最小単位 ボタン、テキスト、アイコン、バルーン、バッチ、カード

アプリケーションのUIデザインにおいて変更頻度が最も高いのは、TemplatesやOrganismsの上位層です。
適切にコンポーネント化ができていれば上位のレイヤーの階層の関心事に下位レイヤーは影響を受けにくいです。

AtomicDesignとコンテナ・プレゼンテーションパターン

プレゼンテーションパターンとは

データがユーザーにどのように表示されるかを管理するコンポーネントのこと
UIの表示を担当する

コンテナテパターンとは

何のデータがユーザーに表示されるかを管理するコンポーネント
UIのロジックを担当する。
今はcustomHooksで代替できる

AtomicDesignに適用するとどうなるか

レイヤー コンテナ・プレゼンテーション
Pages コンテナパターン
Templates プレゼンテーションパターン
Organisms プレゼンテーションパターン
Molecules プレゼンテーションパターン
Atoms プレゼンテーションパターン

参考:
https://zenn.dev/morinokami/books/learning-patterns-1/viewer/presentational-container-pattern

AtomicDesignの辛い点

上記の表を見てください。コンテナパターンが適用されるのがPagesのみです。
Atomsまではpagesから引数を渡して上げる必要があります。
Pages -> Templates -> Organisms -> Molecules -> Atoms
とPagesからAtomsまで引数渡しをする必要があります。
大変シンドイところです。

よくある解決策

よくある解決案として、Organisms層をコンテナコンポーネント兼プレゼンテーショナルコンポーネントにするパターンがあります。

メリット
  • ロジックがOrganisms -> Molecules -> Atomsの引数渡しで済むから楽
デミリット
  • Storybookの運用が大変になり、Storybookが形骸化してしまう。
  • Templates層も形骸化してしまう
  • Organisms層が肥大化してしまう
どうやってデミリットを打ち消すか
  • Organismsをコンテナ.tsxとプレゼンテーショナル.tsxに分ける
  • Storybook上ではMSWを使用し、Storybookの形骸化を避ける
  • コンテナ.tsxに書いたビジネスロジックはCustomHooksになるべく移行する。
    (プレゼンテーショナル.tsxの中にCustomHooksを記述しないのは、やがてルール破る人がでてくるから)

以下参照のこと
https://qiita.com/mball/items/5dc0a95ef691b17ff8bc

https://techblog.zozo.com/entry/storybook-msw-chromatic

https://zenn.dev/kazu777/articles/9460c75b7cd8d1

Discussion