Never Use Atomic Design for Component Management
コンテキスト
Section titled “コンテキスト”フロントエンド開発においてコンポーネントの階層構造を管理する手法として、Brad Frost提案のAtomic Designが広く知られている。しかし、実際のプロダクト開発において以下の問題が継続的に発生している:
- Atoms、Molecules、Organisms、Templates、Pagesの分類基準が曖昧で、開発者間で判断が分かれる
- 同じコンポーネントでも文脈によって異なるレベルに分類される可能性がある
- 複雑なコンポーネントの分類に時間を要し、開発効率が低下する
- リファクタリング時にディレクトリ間の移動が頻繁に発生する
- チーム内でのコンポーネント分類に関する議論が増加し、本質的でない作業に時間を消費している
また、現代のReact開発ではコンポーネントの再利用性よりも、機能やドメインに基づいた明確な境界が重要視される傾向にある。
Atomic Designによるコンポーネント分類は採用せず、機能とドメインベースのディレクトリ構造でコンポーネントを管理する。
選択肢1: Atomic Design採用
Section titled “選択肢1: Atomic Design採用”-
利点:
- 業界で広く知られた手法で、新しいメンバーにとって理解しやすい
- 理論的にはコンポーネントの再利用性が向上する
- デザインシステムとの親和性が高い
-
欠点:
- 分類基準が曖昧で、開発者間で判断が分かれる
- 機能追加・変更時にコンポーネントの分類変更が頻繁に発生
- ビジネスロジックとUIの境界が不明確になりやすい
- ディレクトリ構造が深くなり、ファイル検索が困難
選択肢2: 機能・ドメインベース分類(採用案)
Section titled “選択肢2: 機能・ドメインベース分類(採用案)”-
利点:
- ビジネス要件に基づいた明確な分類基準
- 機能単位での開発・テスト・デプロイが容易
- コンポーネントの責務が明確
- 新機能追加時の影響範囲が限定的
-
欠点:
- 一般的でない手法のため、チーム内での認識合わせが必要
- コンポーネントの重複が発生する可能性
- 初期設計時にドメイン境界の検討が必要
選択肢3: フラットな構造
Section titled “選択肢3: フラットな構造”-
利点:
- シンプルで分かりやすい
- ファイル検索が容易
-
欠点:
- プロジェクト規模が大きくなると管理が困難
- 関連性のあるコンポーネントの把握が困難
- 命名規則への依存度が高い
この決定による影響:
-
ポジティブな影響:
- コンポーネント分類の議論時間削減により、開発速度が向上
- 機能単位での開発により、責務が明確化
- ビジネス要件とコードの対応関係が理解しやすい
- リファクタリング時の影響範囲が限定的
-
ネガティブな影響:
- 類似コンポーネントの重複が発生する可能性
- デザインシステムとの整合性確保に別途工夫が必要
- チーム内での設計方針の説明・教育コストが発生
-
リスク:
- ドメイン境界の設計誤りによる後々のリファクタリングコスト
- コンポーネントの再利用性低下による開発効率の悪化
- デザインとの一貫性が損なわれる可能性
実装ガイドライン
Section titled “実装ガイドライン”コンポーネント管理戦略
Section titled “コンポーネント管理戦略”2層構造でのコンポーネント管理
- 共通UIコンポーネント: npm packageとして独立管理
- 機能特化コンポーネント: アプリケーション内で機能ごとに管理
ディレクトリ構造例
Section titled “ディレクトリ構造例”# 共通UIコンポーネント(独立npm package)@company/ui-components/ Button/ Input/ Modal/ Table/ etc...
# アプリケーション内(コードジェネレーター使用前提)src/ components/ UserProfile/ UserSettings/ UserCard/ ProductCard/ ProductList/ ProductFilter/ OrderForm/ OrderHistory/ OrderStatus/
-
共通UIコンポーネント(npm package):
- 複数のアプリケーションで再利用可能
- ビジネスロジックを含まない純粋なUIコンポーネント
- デザインシステムに基づいた基本的なUI要素
-
機能特化コンポーネント(アプリケーション内):
- 特定のビジネス機能に関連するコンポーネント
- ビジネスロジックを含む可能性がある
- アプリケーション固有の要件に最適化
- フラットな構造でコードジェネレーターによる自動生成・管理を前提
- コンポーネント名は機能を表す具体的な名称を使用
- 抽象的な名称(Atom、Molecule等)は使用しない
- ビジネス用語を積極的に採用し、ドメインとの対応を明確化
npm packageとアプリケーション間の連携
Section titled “npm packageとアプリケーション間の連携”// 共通UIコンポーネントの使用例import { Button, Input, Modal } from '@company/ui-components'
// 機能特化コンポーネント内での活用const UserProfile = ({ user }: { user: User }) => { return ( <div> <Input placeholder="ユーザー名" defaultValue={user.name} /> <Button variant="primary">保存</Button> </div> )}
コンポーネント重複時の対応
Section titled “コンポーネント重複時の対応”- 共通UIコンポーネントレベル: npm packageに追加を検討
- 機能特化レベル: 各ドメイン内での重複は許容
- 定期的なレビュー: npm packageへの昇格候補を評価
- コードジェネレーター活用: 新しいコンポーネントはツールにより自動生成
- フラット配置: 生成されたコンポーネントはsrc/components直下にフラット配置
- 共通化検討: 複数箇所で類似パターンが発生した場合、共通UIコンポーネント化を検討
- npm package昇格: 設計レビューを経てnpm packageへ追加
コードジェネレーター使用の利点
Section titled “コードジェネレーター使用の利点”- ディレクトリ分類の議論時間を削減
- 一貫したコンポーネント構造の自動生成
- ファイル検索の高速化(フラット構造)
- リファクタリング時の影響範囲の明確化