Vertical Slice Architecture に関する .NET Conf 2023 セッションのまとめ
開発チームの川江です。最近、社内で Vertical Slice Architecture (VSA) が話題になっています。.NET Conf 2023 の以下のセッションでも取り上げられており、一般的にも注目を集めていることが伺えます。勉強のために、セッションの内容をまとめてみました。
Vertical Slice Architecture の基本の考え方
このセッションによると、Vertical Slice Architecture には以下の基本的な考え方があります。
-
同じ機能に関するコードは同じ場所に置く。
-
システムを、クリーンアーキテクチャのように技術的な要件で水平に分けるのではなく、機能毎に縦(垂直)に分ける。
セッションの内容
セッションは、これまでに登場してきた主なアーキテクチャと、それぞれのアーキテクチャのメリット・デメリットの紹介、という流れで進みます。
スパゲッティアーキテクチャ
アーキテクチャがないとどうなってしまうのか
アーキテクチャがない、いわゆるスパゲッティアーキテクチャの問題点は、プレゼンテーションロジック・ビジネスロジック・システムロジックがごちゃごちゃに混ざってしまうこと(それぞれのフォルダに分けることである程度解決できるかもしれない)。これはおそらくモノリスと呼ばれる。
モノリス(スパゲッティアーキテクチャ)のメリット
- 抽象化がほとんどない。
- 素早く実装できる。
- 抽象度の低さと結合度の高さにより、パフォーマンスは良い可能性がある。
モノリス(スパゲッティアーキテクチャ)のデメリット
- システムの規模が大きくなるにつれて、新機能の開発にかかる時間とコストが飛躍的に増大する。
- 複数のチームが同時に同じコードベースに取り組むのが難しくなる。
- コードが密に絡み合っているため、技術の変更がシステム全体に影響する。
- テストが難しい。
N層アーキテクチャ
技術上の課題を分離する
アーキテクチャを、まずプレゼンテーションロジックを処理し、次にビジネスロジックレイヤー、さらにデータアクセスレイヤーへと順に処理を進め、最終的にデータベースに到達するよう変更する。これはN層アーキテクチャ、この場合は特に3層アーキテクチャと呼ばれる。
N層アーキテクチャのメリット
- 直感的に理解しやすく、複雑な抽象化が少ない。
- 比較的早く実装できる。
- スパゲッティアーキテクチャよりはテストしやすい。
N層アーキテクチャのデメリット
スパゲッティアーキテクチャと同様のデメリットがある。
- システムの規模が大きくなるにつれて、新機能の開発にかかる時間とコストが飛躍的に増大する。
- 複数のチームが同時に同じコードベースに取り組むのが難しくなる。
- 技術の変更がシステム全体に影響する(すべてがデータアクセスに依存してしまう)。
クリーンアーキテクチャ
ビジネスと技術上の課題を分離する
次に、ビジネスロジックと技術上の課題を分離するようアーキテクチャを変える。プレゼンテーション層はそのまま残し、データアクセスとビジネスロジックを別のレイヤーに分ける。アプリケーション層は主にビジネスロジックを担当し、ドメイン層はデータモデルを定義している。ドメイン層は前のアーキテクチャではデータアクセス層にあったが、ここでは明示的に分離する。重要なポイントは、データアクセス層(インフラストラクチャ層)が図の上部にある、つまりシステム外部にあることで、システム全体がデータアクセス層に依存しないことを意味する。
これは、見慣れたクリーンアーキテクチャの「オニオン」で、図のグレーのレイヤーはアプリケーションの中核部分となる。特定の技術に依存する要素はシステムの外側に配置され、各レイヤーは内側に向かって依存する。
クリーンアーキテクチャについては、Uncle Bob によるクリーンアーキテクチャの図の中心、黄色の Entities の部分に関してよく誤解がある。そこには Enterprise Business Rules とあるが、外側のアプリケーション層(図では Use Cases)には Application Business Rules と注釈がある。この部分に関する一つの解釈は、ドメイン層 (Entities) には外部の存在を認識しないロジックを入れるべき、というもの。アプリケーション層では、データベースや Web API など外部システムとのインタフェースやポートを用意できる。
クリーンアーキテクチャのメリット
- 大規模システム向けの高度な抽象化が可能。
- インフラを外部に切り離すことで、技術変更に対する耐性が向上する。
- テストが容易になる。
- 内側のレイヤーは外側のレイヤーの影響を受けない。
- 一貫した速度で拡張していける。
- 複数チームでの作業分担が容易。
クリーンアーキテクチャのデメリット
- 理論的な要素が多く、理解するにはかなりのトレーニングが必要になるので、導入のハードルが高い。
- チームに規律がないとうまく生かせない。
- 開発速度は遅くなりやすい(しかし、複雑なシステムを長期間に渡って実装する場合にはクリーンアーキテクチャはとても有効)。
- シンプルな機能の実装のために、幾つものプロジェクトに大量のコードを書かなくてはならない。
(最後の問題点について)本当にシンプルなアプリ開発の場合、クリーンアーキテクチャではなく、スパゲッティアーキテクチャやN層アーキテクチャを採用できる。生じるデメリットは、間違ったアーキテクチャを採用した結果かもしれない。一方でシステムが複雑な場合、単純な機能のために多くのコードを書く必要があるのは正当化できる。
クリーンアーキテクチャではリクエストやユースケースで何が起こるのか
クリーンアーキテクチャでは、処理がレイヤーごとに水平に配置される。プレゼンテーション層では各操作(リクエスト)に対してエンドポイントを用意する。アプリケーション層ではサービスやバリデーションを、ドメイン層ではエンティティを扱う。インフラ層ではデータベースを操作する。コードは技術的な関心事に沿って、この4つのレイヤーに分割される。
しかしこの構造では、機能がプロジェクト全体に散らばってしまう、という問題が生じる。大量の機能を持つ大規模なコードベースではこの問題が顕著になる。一つ一つの機能に関するフォルダがすべてのレイヤーに存在するため、(コーディングのために)頻繁にスクロールをしなくてはならない。
Vertical Slice Architecture
Proximity Principle (近接性の原理)
Vertical Slice Architecture の核となる(とスピーカーが考える)一つの原則がある。それは近接性の原理である。
Code that is changed together should live together.
(一緒に変更されるコードは一緒に配置されるべきである。)
これは、同じユースケースやユーザーストーリーに関するコードは、複数のプロジェクトに分散させるのではなく、すべて同じフォルダにまとめておくべき、ということ。例えば、「ToDoアイテムを完了済みにする」というユースケースを実現するために必要なすべてのコードは、同じフォルダにまとめておくべきである。
Vertical Slice Architecture で再構築する
先ほどの CRUD を Vertical Slice Architecture で再構築する。クリーンアーキテクチャのレイヤーはそのままで、その上にフォルダを配置する。"ToDo" を機能のフォルダとして配置し、その下に "Read" などのフォルダを置く。そして縦に区切り線を引く。"Vertical Slice" という名前はこれに由来する。クリーンアーキテクチャは水平方向にスライスするが、Vertical Slice Architecture では垂直方向にスライスする。
具体的にはどんな風になるか
Web API の場合、一つの ASP.NET Core ホストアプリケーションに上図のように4つの機能フォルダがあり、それぞれに3つのレイヤーが含まれるかもしれない。機能フォルダ上部にはプレゼンテーションロジック、中間にはビジネスロジック、下部にはデータアクセスロジックがある。
Vertical Slice Architecture では、各機能(スライス)が独立しているので、スライスごとに好きなように処理を記述できる。1行のコードや1つのファイルだけでも良いし、大きな関数を書くこともできる。この図のようにクリーンアーキテクチャにしても良い。
もっとも、何でもできるから何をしても構わない、ということではない。何事もトレードオフなので、適切なバランスを見つける必要がある。
Vertical Slice Architecture のメリット
- 抽象化が少ない。各機能の構成は自由で、抽象化の層は少なくなる。
- 導入のハードルが低い。
- 技術変更が容易。機能がそれぞれ分離しているので、他の機能に影響を与えずに個別の機能の技術を移行できる。
- 機能ごとのテストがやりやすい。
- 複数チームでの作業がしやすい。共有コード以外のそれぞれの機能について作業している場合、同じコードベース内の他のチームや製品に影響を与える心配がないため、安全に作業できる。
- デプロイが容易。各機能を個別にデプロイすることができるため、開発・デプロイサイクルが速くなる。
Vertical Slice Architecture のデメリット
- 機能ごとの連携の仕組みが必要。アプリ内の各機能は完全に独立しているわけではなく、機能同士の通信が必要になる場合もある。そのため、機能間のメッセージングを明確にしなくてはならず、それによって複雑性は増す。
- 共有コードと機能コードの線引きが難しい。また、複数の機能に重複するコードが存在する可能性が高くなる。
- 機能ごとにコードの書き方が異なる可能性がある。複数のチームが別々の機能を開発するとそうなりやすく、後から加わる開発者が機能ごとに全く異なるコードを見て混乱するかもしれない。開発者は人間なので、認知負荷の問題は考慮すべき重要な点である。
Vertical Slice Architecture の実装デモ
スピーカーである Luke Parker さんによる 以下の VSA ソリューションテンプレートを用いた実装デモ(文章でまとめるのは大変なので省略します)。
結論
どのアーキテクチャを採用すべきか
考慮すべきは、開発チームの人数、プロジェクト期間、解決しようとしている問題およびプロダクトの複雑さ、など。
開発者数が少ない場合、モノリシックなアーキテクチャでも十分機能する場合が多いだろう。開発期間がとても短い場合も、抽象化に伴う時間の投資はそれに見合う価値がないため、モノリシックなアーキテクチャでも問題ない。
ビジネスドメインは複雑だが、システムの構成は単純、という場合は、ドメイン駆動設計やクリーンアーキテクチャといったアプローチが有効になる。
副作用の明確化や、コード変更の容易性を確保したい場合、Vertical Slice Architecture が選択肢の一つになる。
Summary
-
データアクセス層を外部化するのがクリーンアーキテクチャの鍵。これによりテスト容易性と変更耐性を向上できる。
-
Vertical Slice Architecture は、視点を技術的な観点からビジネスロジックやユースケースの観点へと変化させる。
セッションの感想
個人的には VSA とその考え方はとても良いと思います。Luke Parker さんが提唱していた原則、"Code that is changed together should live together." にとても共感しました。
一方、セッションで述べられていたとおり、絶対的に優れているアーキテクチャはなく、いずれにもメリット・デメリットがあるので、状況によって最適なものを選択する必要があります。これは言ってみれば当たり前ですが、開発者が忘れてしまいがちなことでもあるかもしれません。
ところで、Vertical Slice Architecture の日本語訳って何になるんでしょうか。現状日本語の資料がほとんどなく、ふさわしい訳語も見つけられなかったので、この記事内では英語表記で通しました。普通にカタカナ表記だと、バーティカルスライスアーキテクチャ。少し長いんですよね。垂直スライスアーキテクチャ?それとも、縦割りアーキテクチャ?誰か偉い人が良い訳語を考えてくれることを期待したいと思います。
Discussion