マイクロサービスの適切な粒度の１つの観点からの考察

# 背景
UAFにあるサービスビューをプロジェクト中にあまり使用していなかった。
というのも、サービスビューについての参考文献も探した限りではほぼなく、
来日したUAFに詳しい方J氏の説明内容を聞いてもイマイチぴんと来なかったからである。
J氏は
「サービスてのはユースケース、UAFでいうとリソースビューのFunctionを抽象化したものだよ」みたいなことを言ってたけど、
これだけでは「？？？」て感じです。

そこで実際に自分なりに「多分こうなんじゃないか」という仮説を立てて
実際に使ってみた結果しっくりとくるものを感じたので、その仮説内容について記載する。
その結果、システムのサービスアーキテクチャの手助けになることが分かった。
そもそもアプリサイドでサービスがどの粒度であるのか？
などの考察は仮説考察程度になり困難を極めるため、
ビジネスサイドで「この単位で１つのサービス」と明確に分かるようにしておくべきである。
その責務をこのビューで行うと考えた上での仮説考察である。

## 注意
あくまでもビジネスサイドでの１つのサービスのメンテ性という観点からのみの考察である。
他の拡張性やセキュリティ・耐障害性といった観点からの考察も込みで分離した方がいいとなった場合に
分離を快く決断すべきである。
今回はあくまでもサービスの凝集度といった観点からのみの極端な粒度のみの考察にしておく。

※UAFでいうResourceビューの動的な要素Functionは、システムのユースケースの単位そのものであるとする。


<img width="600" alt="uaf_grid (2).png (422.9 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/26/135213/c2c92e83-9431-4d76-a5aa-9feabcf7df3f.png">

# サービスについての定義
まずServiceという用語の定義を確認する。
これはコンピューターシステムだろうが、人がやることであろうがユーザーが認識できる単位での機能である。
つまり、そのサービスの裏にどのようなリソース、人なのか機械なのか？
といったことは隠ぺいした状態で、
しかもそれらがどのようなユースケースの連携によって構成されてるか？
まですべて隠ぺいして外部のユーザーから観測できる単位のものにした単位である。
よって、サービスを１段階詳細化すると、各リソースに割り当てられるユースケースが見える。

## 例
上記だけではわかりにくいため、以下のような具体例を記載する。
<img width="600" alt="スクリーンショット (96).png (105.1 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/26/135213/5ea5134b-5f42-449b-8ed3-272f3262df91.png">
図のaやbはコンピューターシステムとする。
こんな上図のようなエンドユーザーが受けられるサービスは、
・ユーザー自身の行うユースケース
・ユーザーが支援サービスとして使用するコンピューターシステムのユースケース
の２つの組み合わせからなりますよ～てことです。
この時、エンドユーザーからはこの緑枠で囲まれた中身が、
どんなユースケースの組み合わせからなってるかなんてわからなくていいですよね？

このような感じで複数のユースケースを小さい粒度の目的とみたら、
サービスというのは、それらを束ねた大きい粒度の目的ってことになります。
だから抽象化してることになるので、J氏のセリフにも矛盾しませんし、違和感もありません。

同様に今度は、ユーザー視点でのサービスの粒度を確認するために、
緑枠で囲まれた範囲に限定して考えてみましょう。
この粒度の世界では、エンドユーザーは登場しません。
<img width="500" alt="スクリーンショッ (96).png (26.0 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/26/135213/f7000e1e-f4be-4032-a446-17749ac18283.png">

UMLのユースケース図で上図を描くと以下のようになります。
<img width="500" alt="スクリーンショット (97).png (60.2 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/26/135213/e5a03418-9a52-4c1b-8dd4-e0594186ce28.png">
ここでユーザー視点でのサービスとはどの粒度になるでしょうか？
ユーザーさんからすると裏に外部システムbがあるってことなどの詳細は視えなくていいです。
なので、ユーザーさんは２つのサービスを支援サービスとして使えることになります。
１つ目のサービスは、ユースケース①と外部システムbの連携により使えるサービス。
２つ目のサービスは、ユースケース②そのもの。

# このServicesビューで行いたいこと(推測)
このビューにおいてSoSレベルのサービスの粒度を明らかにしておくことにより、
後の工程でのモノリスにすべきなのか？
「本来はこの単位でマイクロサービスにしたいけど、後から分離しなきゃよかったとなるリスクを考えて、
マイクロサービスではなく、この単位でモジュラーモノリスにしておこう」
といった具合にサービスアーキテクチャの検討がしやすくなると考えられる。
マイクロサービスの基本思想は、言い換えるならば【サービスのカプセル化】である。
そこでいくつかの簡単なモデルの例を通してその考察を行う。

さらにそのどのように分割するか？を考察後に、どうリソースに割り当てるのか？
をResourceビューで考えられる手助けになるビューであると考えた。
これについては後述で記載する。

## 注意
以下の考察ではServicesビューでリソースレベルの詳細内容が見えてしまっていることに
若干違和感を覚えられるかもしれないが、考察がしやすいようにしただけである。
また、データ＝UAFでいうResourceレベルのInformationとして扱うことにする。

