
この記事は基本に立ち戻りアーキテクチャの選定を試みた際の備忘録です。
Feature-Sliced Design(FSD)や Vertical Slice Architecture など、モダンなアーキテクチャがありますが、どのような判断をもとに選定するのかを考え直します。
アーキテクチャを理解するために、以下のような学習のための地図を作りました。
設計原則、アーキテクチャ、個別の設計パターンへと詳細になっていきます。
ソフトウェア設計
│
├── 設計原則
│ ├── Separation of Concerns
│ ├── 高凝集・低結合
│ ├── コロケーション
│ ├── Dependency Inversion
│ ├── SRP
│ └── DRY / KISS / YAGNI
│
├── アプリケーション全体の構造
│ ├── Layered Architecture
│ ├── Feature-Based Architecture
│ ├── Vertical Slice Architecture
│ ├── Clean Architecture
│ └── Feature-Sliced Design
│
├── UI・Presentationの設計
│ ├── MVC
│ ├── MVP
│ └── MVVM
│
└── より細かな設計パターン
├── Repository
├── Factory
├── Adapter
└── Dependency Injection
このコードは何を担当しているのかを考えるのが最初の問です。
商品一覧画面を作るときに
商品を取得する
商品を表示する
商品を検索する
商品を並び替える
商品を編集する
といったタスクを書き出します。
これら全てを一つの巨大なコンポーネントとして作ることもできますが、管理が大変になるのは皆さんもお分かりだと思います。
参考:https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html?utm_source=chatgpt.com
ここからどこまでを同じモジュールとして管理するのか?という設計の問題が始まります。
CohesionとCouplingはそれぞれ、凝集度、結合度というようです。https://qiita.com/dsudo/items/ee3fee1f558c7f1b359f
Cohesionは関係するコードがまとまっているか?
Couplingは別のコードにどれだけ依存しているか?
です。
例えば以下のようなコードがあります。
components/
ProductList.tsx
hooks/
useProducts.ts
api/
products.ts
types/
product.ts
tests/
ProductList.test.tsx
技術的な種類ごとに整理されていますが、商品一覧のコーディングをするのにそれぞれ別のディレクトリを行き来する必要があります。
一方で、以下のように書いた場合はどうでしょうか?
features/
└── products/
├── ProductList.tsx
├── useProducts.ts
├── api.ts
├── types.ts
└── ProductList.test.tsx
この書き方なら、商品に依存するコードがまとまっています。
この書き方が Feature-based Architecture, Vertical Slice Architecture に繋がっていきます。
colocation
Place code as close to where it’s relevant as possible
同じ種類のコードを集めること
ではなく、
一緒に変更されるコードを近くに置くこと
です。
https://kentcdodds.com/blog/colocation?utm_source=chatgpt.com
ここからアーキテクチャの話です。
Layered Architectureでは、技術的責務でアプリケーションを分離します。
Presentation
↓
Application
↓
Domain
↓
Infrastructure
これのメリットは責務がわかりやすいところです。
しかし、この方法では前述までとは変わり、機能を変更するときに、横断して変更する可能性があります。
つまり、技術的には分かれている一方で、機能は複数に分散するわけです。
Layered Architecture に対して、異なる方法がVertical Slice Architecture です
変更の軸に沿って関連する処理をまとめる考え方です。
features/
├── create-order/
├── cancel-order/
├── get-order-list/
└── update-order/
このようにしたり、
create-order/
├── UI
├── validation
├── application logic
├── database access
└── tests
このように書けます。
これは機能(ユースケース)で縦に切る。という方法です。
https://www.jimmybogard.com/vertical-slice-architecture/?utm_source=chatgpt.com
React界隈で盛り上がっている?ように感じているFSDについてです。私がReactを業務で描き始めた頃はAtomicデザインが出始めていた頃だったと思うのですが、こちらの方が優位では?みたいな流れな気がしています。
FSDは公式のドキュメントがあるので、それを一読すると良さそうです。
私も完全に理解しているわけではないのですが、備忘録として、、、。
app
pages
widgets
features
entities
shared
このようなレイヤーを用意します。
Layer
↓
Slice
↓
Segment
という段階で整理するようです。
features/
└── add-to-cart/
├── ui/
├── api/
└── model/
この場合であれば、
features: Layer
add-to-card: Slice
ui, api, model: Segment
と対応するようです。
またUI周りの責務をどう分けるかの話で、MVC, MVP, MVVMの話があがります。
まずソフトウェアでの責務とは
コードが何を担当し、何を決定する責任を持つか
といった意味になります。
例えば商品一覧なら、
1. 商品データを取得する
2. 商品データを保持する
3. 検索条件を管理する
4. 商品を絞り込む
5. HTMLとして表示する
6. ボタンが押されたときの処理をする
といった処理があります。
これを全部同じコンポーネントに書くこともできますが、API仕様の変更やデザインの変更、検索ロジックの変更など、いろいろな理由でこのコンポーネントが変更されるます。
この状態が責務が多すぎる状態です。
MVCであれば、Model, View, Controller に分けて、
Model
商品
価格
在庫
検索処理
View
商品名を表示
価格を表示
ボタンを表示
Controller
検索ボタンが押された
↓
Modelに検索させる
↓
結果をViewへ反映
のように責務を分けます。
MVVMも同様に責務を分離します。
View
↓
「productsを表示するだけ」
ViewModel
↓
「products、isLoading、errorをView用に準備する」
Model
↓
「商品データやビジネスルール」
このドキュメントではFSDは他のアーキテクチャとの違いが述べられていて参考になりました。
コロケーションについて着目して有用性を説いている点が参考になりました。
この記事をシェア
coiai
この記事もおすすめ
株式会社coiaiは、「想像できることを美しく実現」を掲げ、XR・Web・アプリ・システム開発およびDX支援を行う会社です。 創業2022年、東京都練馬区に本社を置き、要件のヒアリングからPoC(概念実証)、本番運用まで一貫して伴走します。 まずはお気軽にご相談ください。
主なご相談内容
詳しい会社情報は会社概要ページでご覧いただけます。