プレイブック
レイヤーからフィーチャへ: 垂直スライスはなぜ生まれたのか? (Vertical Slice From Layers To Features)
階層構造のアーキテクチャが成長するにつれて変化が遅くなるのはなぜですか?垂直スライスのフォルダー レイアウトではありません。機能の所有権、動作の局所性、スイッチング コストの決定…
垂直スライス — 機能指向エンジニアリング
一部 1 の 4
まず CRUD とレイヤーを責めないようにしましょう
階層化アーキテクチャは、多くの中小規模のシステムにとって良いスタート地点となります。コントローラー、アプリケーション サービス、リポジトリ、データ アクセスの分離。これにより、チームに共通の技術言語が与えられます。問題は、これらの層の存在ではありません。問題は、単一のユーザー要求が時間の経過とともにすべてのレイヤーに広がり、それぞれの変更が調整タスクになってしまうことです。
ある日、注文品に納品書を追加してほしいという一見単純な依頼が届きます。```text Controller → Request / DTO → Service → Validator → Repository → Mapping → Test doubles → Tests
## 最初に説明した概念```text
📦 Vertical Slice
Bir kullanıcı niyetini request'ten veri kaydına ve teste kadar tek sınırda tutan uçtan uca özellik birimi.
📦 Davranışın yerelliği
Bir davranışı anlamak veya değiştirmek için gereken kodun birbirine fiziksel olarak yakın olması.
📦 Temporal DRY
Bugün benzer görünen kodun, yarın aynı sebeple değişip değişmeyeceğini sorgulayan DRY yaklaşımı.
📦 Wrong abstraction
Sadece tekrar var diye erken paylaşılan; zamanla farklı ihtiyaçları birbirine bağlayan soyutlama.
```垂直スライスはレイヤーを禁止しません。機能内で技術的な区別を維持します。機能の外側の制限は、ユーザーの意図、ビジネス ルール、所有権によって決まります。
## ストーリー: レイヤーの速度が低下するのはいつですか?
初日の `CreateOrder` は小さくなります。 1 つのコントローラー、1 つのサービス、1 つのリポジトリで十分だと思われます。次に、在庫管理、キャンペーン ルール、配送設定、監査記録が追加されます。すべての属性が同じ `OrderService` に分類される場合、システム内で最も危険なファイルが、一般的に最も使用されるファイルになります。```text
Yeni özellik
→ ortak Service'e dokunur
→ ilgisiz testleri etkiler
→ farklı ekiplerin release'ini bekler
```CRUDは壊れていません。モデル層とアプリケーション層の責任は異なります。垂直スライスの質問は、「この動作を変えるビジネス上の意図は何ですか?」です。
## 水平および垂直組織
|基準 |レイヤー中心 |機能重視 |
| --- | --- | --- |
|組織軸 |技術的な役割 |ユーザーの意図 / 機能 |
|交換単位 |複数のレイヤー上のファイル |単一機能の制限 |
|コード共有 |初期の共通サービスの傾向 |実績のあるパートナーシップ |
|ナビゲーション |コントローラー → サービス → リポジトリ |機能 → リクエスト → ハンドラー → テスト |
|エラー効果 |共通層を介して伝播可能 |フィーチャはその境界部分でより目立つままになります。```text
❌ Controllers / Services / Repositories
→ OrdersController
→ OrderService
→ OrderRepository
✓ Features / Orders / CreateOrder
→ Request
→ Validator
→ Handler
→ Response
→ Tests
```この違いはフォルダ名だけではありません。これは、変更の検索、理解、テスト、ロールバックのコストに影響します。最悪の場合、ファイル `n` の数に対して機能内の検索コストが O(n) にとどまる場合でも、関連するコードを併置することで、間違ったディレクトリでの検索や精神的なスイッチの数が減ります。
## Screaming Architecture: ディレクトリ構造は何を伝えるべきでしょうか?
プロジェクトを開いたときに最初に表示されるフォルダーが `Controllers`、`Services`、および `Infrastructure` の場合。システムテクニカルツールについて説明します。 `Orders`、`Catalog`、`Billing`、および `Returns` はビジネス フィールドを説明します。アーキテクチャのフレームワークではなく、製品の意図を叫ぶ必要があります。
`CancelOrder` の変更では、開発者はハンドラー、検証、応答、および動作のテストを同じ場所で見つけます。また、新しいチームメンバーの学習曲線も短縮されます。ただし、機能フォルダーは、すべてが公開される小さな一枚岩ではありません。エントリーポイントは開いたままです。詳細は機能に隠されています。
## 凝集、カプセル化、戦略的複製
スライスは、別のスライスの内部実装を認識してはなりません。共同動作が本当に安定していて、少なくとも複数の独立したニーズによって同じ理由で変化する場合、共同動作は共有される必要があります。それ以外の場合、`Shared` フォルダーは、境界線が表示されない新しいレイヤーになります。```text
CreateOrder
→ Order aggregate'e komut verir
→ local transaction'ı tamamlar
→ response üretir
CancelOrder
→ kendi kurallarını uygular
→ CreateOrder'ın handler'ını çağırmaz
```このアプローチでは、重複が適切な代償となる場合があります。異なるビジネス上の決定により 2 つの類似したコードが変更される場合、それらを早期にマージすると、将来的に各変更が O(k) 依存機能に反映される可能性があります。
## 遷移信号
見た目がモダンなだけでは、垂直スライスに切り替えるには十分ではありません。次のシグナルが同時に発生すると、投資が利益をもたらします。
1. 単純なリクエストが常に多くのレイヤーでの変更を必要とする場合。
2. 共通サービスに小さな変更を加えると、無関係な機能テストが中断されます。
3. 模擬集中テストの場合、動作は保存されますが、内部呼び出し順序は保存されません。
4. チームがビジネス ルールがどのファイルに存在するかを把握するのに苦労している場合。
5. 異なる機能の所有者と配信リズムが分離されている場合。
これらの制限を文書に残すべきではありません。 .NET のアーキテクチャ テストを使用すると、ある機能が別の機能の内部詳細に依存していないことを確認できます。ルールのコストは、コンパイルまたはテスト段階での O(依存関係) スキャンです。利点は、違反が運用環境に到達する前に現れることです。
## DDD と CQRS の関係
垂直スライスはアプリケーションを整理します。 DDD は、ビジネス ルールと言語がどこに存在するかを説明します。一方、CQRS は、ユースケースのコマンド側とクエリ側のフローを分離できます。これらは競合他社ではなく、意思決定の異なる層です。```text
Feature boundary → Vertical Slice
Consistency rule → DDD Aggregate
Read / write flow → CQRS
Deployment unit → Modular monolith veya microservice
```まずモジュラーモノリス内の機能境界を検証することで、マイクロサービスのコストを早期に支払うことなく独立性の主張をテストできるようになります。
## 誤った信頼を生み出す一致```text
❌ Vertical Slice = klasörleri yeniden adlandırmak
✓ Kullanıcı niyeti, davranış ve sahipliği aynı sınırda tutmaktır.
❌ DRY = her benzer kodu paylaşmak
✓ Aynı nedenle değişen kodu paylaşmaktır.
❌ Handler = tüm iş kuralları
✓ Handler orkestrasyon yapar; domain kuralları uygun domain modelinde yaşar.
❌ Vertical Slice = mikroservis
✓ Önce modüler monolith içinde doğrulanabilen application boundary'dir.
❌ Shared = ücretsiz yeniden kullanım
✓ Shared, sürümleme ve koordinasyon maliyeti de getirir.
意思決定チェックリスト
- このコードは同じユーザーの意図によって変更されていますか?
- 機能のリクエスト、検証、ハンドラー、レスポンス、テストは同時に存在できますか?
- 別の機能の内部クラスにアクセスせずにニーズを満たすことはできますか?
- この共通の抽象化は、少なくとも 3 つの独立した場所で同じ理由で変更されますか?
- 集計ルールとアプリケーション オーケストレーションは分離されていますか?
- 機能の境界はモジュラーモノリス内のアーキテクチャテストによって保護されていますか?
- 変更後にエラーの影響、テストカバレッジ、ロールバックパスが表示されますか?
目標は、フォルダーをさらに作成することではありません。目標は、動作を変更するために必要な意思決定とコードの面積を減らすことです。
この記事で覚えておくべきこと
- 階層化されたアーキテクチャは悪くありません。ただし、交換単位が複数のレイヤーに分散すると、調整コストが増大します。
- 垂直スライスでは、技術的な役割ではなく、ユーザーの意図と行動を中心にコードを配置します。
- 戦略的複製は、誤った抽象化よりもコストがかからない可能性があります。
- 垂直スライス。 DDD は、CQRS およびモジュラー モノリスと連携して機能するアプリケーション構成の決定です。
垂直スライスの目的は、ファイルを垂直に配置することではありません。変更の影響を正しい機能制限に保つことです。
次のセクションでは、リクエスト、検証、ハンドラー、マッピング、テストを使用して、スライスが内部からどのように機能するかを調べます。
FAQ
よくある質問
垂直スライスとは何ですか?
リクエストからデータ記録、テストまで 1 つの境界内でユーザーの意図を維持するエンドツーエンドの機能ユニット。
行動の地域性は何ですか?
動作を理解または変更するために必要なコードは、互いに物理的に近接しています。
「垂直スライス=フォルダ名の変更」は正しいでしょうか?
ユーザーの意図は、行動と所有権を同じ境界に保つことです。
このセクションでは何を修正しますか?
8 つのファイルを変更するだけでも間違いではありません。ただし、これらのファイルが同じ動作に対して、同じチームによって同時に変更された場合は、ファイル システムは、ビジネス上の価値ではなく、技術的な役割を表現し始めています。垂直スライスは、この摩擦に対する現実的な解決策です。階層化されたアーキテクチャは悪くありません。ただし、交換単位が複数のレイヤーに分散すると、調整コストが増大します。階層化アーキテクチャは、多くの中小規模のシステムにとって良いスタート地点となります。コントローラー、アプリケーション サービス、リポジトリ、データ アクセスの分離。これにより、チームに共通の技術言語が与えられます。問題は、これらの層の存在ではありません。問題は、単一のユーザー要求が時間の経過とともにすべてのレイヤーに広がり、それぞれの変更が調整タスクになってしまうことです。
学んだエンジニアリング原則
- コードの構成では、技術層の前に変更の理由が見えるようにする必要があります。
- 動作の局所性は、ナビゲーションとテストのコストを削減するためのアーキテクチャ上の決定です。
- 共有は、変更の理由が共通している場合にのみ価値があります。それ以外の場合は、複製の方が安全である可能性があります。
続きを読む
続きを読む
シリーズの次のシリーズ
内側からの垂直スライスはどのように機能しますか?
垂直スライスは、リクエストから検証、ハンドラーから集計、アウトボックス イベントからモデルの読み取り、そしてクラウド コストまで、内部的にどのように流れるのでしょうか? CQRS…
関連記事
CRUD (作成、読み取り、更新、削除) から CQRS (コマンド クエリ責任分離) まで: 問題はコードではなくモデルです
CQRS とは何ですか? CRUD と CQRS の違いは何ですか? CQRS はどのような場合に使用する必要がありますか?大規模システムでは単一モデルでは不十分な理由を説明するガイド。
関連記事
DDD - データベースのためではなく、ビジネスのためのソフトウェアを設計する
ドメイン駆動設計とは何ですか?データベース駆動設計の限界、共通言語の力、DDD が実際の投資となる場合についてのガイドです。