また、以下の図ではユースケースが直接データを参照しているように描いているが、
これはそのユースケースが最終的にどのデータを必要としているのか？　
という意図が伝わればいいと思って省略表記しただけで、決してバウンダリオブジェクトなどから直接参照するなどといった意味ではないことに注意してほしい。

## 例①　よい分離の仕方(発想はカプセル化高凝集より)
<img width="500" alt="サービス.png (27.6 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/9bc1a853-73e3-4acd-a0ad-fd5611c339ee.png">

図のようにデータS、T、U、Vがあったとして、
そのデータをユースケースがそれぞれ図のように参照する場合を想定する。
サービス①で実行される順番は、ユースケースA→ユースケースC
サービス②で実行される順番は、ユースケースB→ユースケースC　と仮定する。

このとき【関係のないものは混ぜない】というオブジェクト指向のカプセル化の考え方に基づくと、
以下のように境界を置いてサービスを分離して考えたくなる。
<img width="500" alt="分割方法.png (19.7 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/ab73db78-a229-4898-b92f-1e9d662fcaab.png">


そしてこのサービスXやサービスYなどの粒度のサービスが、Resourceレベルのサービス、
UAFの用語で言うとResource Serviceといえると考えた。
そこでこのあとどのようにシステムに情報やユースケースを割り当てるのか？
いくつか分類して考える。
### リソースへの割り当て
ここでユースケースCが今後、データS、T、Uを参照することがないという保証があれば、
マイクロサービスとして、サービスXとYを完全に分離し、
さらにはサービスXを　システムXというリソースに、
サービスYを　システムYというリソースに配置するという手法を取るであろう。
ここの考察はResourceビューですればいいことなので後述で記載する。

## 例②　悪い分離方法
①と同じ例で悪いサービス分割のパターンをいくつか列挙する。
まず、無関係なサービスまで一緒になってしまっている下図のようなケースだ。
今後、【ユースケースCがデータS、T、Uを使用することが見込まれるから、あえて一緒にしている】とかならその限りではないが、
無頓着に何も考えずに図のようにすべてを一緒にしているのは、低凝集なモノリシックアーキテクチャになってしまう。
せめてまとめるのならば、データV+ユースケースCのまとまりを他と疎結合になるように
モジュラーモノリスな設計にしておくべきである。
<img width="500" alt="モノリシック.png (18.5 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/3b59e281-b93c-4dee-9ebc-f24d292a47aa.png">


## 例③　悪い分離方法
他にも下図のように参照したい情報とユースケースが分割されてしまってるケース。
これは問答無用にアンチパターンである。
サービスaとサービスbがともに低凝集で密結合になってしまっている。
カプセル化の思想に全く則っていないので、このような設計にしてしまっている場合は
速やかにサービスaとサービスbをまとめる施策が必要である。
<img width="500" alt="アンチパターン.png (20.2 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/fc86d786-e1f0-40f7-89f4-7aa30f55dd12.png">


# リソースへの割り当て
再度先程の例の図を通して考察する。
置かれている前提は以下である。
サービス①で実行される順番は、ユースケースA→ユースケースC  
サービス②で実行される順番は、ユースケースB→ユースケースC

<img width="500" alt="割り当て.png (31.4 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/65b6bb8b-394f-45cc-93e0-251686575e25.png">

これをどのようにリソースに割り当てるのかは複数の分類がある。以下でその考察をする。

## マイクロサービスアーキテクチャで１つのリソース
<img width="500" alt="マイクロサービス.png (26.7 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/a4bc5361-8f62-449b-afee-befce1e8a8ee.png">

アプリをサービスXとYのマイクロサービスに分割して、それを１つのシステムへ担わせる手法。

## マイクロサービスアーキテクチャで複数のリソース
<img width="500" alt="マイクロサービス１.png (26.0 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/00b5cd54-f029-4733-b8ea-80301ee1aed4.png">

これをユースケース図に起こすと以下になる。
<img width="450" alt="ユースケース図0_1.png (19.4 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/5a72d088-02ea-484a-8fe5-e23bc3b25e30.png">

この方法だと、先程の１つのシステムで実現する方法に比べて、
仮にどちらかのシステムが落ちてしまってももう片方のサービスは受けられることになる。
またここまでの考察から、SoSとマイクロサービスかどうかは全く別概念ということも証明できた。

## モジュラーモノリス
<img width="500" alt="モジュラモノリス.png (21.4 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/04/27/135213/ea7b4035-c057-4993-814e-b29f504ffb39.png">

サービスとして分割はしないけども、いつでもマイクロサービスに分割できるように
図の赤点線で境界を引いて疎結合になるように設計しておく。
こうすることで仮に今後ユースケースCがデータS、T、Uのいずれかを必要とする
と仕様が変更された場合でも、上記のマイクロサービスに分割してしまった場合に比べて
容易にまとめることが可能となる。

# まとめ
マイクロサービスの適切な粒度について考察してきました。
オブジェクト指向のカプセル化について、それなりに理解が深い方なら思想はすんなり入りやすいかと思います。
要は、サービスとして、関連性の高いものをまとめて、そのサービスに無関係なものは混ぜないってことです。サービスとしての高凝集・疎結合を狙ってるとも言えますね。