ひとことで言うと#
従来のレイヤードアーキテクチャ(Controller → Service → Repository)を横に切る代わりに、機能(ユースケース)単位で全層を縦に切り、各スライスが自己完結する設計手法。
押さえておきたい用語#
- Vertical Slice(バーティカルスライス)
- 1つのユースケースに必要なUIからDBまでの全レイヤーを含む縦の単位のこと。スライスごとに独立して開発・テストできる。
- Horizontal Layer(ホリゾンタルレイヤー)
- Controller・Service・Repositoryのように技術的関心で分割した横の層を指す。従来のレイヤードアーキテクチャの基本構造。
- Handler(ハンドラー)
- 1つのリクエストを受け取り処理を完結させるスライスの中核コンポーネントである。MediatRなどのライブラリでディスパッチされる。
- Cross-Cutting Concern(横断的関心事)
- 認証・ログ・バリデーションなど複数のスライスに共通する処理。パイプライン(ミドルウェア)として実装し、スライスの外に置く。
バーティカルスライスアーキテクチャの全体像#
こんな悩みに効く#
- Serviceクラスが肥大化して1ファイル1,000行を超えている
- ある機能の修正が、関係ない機能のテストを壊す
- 新機能追加のたびにRepository・Service・Controllerの3層すべてに手を入れる必要がある
基本の使い方#
具体例#
エンジニア25名のEC企業。OrderServiceが 2,800行 に膨れ上がり、注文作成・一覧取得・キャンセル・返品・配送状況更新の全ロジックが1クラスに集約されていた。1つの機能修正でOrderService全体のテスト(340件)が走り、CIに 18分 かかっていた。
バーティカルスライスに移行し、CreateOrder、GetOrderList、CancelOrder等の各Handlerに分割。各スライスは自分に必要なDB操作を直接持ち、共有Repositoryは廃止した。
スライス単位のテスト実行時間は平均 45秒。機能修正時に影響する他スライスが ゼロ になり、エンジニアのコンフリクト解消作業が月 20時間 → 2時間 に減少した。
エンジニア40名の金融系SaaS。Read/Write比率が 20:1 と読み取りが支配的だったが、レイヤードアーキテクチャでは読み取りも書き込みも同じService → Repositoryを経由しており、Readの最適化が困難だった。
まずバーティカルスライスに移行し、Command(Write)とQuery(Read)を別スライスに分離。QueryスライスはORMを使わずDapperで直接SQLを発行する形に変更。Commandスライスは既存のドメインモデルを活用した。
Read系のレスポンスタイムが 320ms → 45ms に改善。その後、Read側のみ別DBに向ける本格的なCQRS移行が 3週間 で完了している。
エンジニア6名のスタートアップ。レイヤードアーキテクチャでServiceクラスへの変更がコンフリクトの温床になり、3名が同時に作業すると日に 4〜5回 のマージコンフリクトが発生。機能開発の並列性が事実上 2名 に制限されていた。
バーティカルスライスを採用し、1機能=1フォルダ(Handler + Request/Response + テスト)の構成に変更。各エンジニアが異なるスライスを担当し、ファイルレベルでの衝突をほぼゼロにした。
マージコンフリクトが日 0.3回 に激減。6名全員の並列開発が可能になり、スプリントあたりの完了ストーリーポイントが 42 → 68 に向上した。
やりがちな失敗パターン#
- スライス間でコードを共有しすぎる — 共通化を急ぐとスライスの独立性が失われる。重複を許容し、3回以上繰り返されたら初めて共通化を検討する
- スライスの粒度が大きすぎる — 「注文管理」全体を1スライスにすると結局Serviceの肥大化と同じ。1エンドポイント=1スライスが原則
- 横断的関心事をスライス内に書く — 認証やログを各Handlerに書くと重複が爆発する。Pipelineに分離する
- 既存コードを一括で移行しようとする — 新機能からスライス方式で書き始め、既存コードは触る際に段階的に移行する
まとめ#
バーティカルスライスアーキテクチャは、レイヤードアーキテクチャの横分割に代わり、ユースケース単位で全層を縦に切る設計手法。各スライスが自己完結することでService肥大化・テスト結合・コンフリクトの問題を解消する。横断的関心事はPipelineに分離し、CQRSやModular Monolithとの組み合わせで段階的に発展させることができる。