タイトルはざっくりしていますが、年々複雑化するソフトウェア開発を背景に様々な設計概念、実装が編み出されています。
例えば言語体系によるデザインパターンやドメイン駆動設計(DDD)、あるいはインフラ領域であるクラウドデザインパターンなども単なるテンプレートではなく、そこから何か新しい概念や実装を生み出す「変化の場」として活用され始めてきています。
クラウドネイティブはそういう変化の場で生まれ、OSSに形を変え、ユーザーのニーズを満たせるアプリケーションとして提供されています。
今回はそのクラウドネイティブな環境で有効なアプリケーションアーキテクチャーをざっくりまとめてみました。
マイクロサービスアーキテクチャー
マイクロサービスアーキテクチャーはコンテナ技術の発展とともにクローズアップされ、Kubernetesのようなコンテナクラスター環境で最も活用されます。
マイクロサービスそのものの説明はまた別の記事で深く書きますが、まずはそのマイクロサービスアーキテクチャーの背景について考察してみます。
ドメイン駆動設計(DDD)
ドメイン駆動設計(以下、DDDと略します)はEric Evansの著書「Domain-Driven Design」で深く書かれています。DDDの本質は当時主流であったモノリシックなシステムデザインとウォーターフォール型のマネジメントに対する、アプリケーション開発の本質を説いたものと理解しています。DDDではアプリケーション開発における本質的考えを中心に構成され、非常に難解ですが現在におけるマイクロサービスアーキテクチャーの原点とも言えるものです。
DDDの基本的な考え方は以下です。
- ドメインの中核となる複雑さと機会に焦点を当てる
Focus on the core complexity and opportunity in the domain - ドメイン専門家とソフトウェア専門家のコラボレーションでモデルを探求する
Explore models in a collaboration of domain experts and software experts - 明示的にそれらのモデルを表現するソフトウェアを書く
Write software that expresses those models explicitly - 境界付けられたコンテキストの中のユビキタス言語で話す
Speak ubiquitous language within a bounded context
恐らく多くの方は上記のような説明を聞いてもあまりピンとこないのではないでしょうか?(私もです)
DDD非常に難解ではありますが、ドメイン(実現したい機能)とユースケース(実現するプロセス)を最小化する設計を行うわけです。
故にマイクロサービスアークテクチャーを実践する上で避けて通れない重要なアプリケーションアーキテクチャーになります。
DDDに関連するアーキテクチャーの整理
DDDでは様々なアーキテクチャーが登場します。このアーキテクチャー全てを理解することは困難ですが、基本となるアーキテクチャーを整理するとわかりやすいかもしれません。
レイヤードアーキテクチャー
レイヤードアーキテクチャーはDDDの基本的な考え方であり、まずはこのレイヤードアーキテクチャーを視覚的に理解することをおすすめします。
上層のPresenteationはUIだと想定するとわかりやすいかもしれません。このアーキテクチャーで最も重要なことは各層の依存関係になります。
基本的には上の層から下の層のみ許可をするという依存関係を構築していきます。
Domain層がApplication層とInfrastructure層の間にあることに注目してください。
このDomain層にビジネスロジックを集中させます。レイヤー間での依存関係をより明確に分けるためにビジネスロジックを挟むわけです。
一般的なMVCの原型になりますね。
ヘキサゴナルアーキテクチャー
僕はこのヘキサゴナルアーキテクチャーが全てではないかと考えています。もちろんそうではない、という意見もありますがモダンアーキテクチャーはたいていヘキサゴナルアーキテクチャーを基に作られている事が多いです。ヘキサゴナルアーキテクチャーはAlistair Cockburnという人が書いたブログが発端と言われています。
ヘキサゴナルアーキテクチャーは別名「Ports and Adapters Pattern」とも呼ばれており、中心的な考え方は以下です。
- 外部からのイベントをPortsがキャッチしたらそれに必要なアダプタがそのイベントをアプリケーションに届ける
- アプリケーションから外部へ何かデータを渡したいときもPortsを通じてアダプタへ渡される
- アプリケーションは自分に必要なアダプタしか見えない
ここで重要なのはアプリケーションの独立性です。レイヤードアーキテクチャーは最下層にInfrastructureがあるので、依存関係からDomain層にあるビジネスロジックはInfrastructureに依存します。
そうなるとアプリケーションは上下の依存関係から独立したドメインに本質的にはなることが出来ません。なのでInfrastructureを外に外し、内部にDomain Modelを入れました。
依存は外から内へと変化しています。ドメインモデルを置くことでアプリケーション独立性を保ちます。MVCの形が出来てきましたね。
オニオンアーキテクチャー
オニオンアーキテクチャーはヘキサゴナルアーキテクチャーと本質的に同じと理解しています。ただ、オニオンアーキテクチャーではよりMVCの実装に近い形へと見え方が変わります。
MVCに必要な要素が組み込まれました。この形は一般的なMVCに非常に近く想像しやすいですよね。
MVCはご存知の通り、Model View Controllerの3つで成り立ちますが、オニオンアーキテクチャーを取り入れると、MVCに加え「Service」という概念が入ります。
ServiceはModelとControllerの中間に位置し、レイヤー間の依存を明確にします。
この考え方は非常に有効で、マイクロサービスにおいても実践的で役に立ちます。
DDDとマイクロサービス
実際マイクロサービスをやるとなった場合、DDDは必要なのでしょうか?結論を急ぐことは出来ませんが、現時点ではどちらとも言えないという状況でしょう。
マイクロサービス=DDDというのはかなり乱暴です。マイクロサービスの考え方にはアプリケーションだけでなく、インフラや新しい領域であるサーバーレスコンピューティングも深く関わってくるからです。
話の本題はアーキテクチャーであるので、マイクロサービスを実践する上で必要なDDD的要素はどこなのか、これを簡単に紐解いてみます。
ドメイン分析
ヘキサゴナルアーキテクチャーを代表としたDDD関連アーキテクチャーはDomainという概念を入れてアプリケーションの独立性を可視化します。
しかしその独立性というものは一言で言ったもののなかなか難しいのが現実です。そこで、まずはDomain=DBと考えてDBとアプリケーションの結合度合いを確認します。
概念的な図で構わないので、簡単に書き表すと良いです。
ユースケース
本来はユースケース駆動設計は別物なのですが、ユースケースを1つのDomain Serviceとして考えるのもありかもしれません。これはクリーンアーキテクチャーに詳しく書かれていますがユースケース単位でのドメイン分割という考えは非常にわかりやすいです。もしくはドメイン分析の結果、必要なユースケースから分割していくといったアプローチもありかもしれません。
気をつけなくてはいけないのは、マイクロサービス化を前提としたユースケース駆動の場合、ユースケースが細かくなりがちです。その結果膨大な量のマイクロサービスを開発することになりコストが増大します。
クラウドネイティブ指向のアプリケーションアーキテクチャーとは
ようやく本題にたどり着きました。クラウドネイティブとマイクロサービスの関連性については言うまでもなく非常に密接です。マイクロサービスアーキテクチャーの実践がクラウドネイティブそのものです。
アプリケーションアーキテクチャーだけでなく、プラットフォーム(インフラ?)がマイクロサービスの大半をカバーしていたりします。
それが本質でマイクロサービスとはアプリケーションとプラットフォームの見事な融合になります。
- DDDによるアプリケーション設計
- コンテナを中心としたクラウドネイティブの実装
- パイプラインはサーバーレスコンピューティング
- SREの実践
まさにこれらがオーケストラのように複合しあいシステムが出来上がっていきます。
最後になりましたが、Alternative Architecture DOJOを通じて今回のようななかなか踏み込みづらいものも意訳を多く含みますがわかりやすく発信していきます。
今回は概念のまとめでしたが、実際の設計、実装、そして私たちでもわからないような技術の実験など情報発信していきますので引き続きよろしくお願い致します。