(翻訳) 機能分割設計 - 最高のフロントエンドアーキテクチャー


![fsd](https://emewjin.github.io/static/12d56d5acc56e2fdb70a0eee3bea334f/8c557/thumbnail.png)

## 目次

- [目次](#目次)
- [はじめに](#はじめに)
- [レイヤー](#レイヤー)
- [スライス](#スライス)
- [セグメント](#セグメント)
- [公開 API](#公開-api)
- [アーキテクチャについてより詳しく](#アーキテクチャについてより詳しく)
  - [抽象化とビジネスロジック](#抽象化とビジネスロジック)
  - [FSDが問題を解決する方法](#fsdが問題を解決する方法)
  - [従来のアーキテクチャとの比較](#従来のアーキテクチャとの比較)
  - [シンプルなモジュラーアーキテクチャとの比較](#シンプルなモジュラーアーキテクチャとの比較)
  - [Next.jsとFSDの衝突](#nextjsとfsdの衝突)
    - [Pages](#pages)
    - [App](#app)
  - [機能分割設計の潜在力](#機能分割設計の潜在力)
- [アーキテクチャの長所と短所](#アーキテクチャの長所と短所)
  - [長所](#長所)
  - [短所](#短所)
- [結論](#結論)

## はじめに

フロントエンド開発者は、アプリケーションのアーキテクチャに関連する問題によく直面します。多くの場合、モジュール間の疎結合と高凝集性を提供し、容易に拡張可能なアーキテクチャが必要とされます。

この記事では、フィーチャースライス設計（Feature-Sliced Design、FSD）アーキテクチャについて説明します。私の考えでは、これが利用可能なオプションの中で最高のアーキテクチャだと思います。順を追ってFSDの概念とこのアーキテクチャ方法論が解決する問題について説明し、FSDを既存のアーキテクチャやモジュラーアーキテクチャと比較した後、その長所と短所について紹介します。

まずは、レイヤー（layer）、スライス（slice）、セグメント（segment）という3つの概念を区別してみましょう。

![introduction.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3539939/359ed570-62e3-6b97-61fe-3101745a75ff.png)

## レイヤー

レイヤーは最上位ディレクトリであり、アプリケーション分解の第一段階です。レイヤーの数は最大7つに制限されており、一部はオプションですが標準化されています。現在、以下のようにレイヤーが区分されています。

![layer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3539939/96670751-c8bf-d2c9-c9a2-70dbce970c3c.png)

各レイヤーには固有の責任領域があり、これはビジネス指向です。
各レイヤーを個別に見ていきましょう。

- `app`: アプリケーションロジックが初期化される場所です。プロバイダー、ルーター、グローバルスタイル、グローバル型定義などがここで定義されます。アプリケーションのエントリーポイントとして機能します。
- `processes`: このレイヤーは、複数のステップからなる登録など、複数のページにまたがるプロセスを処理します。このレイヤーは非推奨とされていますが、まだ時々遭遇することがあります。オプションのレイヤーです。
- `pages`: このレイヤー内にはアプリケーションのページが含まれます。
- `widgets`: ページで使用される独立したUIコンポーネントです。
- `features`: このレイヤーにはビジネス価値を提供するユーザーシナリオと機能を扱います。例えば、いいね、レビュー作成、商品評価などがあります。オプションのレイヤーです。
- `entities`: このレイヤーはビジネスエンティティを表します。これらのエンティティにはユーザー、レビュー、コメントなどが含まれます。オプションのレイヤーです。
- `shared`: このレイヤーには特定のビジネスロジックに依存しない再利用可能なコンポーネントとユーティリティが含まれています。UIキット、axios設定、アプリケーション設定、ビジネスロジックに縛られないヘルパーなどが含まれます。

これらのレイヤーは、コードベースを組織化し、モジュール化され保守が容易な拡張可能なアーキテクチャを促進するのに役立ちます。

![layer(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3539939/4d710e49-14cf-e95e-315a-8ec20fa78813.png)

機能 分割 設計の主要な特徴の1つは階層構造です。この構造では、features レイヤーが entities レイヤーよりも上にあるため、entities レイヤーは features レイヤーの機能を使用できません。同様に features レイヤーは widgets レイヤーや processes レイヤーのコンポーネントを使用できません。上のレイヤーは下のレイヤーしか利用できません。これは線形の流れを維持するためです。

|    Layer    |                              Can use                              |                         Can be used by                         |
| :---------: | :---------------------------------------------------------------: | :------------------------------------------------------------: |
|    `app`    | `shared`, `entities`, `features`, `widgets`, `pages`, `processes` |                               ❌                                |
| `processes` |       `shared`, `entities`, `features`, `widgets`, `pages`        |                             `app`                              |
|   `pages`   |            `shared`, `entities`, `features`, `widgets`            |                       `processes`, `app`                       |
|  `widgets`  |                 `shared`, `entities`, `features`                  |                  `pages`, `processes`, `app`                   |
| `features`  |                       `shared`, `entities`                        |             `widgets`, `pages`, `processes`, `app`             |
| `entities`  |                             `shared`                              |       `features`, `widgets`, `pages`, `processes`, `app`       |
|  `shared`   |                                 ❌                                 | `entities`, `features`, `widgets`, `pages`, `processes`, `app` |

階層構造では、レイヤーの位置が低いほどコードの多くの場所で使用される可能性が高いため、レイヤーを変更することはより危険です。例えば、shared レイヤーのUIキットは features, widgets, さらには pages レイヤーでも使用されます。

## スライス

各レイヤーには、アプリケーション分解の第二段階であるスライスと呼ばれるサブディレクトリがあります。スライスの接続は抽象的ではなく、特定のビジネスエンティティに対して行われます。スライスの主な目的は、コードを値別にグループ化することです。

スライスの名前はプロジェクトのビジネス領域に基づいて直接決定されるため、標準化されていません。例えば、写真ギャラリーには写真、アルバム、ギャラリーなどのセクションがある場合があります。ソーシャルネットワークには、投稿、ユーザー、ニュースフィードなどのスライスが必要になる場合があります。

密接に関連するスライスは構造的にディレクトリ内にグループ化できますが、他のスライスと同じ分離規則を遵守する必要があり、このディレクトリにあるコードは直接共有されるべきではありません。

![slice.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3539939/2fc621e4-392c-7e1a-6b17-efbca5958cf4.png)

## セグメント

各スライスはセグメントで構成されます。セグメントは、セグメント内のコードを目的別に分割するのに役立ちます。チームの合意に基づいてセグメントの構成と名前が変更される場合があります。一般的に使用されるセグメントは次のとおりです。

- api: 必要なサーバーリクエスト
- UI: スライスのUIコンポーネント
- model: ビジネスロジック、つまり状態との相互作用。actions および selectors に該当
- lib: セグメント内で使用される補助機能
- config: セグメントに必要な構成値ですが、構成セグメントはほとんど必要ありません
- consts: 必要な定数

## 公開 API

各スライスとセグメントには公開 API があります。公開 API は index.js または index.ts ファイルであり、このファイルを通じてスライスまたはセグメントに必要な機能のみを外部に抽出し、不要な機能を隔離できます。インデックスファイルはエントリーポイントとして機能します。

公開 API に関する規則は次のとおりです。
- アプリケーションスライスとセグメントは公開 API インデックスファイルに定義されたスライスの機能とコンポーネントのみを使用します。
- 公開 API に定義されていないスライスまたはセグメントの内部部分は隔離されたものと見なされ、スライスまたはセグメントの内部からのみアクセスできます。

公開 API は import および export を使用して単純に機能します。これにより、アプリケーションを変更するときにコードのすべての場所から import を変更する必要がありません。

![public-api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3539939/8981d2d6-cff4-2ca5-d518-c8ff53959ac8.png)

## アーキテクチャについてより詳しく

### 抽象化とビジネスロジック

レイヤーが高いほど、特定のビジネスノードにより多く依存し、より多くのビジネスロジックを含むことになります。
レイヤーが低いほど、抽象化レベルが高く、再利用性が高く、レイヤー自体の自律性が低くなります。

![abstract.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3539939/a1d96b24-580d-a8ba-d295-ce09a6031018.png)

### FSDが問題を解決する方法

機能分割設計の課題の1つは結合を緩めて凝集を高めることです。FSDがこの結果をどのように達成するかを理解することは重要です。

OOPでは、**多態性(polymorphism)**, **カプセル化(encapsulation)**, **継承(inheritance)** および **抽象化(abstraction)**などの概念を長い間使用してこれらの問題を解決してきました。これらの概念はコードの隔離、再利用性、そしてさまざまな結果を保証します。これはコンポーネントや機能がどのように使用されるかによって異なる結果を得ることを可能にします。

機能分割設計は、これらの原則をフロントエンドに適用するのに役立ちます。

**抽象化**と**多態性**はレイヤーを通じて達成されます。低いレイヤーはより抽象化されているため、高いレイヤーで再利用でき、特定のパラメータや属性によってコンポーネントや機能が異なることができます。

**カプセル化**は、必要でないものを隔離する公開 APIを通じて達成されます。セグメントの内部セグメントへのアクセスは制限され、公開 APIはセグメントまたはセグメントの機能およびコンポーネントにアクセスする唯一の方法です。

**継承**もレイヤーを通じて達成されます。高いレイヤーは低いレイヤーを再利用できます。

### 従来のアーキテクチャとの比較

あなたは従来のアーキテクチャを何度も見てきたと思います。従来のソフトウェアアーキテクチャに関する内容は、その単純さのために教育記事やYouTube動画でよく扱われます。従来のアーキテクチャには明確な標準はありません。ただし、一般的には次のような形式を見ることができます。

![classical-architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3539939/72daeef7-0818-8c02-c772-98f2d59dc303.png)

従来のアーキテクチャには目立つ欠点があります。最大の欠点は、コンポーネント間の暗黙の接続とモジュールの複雑さのためにプロジェクトが保守が難しくなることです。従来のアーキテクチャの欠点は時間が経てばどんどん明確になります。プロジェクトが進化するにつれてアプリケーションアーキテクチャは混乱してしまいます。

従来のアーキテクチャは、継続的な保守がない小規模プロジェクトや個人プロジェクトには適しています。

機能分割設計は、その概念と標準のおかげで従来のアーキテクチャの問題を解決できます。ただし、FSDを使用する開発者は、従来のアーキテクチャを扱うときよりもはるかに高い理解と技術レベルを必要とします。一般的には、2年未満の経験を持つ開発者はFSDについて聞いたことがありません。
ただし、機能分割設計を使用するときは、問題を「後で」ではなく「今すぐ」解決する必要があります。コードの問題と概念から逸脱した部分はすぐに明らかになります。ただし、これは利点とも見ることができます。

### シンプルなモジュラーアーキテクチャとの比較

シンプルなモジュラーアーキテクチャにはいくつかの欠点があります。
- 機能をどのモジュールに入れるかは明確ではない場合があります。
- 他のモジュール内でモジュールを使用するのに難があります。
- ビジネスエンティティを保存するのに問題があります。
- グローバル関数と暗黙の依存関係により構造が複雑になります。

複雑または適度に複雑なプロジェクトの場合、シンプルなモジュラーアーキテクチャより機能分割設計を優先する必要があります。FSDは多くの基本的なアーキテクチャの問題を解決し、欠点もほとんどありません。

単純さと開発速度の側面から、シンプルなモジュラーアーキテクチャより機能分割設計を優先する必要があります。FSDは多くの基本的なアーキテクチャの問題を解決し、欠点もほとんどありません。

単純さと開発速度の側面から、シンプルなモジュラーアーキテクチャがFSDより有利になる場合があります。MVPが必要な場合や、寿命が短いプロジェクトを開発する場合は、シンプルなモジュラーアーキテクチャがFSDより適している場合があります。
ただし、その他の場合は、機能分割設計がはるかに優れていると思われます。

### Next.jsとFSDの衝突

最近、Next.jsを機能分割設計と一緒に使用する傾向が増えています。Next.jsはFSDとうまく機能しますが、ファイルルーティングとアプリケーションの不在という2つの領域で衝突が発生します。

#### Pages

Next.jsではpagesディレクトリがファイルルーティングを担当し、各コンポーネントが1つのルートを表します。FSDではpagesはページの平面リストを含むレイヤーとして使用されます。これにより、Next.jsページとFSDページをどのように結合するかについての衝突が発生します。

Next.jsとFSDを一緒に使用するとき、`[root]/pages/`のようにNext.jsページをアプリケーションルートに保存する方法があります。そしてFSDページは`[root]/src/pages/`のようにsrcフォルダ内に保存します。

別の解決方法は、2つのディレクトリを維持することです。FSDのページの平面リストを再び名前付けしたpages-flatとNext.jsの重なりルート用のpagesです。実際のページコードはpages-flatに保存され、その後pagesにエクスポートできます。

2つの方法を使用してもかまいませんが、私は最初の方法を好みます。

#### App

appレイヤーのすべての基本的な機能はNext.jsで処理されます。ただし、ページと独立して全体アプリケーションに対して何かを実行する必要がある場合は、レイアウトパターンを使用して全体アプリケーションのレイアウトを作成できます。

レイアウトパターンに関するNext.jsのドキュメント [Routing: Pages and Layouts](https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern)を参照してください。

### 機能分割設計の潜在力

FSDは比較的若いソフトウェアアーキテクチャ方法論です。ただし、すでに多くの銀行、フィンテック、B2B、電子商取引などのさまざまな企業で使用されています。この関連企業リストは[GitHub Issue](https://github.com/feature-sliced/documentation/issues/131)で確認できます。

現在、この記事を書いている時点で公式FSDドキュメントのGitHubリポジトリは858個のスターを受けました。このドキュメントは活発に拡張されており、FSD開発チーム、テレグラム、およびDiscordコミュニティはアーキテクチャ関連の質問がある方々のために24時間365日のサポートを提供しています。

このアーキテクチャの潜在力は非常に高く評価され、世界のさまざまな大規模企業間で広く使用されています。適切な導入が行われた場合、FSDはフロントエンド開発分野で主導的なアーキテクチャソリューションに成長する潜在力を持っています。

## アーキテクチャの長所と短所

### 長所

- アーキテクチャ構成要素を簡単に交換、追加、削除できます
- アーキテクチャ標準化
- 拡張性
- 方法論は開発スタックと独立しています
- 予期しない副作用なしでモジュール間の接続が制御されて明示的です
- アーキテクチャ方法論はビジネス指向です

### 短所

- 他の多くのアーキテクチャソリューションに比べて高い入門障壁があります
- 認識、チーム文化、および概念遵守が必要です
- 課題と問題を「後で」ではなく「今すぐ」解決する必要があります。コードの問題と概念から逸脱した部分をすぐに確認できます。ただし、これは利点とも見ることができます。

## 結論

機能分割設計は、フロントエンド開発者が利用できる興味深い価値のある発見です。FSDはチームに柔軟で標準化され、拡張可能なアーキテクチャと開発文化を提供できます。ただし、この方法論の積極的な側面を活用するには、チーム内の知識、認識、およびルールが必要です。

FSDは明確なビジネス指向、エンティティ定義、アプリケーションの機能とコンポーネント構成などの特徴により、他のアーキテクチャと比較して目立ちます。

さらに、個別のプロジェクトでFSDを使用したケースと、機能分割設計の公式ドキュメントを確認することもできます。

<br>

👉 原文は[こちら](https://dev.to/m_midas/feature-sliced-design-the-best-frontend-architecture-4noj)でご確認いただけます。

- [公式ドキュメント](https://feature-sliced.design/)
- [例. Github Client](https://github.com/ani-team/github-client)
- [例. Nike Sneaker and Footwear Store](https://github.com/noveogroup-amorgunov/nukeapp)
- [例. Sudoku](https://github.com/Shiyan7/sudoku-effector)