バーティカルスライス設計(詳細)

英語名 Vertical Slice Detail
読み方 バーティカル スライス ディテール
難易度
所要時間 30分〜1時間
提唱者 Jimmy Bogard (2018) — MediatRライブラリの設計思想
目次

ひとことで言うと
#

バーティカルスライスアーキテクチャの内部設計を掘り下げ、Handlerの実装パターン・テスト戦略・共通処理の扱い方・ディレクトリ構成など、実践に必要な詳細設計のガイドライン。

押さえておきたい用語
#

押さえておきたい用語
Request / Response DTO
スライスの入出力を定義するデータ転送オブジェクトのこと。Handlerと同じファイルに配置するのが一般的。
MediatR(メディエーター)
.NETで広く使われるメディエーターパターンのライブラリ。Requestを受け取り適切なHandlerにディスパッチする。
Pipeline Behavior(パイプライン ビヘイビア)
Handlerの前後に処理を挟むミドルウェア的な仕組みを指す。バリデーション・ログ・トランザクション管理に使う。
Feature Folder(フィーチャーフォルダ)
機能単位でHandler・DTO・テストを1つのフォルダに格納するディレクトリ構成である。レイヤー別フォルダの対極にある構成。
Integration Test(統合テスト)
スライス全体をAPIリクエストからDB操作まで通して検証するテスト。バーティカルスライスのテスト戦略の中心となる手法。

バーティカルスライス設計の全体像
#

スライスの内部構造:Request → Pipeline → Handler → Response
Request入力DTOバリデーションルール定義型安全な入力PipelineValidationLoggingTransaction横断処理HandlerビジネスロジックDB操作外部API呼び出しコア処理Resp出力DTO型安全Feature Folder 構成Features/Orders/CreateOrder/Command.cs + Handler.csValidator.cs + Test.cs従来のレイヤー別構成Controllers/OrderController.csServices/OrderService.csRepositories/OrderRepository.cs機能に関連するファイルが1箇所に集約される
スライス設計の実装フロー
1
Request/Response定義
入出力DTOとバリデーションルールを定義
2
Handler実装
ビジネスロジックとDB操作を1クラスに
3
統合テスト作成
APIリクエストからDBまで通すテストを書く
Feature Folder配置
関連ファイルを機能フォルダに集約

こんな悩みに効く
#

  • Handlerの実装パターンが定まらずチーム内でバラつく
  • 共通処理をどこに置くかの判断基準がない
  • バーティカルスライスのテストの書き方がわからない

基本の使い方
#

Request/Response DTOをスライスごとに定義する
入力(Command/Query)と出力(Response)をスライス専用のDTOとして定義する。他のスライスとDTOを共有しない。FluentValidationなどでバリデーションルールもRequest側に定義する。
Handlerにビジネスロジックとデータアクセスを集約する
1つのHandlerが1つのユースケースを完結させる。DB操作はORMやDapperで直接行い、Repositoryクラスは作らない。Handlerが長くなりすぎたら(100行超)、ドメインオブジェクトにロジックを移す。
Pipeline Behaviorで横断処理を実装する
バリデーション・ログ・トランザクション管理はPipeline Behaviorとして実装する。Handlerの前後に自動的に実行され、各スライスには書かない。MediatR(.NET)、ts-mediator(TypeScript)などのライブラリを使う。
Feature Folder構成でファイルを配置する
Features/{Domain}/{UseCase}/ の構成で、Handler・DTO・Validator・テストを1フォルダにまとめる。1機能の変更に必要なファイルが1箇所に集約され、ナビゲーションが容易になる。

具体例
#

例1:HRテック企業がHandler実装ガイドラインを策定する

エンジニア20名のHRテック企業。バーティカルスライスを採用したが、Handlerの書き方がエンジニアごとにバラバラで、あるHandlerは 300行、別のHandlerは 15行(ロジックがServiceに外出し)という状態になった。

実装ガイドラインを策定。「Handlerは 30〜100行」「DB操作はHandler内で直接」「100行超はドメインオブジェクトにロジックを移す」「共有ServiceはPipelineのみ」とルール化した。

コードレビューでの指摘が 60% 減少。新メンバーのオンボーディングでも「どこに何を書くか」の迷いが解消され、初PRまでの期間が 2週間 → 4日 に短縮された。

例2:物流SaaSがスライス単位のテスト戦略で品質を向上させる

エンジニア35名の物流SaaS。レイヤードアーキテクチャ時代は、Serviceのユニットテスト(Mock多用)とE2Eテストの2極構成だった。Mockの保守コストが高く、E2Eは実行に 45分 かかっていた。

バーティカルスライス移行に合わせ、テスト戦略を「スライス単位の統合テスト中心」に変更。TestContainersでDBを起動し、APIリクエストからDB検証まで1テストで完結。Mockは外部APIのみに限定した。

テストのMock行数が 70% 減少。テスト実行時間は 45分 → 12分 に短縮(E2E削減分)。本番バグの発見率が テスト段階で78%(以前は 52%)に改善された。

例3:教育プラットフォームがFeature Folderで開発者体験を改善する

エンジニア12名の教育プラットフォーム。Controllers/48ファイルServices/35ファイルRepositories/28ファイル が並ぶレイヤー別構成だった。「受講登録」機能の修正に3フォルダを行き来する必要があり、新メンバーが「どのファイルがどの機能か」を把握するのに 1週間 かかっていた。

Feature Folder構成に移行。Features/Enrollment/Register/にHandler・DTO・Validator・テストを集約。IDEのファイルツリーで機能の全体像が一目で把握できるようになった。

新メンバーが特定機能のコードを見つけるまでの時間が 平均15分 → 30秒 に短縮。「どこに書けばいいかわからない」というSlackの質問が月 12件 → 1件 に減少した。

やりがちな失敗パターン
#

  1. Handlerが巨大になる — 200行を超えたらドメインオブジェクトにロジックを移す。Handlerはオーケストレーターに徹する
  2. DTOをスライス間で共有する — 初期は効率的に見えるが、片方の変更がもう片方を壊す。スライスごとに専用DTOを定義する
  3. ユニットテストにこだわりすぎる — スライスは統合テストが最もコスパが高い。Mockを減らしTestContainersで実DBを使うテスト戦略を採る
  4. Feature FolderとLayer Folderを混在させる — 中途半端な移行は混乱を招く。新機能からFeature Folderで書き始め、既存コードは触る際に移行する

まとめ
#

バーティカルスライス設計の詳細として、Request/Response DTO → Pipeline → Handler → Responseの処理フロー、Feature Folder構成によるファイル配置、統合テスト中心のテスト戦略を解説した。Handlerは30〜100行に収め、横断処理はPipeline Behaviorに分離し、各スライスの自己完結性を維持することが設計の要点となる。