ドメイン駆動設計を用いてマイクロサービスに分割することを考える

# はじめに

最近は、ビジネス環境の変化に迅速に対応するために、デジタルトランスフォーメーション（以下、DX）の取り組みが各企業で行われています。それに伴い、クラウドネイティブ環境でアプリケーション開発のアジリティを向上させるマイクロサービスアーキテクチャへの関心も高まっています。[@takahashisansan](https://qiita.com/takahashisansan)の記事「[マイクロサービスが開発・運用コストの削減にどう貢献するか考えてみた件](https://qiita.com/takahashisansan/items/7470a14e45aee2b6739f)」では、開発・運用コストへの影響について整理されています。また、[@atsuo0o](https://qiita.com/atsuo0o)の記事「[デジタルトランスフォーメーションにおけるシステムの俊敏性とは？を考える](https://qiita.com/atsuo0o/items/979257bc39bbe8cc20a6#_reference-d8be764e8e6366733d09)」では、DXにおける課題や進め方が整理されています。それらの内容を踏まえた上で、一歩踏み込んで、マイクロサービス化で直面するサービスの分割について考えてみます。

# マイクロサービスが注目される理由

ます、サービスの分割に入る前に、マイクロサービスが注目される理由を簡単に整理しておきます。これまでの情報システムは、お客様の事業を支えるために、IT化やオペレーションの自動化により業務を効率化することが主な役割でした。
昨今、様々な産業において、新たなデジタル技術を駆使して既存のビジネスを脅かすデジタルネイティブ企業が台頭しています。今や、お客様のビジネス環境は、同業他社との競争のみならず新興企業や異業種からの参入に対抗すべく、新たな事業を創出し続けなければならないほど劇的に変化しています。

そのような中で、これからの情報システムは、従来の役割に加えてお客様のビジネス変革に応じて柔軟に対応できることが求められています。

では、ビジネス変革に応じて柔軟に対応できる情報システムはどのようなものでしょうか。

例えば、市場変化に合わせて新たなシステム機能を素早く組み込むことができる、利用者が想定を超え急激に増えても迅速に対応できる、などが考えられます。
しかし、残念ながら現在の情報システムは、一部の修正が全体に影響してしまう機能構造、データ構造であり、変化に迅速に対応するには一筋縄ではいきません。

* 類似機能をひな形として再利用したり、機能追加を繰り返すことでシステムが複雑化して、影響調査など、改修に多くの時間を費やす
* 機能やデータが互いに関連していることで、部分的な障害がシステム全体に影響を及ぼす
* アプリケーションを構成するソフトウエアコンポーネント同士が密接に結びついているので、新たな開発言語やデータストアなどの導入が困難
* あからじめ計画された取引量の上限が設定されていることで、予測を超えるような想定外の負荷には即座に対応できない

このような情報システムの課題を解決する手法のひとつとして、マイクロサービスアーキテクチャが注目されています。

# マイクロサービスアーキテクチャとサービスの分割

マイクロサービスアーキテクチャは、機能（プロセス）やデータを独立配置可能な単位（サービス）に分割する考え方です。
機能とデータをサービスという単位で独立させることでサービス間の依存関係を低減し、サービス単位で機能拡充やスケーリング、あるいは保守（是正、予防など）などが容易になります。このように、マイクロサービスアーキテクチャを適用することで現在の情報システムの課題が解決できそうです。それでは、どのような単位でサービスを分割すればよいのでしょう。

そもそも、企業は、経営戦略に基づいて機能別組織を構成します。それぞれの組織は経営戦略上の機能を担って業務を遂行しています。そして、情報システムは、ITを導入し自動化することで組織が担っている機能をシステム機能によって補います。

あるビジネス課題を解決したい時に、各組織は経営戦略に基づいて業務目標や施策を設定します。どのように施策を実行していくかは、組織によって実施する内容やタイミング、完了時期は異なります。それらの業務を情報システムで実現するのも同様です。現実世界では、組織ごとに独立してシステム化を進めることができれば、ビジネス課題を解決するのに効果的なのです。

このように、業務目標や施策で境界づけられた組織に着目すれば、情報システムの機能やデータをサービス単位に分割することができます。このような考え方に基づいた方法論があります。それが、ドメイン駆動設計（Domain-driven design, DDD）です。

# ドメイン駆動設計（DDD）とは

ドメイン駆動設計（Domain-driven design, DDD）は、2003年にEric Evansが提唱したソフトウェア開発手法です。

ドメインとは、ソフトウェアを導入してシステム化する対象の業務です。[Domain-Driven Design Quickly 日本語版](https://www.infoq.com/jp/minibooks/domain-driven-design-quickly/) に出てくる「航空監視業務（管制業務）」や、身近なところでは「銀行業務」などがこれにあたります。システム化する対象によっては、銀行業務であれば、「預金業務」、「融資業務」、「為替業務」、「金融商品の販売業務」など、組織ごとにさらに細分化することができるでしょう。ドメイン駆動設計では、ソフトウェアで現実世界の作業を自動化したり、ビジネス上の問題を解決するためには、ソフトウェアを導入してシステム化する対象の業務（ドメイン）を深く理解し、ソフトウェアを開発しなければならないとしています。では、これまでのやりかたと何が違うのでしょうか。

# なぜDDDなのか

これまでは、ソフトウェアを開発するとき、お客様の業務部門など、ドメインの専門家（ドメインエキスパート）が要求仕様を書き起こし、アナリストやアーキテクトが要求をもとに分析モデルを作成し、開発者が設計、コーディングする形態でした。

このようなやり方では、対象の業務そのものを深く理解できていない開発者は、モデルの全体像やオブジェクト同士の関連や振る舞いを詳細に把握できていません。仮にモデルをコードで正確に表現できない場合に、開発者は、モデルに着想を得て独自の要素を加えてしまいます。結果的に業務のモデルと違った不適切な機能をもつソフトウェアになってしまいます。

ドメイン駆動設計では、業務を熟知しているドメインの専門家（ドメインエキスパート）とソフトウェアの専門家（アーキテクトや開発者）が一緒に業務のモデル（ドメインモデル）を作成します。そして、ドメインモデルをコードに変換しながら、ドメインモデルとコードを相互にブラッシュアップしていきます。そうすることで、ドメインの専門家とソフトウェアの専門家の乖離をなくすことができます。

このように、ドメイン駆動設計の手法を用いることで、組織は経営戦略に基づいた業務目標や施策に沿った情報システムのサービスを実現できます。

では、どのようなプロセスで実施すればいいのか見ていきましょう。

# DDDの概念について

まずは、DDDの概念をおさえておきましょう。ここで紹介するのは、DDDの概念からドメインを分割しマイクロサービスに適用するイメージです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540574/42086eea-89ac-38e9-3091-c8904ed13d2e.png" title="contet-map" width="750">

## DDDの用語

### ドメイン
組織が行う事業やそれを取り巻く世界のこと。良いシステム開発を⾏うためには、この世界をチームのメンバが深く理解する必要があります。チームメンバとはシステムの利用者、業務の専門家、設計者、プログラマなどのシステム開発に携わる関係者のことをさします。ドメインのすべての仕組みを理解するには、あまりにも⼤きく複雑すぎるため、通常はコアドメイン、サブドメインという適切な⼤きさに分割します。コアドメインやサブドメインをドメインと呼ぶこともあり、この場合、アプリケーションの中心となる業務領域を意味します。
#### コアドメイン
ドメインにおいて、事業的に最も重要で戦略的に不可⽋な部分です。コアドメインの開発には、優秀なメンバーを参加させ、積極的に成⻑させビジネス的な差別化を図ります。コアドメイン・サブドメインの分類は恒久的なものではなく、内外のビジネス環境変化に応じて変化します。
#### サブドメイン
ドメインにおいてコアドメインではない補助的な部分だが、コアドメインにとって必要な部分になります。サブドメインはさらに支援サブドメインと汎用サブドメインに分けることができます。
##### 支援サブドメイン
コアドメインほど重要ではないものの業務的に特別なドメインです。コアドメインの⽀援を⾏う独⾃機能などが該当します。
##### 汎用サブドメイン
業務的に特別ではないが、今回のシステムにおいて必要な部分です。認証機能などが該当します。
### 問題空間
ドメインの一部であり、解決すべきビジネス戦略上の課題を浮き彫りにするための空間です。問題空間はコアドメインとそこから使う必要のあるサブドメインを包含しています。
### 解決空間
問題空間に対して、その課題を解決するためにソフトウェアをどのように実装するかを検討する空間です。問題空間で抽出した課題に対して、システム化による問題解決を図ります。
### コンテキスト
単語や文章が現れる状況で、その意味を定義するものです。例えば、アカウントという単語が、銀行取引という状況で現れたら、それは口座、すなわち、ある種の論理的な現金の器を意味します。一方、ウェブアプリケーションという状況で現れたら、認証やユーザ証明に関するものを意味します。
#### 境界づけられたコンテキスト
DDDの中でユビキタス言語と並んで重要な概念です。DDDの適用には、境界づけられたコンテキストの抽出が重要となります。境界づけられたコンテキストとは、ドメインにおいて、ユビキタス⾔語の意味が変わる境界で、作ろうとしているドメインモデルの明示的な境界となります。1つの境界づけられたコンテキストは複数チームではなく、1つのチームだけで開発を担当します。DDDでは、1つのコアドメイン（もしくはサブドメイン）に、1つの境界づけられたコンテキストが対応している状態が良いとされています。現実のレガシーシステムでは、複数のドメインに対して1つの境界づけられたコンテキストしか存在しないケースが多々あります。

## DDDで用いられるドキュメント

### ユビキタス言語
DDDの中でも特に重要な概念です。ドメインエキスパートや開発者を含めたチーム全体で作り上げる共有⾔語で、DSL（ドメイン固有⾔語）の⼀種です。普段のチーム内での会話や、ドキュメント、プログラムなどの成果物でユビキタス（遍在的）に使用されます。ユビキタスといっても、業界全体や全社で統一的に利用されるという意味ではなく、個別の境界づけられたコンテキストの開発プロジェクトで作業するチーム内に限定して使用されます。同じ言葉でも、境界づけられたコンテキストごとに違うニュアンスと振る舞いを持つため、境界づけられたコンテキストごとにそれぞれのユビキタス言語が存在します。
### コンテキストマップ
コンテキストマップとは、複数の境界づけられたコンテキスト間の関係を俯瞰する地図です。これを利用してシステムの全体像や相互関係を把握することができます。コンテキストマップを描くことによって、境界づけられたコンテキストを担当するチームは、他の境界づけられたコンテキストを担当するチームとの関係を把握でき、他チームとのコミュケーションの必要性を判断できるようになります。コンテキストマップはToBe像ではなく、AsIsの図として記述します。そして機能を追加するたびにコンテキストマップを更新します。境界づけられたコンテキスト間の関係として、以下の2種類を表現できます。 <br> 　・組織パターン：チーム間の関係を⽰す <br> 　・統合パターン：データとプログラムの連携⽅法を⽰す <br> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540574/c6a09e3e-5157-0f74-d536-ac27884c75e1.png" title="contet-map" width="500"> <br> 上図の例では、組織パターンのひとつで上流・下流の関係を表現しています。図中の”U”が上流（Upstream）、”D”が下流（Downstream）を表しています。モデルの変更が他のモデルに影響を与える場合、影響を与える側が「上流」、影響を受ける側が「下流」となります。
### ロバストネス図
ロバストネス図とは、要求モデルであるドメインモデル、ユースケース記述、ユースケース図などをロバスト（堅牢、強靭）するロバストネス分析のアウトプットで、システムのユースケース記述をもとに、「バウンダリ」「エンティティ」「コントローラー」の三つに分けて表します。ロバストネス図を作成することで、要求モデル（ドメインモデルやユースケース記述、ユースケース図）の不足、疑問点、曖昧な個所を抽出し、改善することができます。

# DDDを用いてマイクロサービスを分割するプロセスを考えてみる

これは、システム化の対象となるドメインから段階的に詳細化することよって、最終的にマイクロサービスに分割することを表しています。ここでは、プロセスを一連の流れで表現していますが、DDDでは、前のプロセスに遡ってリファクタリングを繰り返しながら、ドメインモデルやユビキタス言語を洗練させていくことが重要とされています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540574/6019f08e-7a19-5a98-8438-9941e949ce9c.png" title="contet-map" width="750">


## ドメインの定義

まずは、ドメインを構成要素であるサブドメインに分割し、ユビキタス言語の核となる業務用語を抽出するために、既存業務のモデル図や、ドメインの業務を熟知した業務部門の担当者などのドメインエキスパートへのヒアリングなどを通じて、ドメインを構成する業務を抽出します。業務を抽出する際は、上流・下流などの業務間の関連や、業務の階層構造に注目すると良いでしょう。これらは、コンテキストマップで、サブドメイン間の関係を定義する際に利用できます。

次に、ドメイン内の業務で使用する用語を抽出します。用語は既存システムに関する様々な文書（業務モデル図、設計書、報告書など）やメンバの日常的な会話、ドメインエキスパートへのヒアリング等をつうじて用語を抽出します。用語の意味だけでなく、用語が使用される状況や用語の使われ方も同時に整理するのがポイントです。特に同じ用語でも使用される状況によって定義が異なるケースに注目します。後のステップでドメインを境界づけられたコンテキストに分割するための情報として利用するためです。なお、用語の定義は本節で完結するわけではなく、以降のステップを通じて充実化させていきます。

そして、整理した情報をもとに、人材や予算などのリソースを重点的に投下すべき業務領域であるコアドメインを識別するために、ドメインをコアドメインやサブドメインに分割していきます。

最初に抽出した業務を階層構造が分かるように可視化し、コアドメインとそれ以外に分類します。事業的に重要で戦略的に不可欠な価値の高い業務をコアドメインとします。例えば、販売業務のシステム化の目的が販売チャネルの多様化であれば、販売チャネルに紐づく業務をコアドメインとします。また、それに伴う、受注・請求・決済などの一連の業務もコアドメインとします。一方、コアドメインに付随して必要となる業務は、支援サブドメインとします。なお、ビジネス上の関心事ではないけれども、認証・認可など、システムを機能させるために必要な機能は、汎用サブドメインとします。

## サブドメインの定義

ドメイン全体をコアドメインやサブドメインの単位に分割した後、それぞれの構造を明確にし関係者が業務をより深く理解するために、業務の流れを表すユースケース図や、業務で扱う情報を表すモデル図などを使って詳細に定義していきます。なお、コアドメインやサブドメインごとにマイクロサービスの候補となり得ることが考えられますので、それぞれ考慮すべき情報（目的、課題、非機能要件など）を一覧などで整理しておくと良いでしょう。

## 境界づけられたコンテキストの定義

「境界づけられたコンテキスト」とは、明示的な境界であり、ドメインモデル(*1)がどこに属するのかを表すものですので、各ドメインモデルの内部的な概念やプロパティ、操作がそれぞれ特別な意味をもちます。そのために、それらをユビキタス言語によって適切に分割していきます。[こちらの記事](https://little-hands.hatenablog.com/entry/2017/11/28/bouded-context-concept)でも解説されているように、異なる２つのドメインモデルが、同一名の用語を違う意味で使っている場合があります。例えば、同じ「商品」でも、販売業務と在庫管理業務では、売値や配送先など関心事が異なります。このように、ユビキタス言語の意味が変わる境界で「境界づけられたコンテキスト」を分割し定義していきます。コンテキストが曖昧な場合は、ロバストネス分析によってロバストネス図を作成しユースケースの曖昧さをなくしていきます。このようにして分割した「境界づけられたコンテキスト」のドメインモデル、そのものがマイクロサービスの候補となります。


　*1：ドメインモデルは、ユビキタス言語をソフトウェアモデルとして表したものです。

＜参考＞実践ドメイン駆動設計　Vaughn Vernon 著

> ドメインは、問題空間と解決空間を持っている。問題空間は、解決すべきビジネス戦略上の課題を浮き彫りにするもので、もう一方の解決空間は、ソフトウェアをどのように実装してその課題を解決するかに着目するものだ。（中略）解決空間は、境界づけられたコンテキストのことで、特定のソフトウェアモデルの集合となる。なぜなら、境界づけられたコンテキストは特定のソリューションを表すものであり、それを具現化したビューであるからだ。境界づけられたコンテキストを用いて、何らかのソリューションをソフトウェアとして具現化する。


境界づけられたコンテキストの定義を終えたら、ステークホルダーで共有し、理解できるようにするために、複数の境界づけられたコンテキストとそれらの関係性をコンテキストマップに定義します。コンテキストマップを定義することにより、コンテキスト間での関連性、連携の内容と種別が明確になり、現在の状況の把握を行うことができます。境界づけられたコンテキスト間の関係性については、大きく[９つのパターン](https://codezine.jp/article/detail/9837)に分類されます。

## マイクロサービスの定義

境界づけられたコンテキストの定義によって、分割された複数のマイクロサービスの候補を得ることができました。ここからは、境界づけられたコンテキストとマイクロサービスを対応づけし、機能要件、非機能要件を考慮して、サービスを分割する、あるいは、サービスを統合するなど、サービスの単位を見直して、最終的にマイクロサービスの適用範囲を決定していきます。例えば、今後は決済手段が増えていくので、受注と決済を分割してそれぞれマイクロサービス化する、あるいは、改修頻度が少ないバックエンドのドメインモデル群を既存システムに統合してAPIで連携するなどが考えられます。


# さいごに

ドメイン駆動設計を用いてマイクロサービスに分割する方法について考察してみました。いかがでしたでしょうか。この記事ではマイクロサービスの分割に着目して考えてみましたが、ドメイン駆動設計を端的にいうと、アプリケーション開発者が、ビジネスの活動や業務内容を深く理解して、実世界とシステムの橋渡しをする役割を求められているように感じます。 

近年、DockerやKubernetesなどのコンテナ技術の進化により、オンプレミスやクラウドが混在するハイブリッドクラウドの時代となり、クラウドネイティブ環境のシームレス化が浸透してきています。オンプレミスやクラウドの境界を意識することなく、アプリケーションを開発しデプロイできる環境が整いつつあります。一方で、DXに向けてレガシーシステムをいかに適切に分割し、いかに適切なインフラ環境に配備すればよいかという課題があります。

ドメイン駆動設計では、企業の組織機能や業務特性に合わせて適切なドメインに分割することができます。分割したドメインの非機能特性を踏まえて、例えばSoR/SoE/SoIなど、領域ごとに分類することで、適切なインフラ環境にアプリケーションを実装、配備することができるのではないでしょうか。ドメイン駆動設計によるサービスの分割は、DXに向けての課題を解決するための一つの方法なのかもしれません。

※掲載内容は私個人の見解であり、所属する組織の公式見解ではありません。

# 参考文献・参考記事
[エリック・エヴァンスのドメイン駆動設計 | 翔泳社](https://www.shoeisha.co.jp/book/detail/9784798121963) 
[実践ドメイン駆動設計 | 翔泳社](https://www.shoeisha.co.jp/book/detail/9784798131610) 
[Domain Driven Design（ドメイン駆動設計） Quickly 日本語版 | InfoQ](https://www.infoq.com/jp/minibooks/domain-driven-design-quickly/) 
[IDDD本から理解するドメイン駆動設計 第2回 | CodeZine](https://codezine.jp/article/detail/9744) 
[IDDD本から理解するドメイン駆動設計 第3回 | CodeZine](https://codezine.jp/article/detail/9837) 
[DDDのドメイン・サブドメイン・ユビキタス言語・境界づけられたコンテキストを整理する | Qiita](https://qiita.com/crossroad0201/items/875c5f76ed3794ed56c4) 
[境界づけられたコンテキスト 概念編 - ドメイン駆動設計用語解説 [DDD] | Hatena Blog](https://little-hands.hatenablog.com/entry/2017/11/28/bouded-context-concept) 
[マイクロサービスのサービス分割時において、ロバストネス分析が有効なのかを考える | Qiita](https://qiita.com/a_nishiyama/items/c9300d678e1cbe574fe5)