概要
Feature-Sliced Design (FSD) とは、フロントエンドアプリケーションの設計方法論です。簡単に言えば、コードを整理するためのルールと規約の集大成です。FSDの主な目的は、ビジネス要件が絶えず変化する中で、プロジェクトをより理解しやすく、構造化されたものにすることです。
ルールのセットに加えて、FSDはツールチェーンでもあります。プロジェクトのアーキテクチャをチェックするためのリンター、CLIやIDEを通じたフォルダージェネレーター、および豊富な実装例のコレクションがあります。
FSDは私のプロジェクトに適しているのか?
FSDは、あらゆる規模のプロジェクトやチームに導入できます。以下の場合、あなたのプロジェクトに適しています。
- フロントエンド開発での使用(ウェブサイト、モバイル/デスクトップアプリケーションのインターフェース作成など)
- アプリケーション開発での使用(ライブラリ開発ではない)
これだけです!使用するプログラミング言語、フレームワーク、状態管理ライブラリには制限がありません。尚、FSDを段階的に導入したり、モノレポで使用したり、アプリケーションをパッケージに分割し、それぞれにFSDを個別に導入することもできます!
既存のアーキテクチャからFSDに移行することを検討している場合は、現在のアーキテクチャがチームに支障をきたしているかどうかを確認してください。例えば、プロジェクトが大きくなりすぎて新機能の開発が効率的に行えない場合や、多くの新しいメンバーがチームに加わることが予想される場合です。現在のアーキテクチャが正常に機能している場合、変更する必要はないかもしれません。しかし、移行を決定した場合は、移行セクションの推奨事項を確認してください。
基本的な例
以下は、FSDを実装したシンプルなプロジェクトです。
📁 app
📁 pages
📁 shared
これらのトップレベルのフォルダーはレイヤーと呼ばれます。詳しく見てみましょう。
📂 app
📁 routes
📁 analytics
📂 pages
📁 home
📂 article-reader
📁 ui
📁 api
📁 settings
📂 shared
📁 ui
📁 api
📂 pages
内のフォルダーはスライスと呼ばれます。スライスはドメイン(この場合はページ)ごとにレイヤーを分割します。
📂 app
、📂 shared
、および📂 pages/article-reader
内のフォルダーはセグメントと呼ばれ、スライス(またはレイヤー)を技術的な目的に応じて分割します。
概念
レイヤー、スライス、セグメントは、以下の図に示されるように階層を形成します。
レイヤー
レイヤーはすべてのFSDプロジェクトで標準化されています。すべてのレイヤーを使用する必要はありませんが、ネーミングは重要です。現在、7つのレイヤーが存在しています(上から下へ)。
- App*(アップ) — アプリケーションの起動に必要なすべてのもの(ルーティング、エントリーポイント、グローバルスタイル、プロバイダーなど)
- Processes(プロセス、非推奨) — 複雑なページ間のシナリオ
- Pages(ページ) — ページ全体、またはネストされたルーティングの場合、ページの大部分
- Widgets(ウィジェット) — 大きな自己完結型の機能部分、またはインターフェースの大部分。通常はユーザーシナリオ全体を実装する
- Features(フィーチャー) — プロダクト機能の再利用可能な実装、つまりユーザーにビジネス価値をもたらすアクション
- Entities(エンティティ) — プロジェクトが扱うビジネスエンティティ、例えば
user
やproduct
- Shared*(シェアード) — 再利用可能なコード。特にプロジェクト/ビジネスの詳細から切り離されたもの
* — App層とShared層のレイヤーは他のレイヤーとは異なり、スライスを持たず、直接セグメントで構成されています。
レイヤーの特徴は、レイヤーのモジュールは、下層のレイヤーモジュールのみを知ることができ、その結果、レイヤーが下層のレイヤーからのみモジュールをインポートできることです。
スライス
次にスライスがあり、レイヤーをドメインごとに分割します。スライスの名前は自由に付けることができ、いくつでも作成できます。スライスは、意味的に関連するコードをグループ化することで、プロジェクト内のナビゲーションをしやすくします。
スライスは同じレイヤーの他のスライスを使用できないため、スライス内のコードの強い結合とスライス間の弱い結合が保証されます。
セグメント
スライス、およびApp層とShared層のレイヤーはセグメントで構成され、セグメントはその目的に応じてコードをグループ化します。セグメントの名前は標準で固定されていませんが、最も一般的な目的のためにいくつかの共通の名前があります。
ui
— 表示に関連するすべて: UIコンポーネント、日付フォーマッター、スタイルなどapi
— バックエンドとのやり取り: リクエスト関数、データ型、マッパーmodel
— データモデル: バリデーションスキーマ、インターフェース、ストレージ、ビジネスロジックlib
— 他のモジュールが必要とするライブラリコードconfig
— 設定ファイルとフィーチャーフラグ
通常、これらのセグメントはほとんどのレイヤーに十分であるため、独自のセグメントはShared層やApp層でのみ作成されることが多いです。しかし、これは厳格なルールではありません。
利点
-
一貫性
構造が標準化されているため、プロジェクトがより一貫性を持ち、新しいメンバーのチームへの参加が容易になります。 -
変更とリファクタリングへの耐性
レイヤーのモジュールは、同じレイヤーや上層レイヤーの他のモジュールを使用できないため、アプリケーションの他の部分に予期しない影響を与えることなく、分離された変更を加えることができます。 -
ロジックの再利用制御
レベルに応じて、コードを非常に再利用可能にすることも、非常にローカルにすることもできます。
これにより、DRY原則と実用性のバランスが保たれます。 -
ビジネスとユーザーのニーズに焦点を当てる
アプリケーションはビジネスドメインに分割され、命名にはビジネス用語の使用が奨励されるため、プロジェクトの他の無関係な部分に完全に精通することなく、プロダクトで有用な作業を行うことができます。
段階的な導入
既存のコードベースをFSDに移行したい場合は、以下の戦略をお勧めします。私たち自身の移行経験から、この方法は非常に効果的であることが分かりました。
-
App層とShared層のレイヤーを徐々に形成し、基盤を作る。
-
既存のすべてのインターフェースコードをウィジェットとページに分散させる。FSDのルールに違反する依存関係があっても良い。
-
インポートのルール違反を徐々に修正しながら、エンティティやフィーチャーを抽出する。
リファクタリング中に新しい大きななエンティティを追加することや、部分的なリファクタリングは避けることをお勧めします。
次のステップ
- FSDの考え方を理解したい? チュートリアルを読んでください。
- 例を見て学びたい? 実装例セクションにたくさんあります。
- 質問がある? Discordチャンネルにアクセスして、コミュニティに質問してください。