マイクロサービスアーキテクチャでデスクトップアプリを作ってみた知見と感想

#はじめに
MicroServicesを意識してGoogleカレンダー風な何かを作成して得られた知見を投稿しようかと思います。

#主な環境
+ VSCode
+ .NET Core
+ C#, F#, WPF, ASP.NET Core
+ [MagicOnion](https://github.com/Cysharp/MagicOnion)
+ [ConsoleAppFramework](https://github.com/Cysharp/ConsoleAppFramework)
+ [ProcessX](https://github.com/Cysharp/ProcessX)


#成果物
[CalendarAppForMicroservicesLearning](https://github.com/kwhrkzk/CalendarAppForMicroservicesLearning)

#概要
[2020年にWebフロントエンドを勉強する人が作るべきたったひとつのアプリ](https://qiita.com/Dragon-taro/items/03f322dee15b19c33613)
にてGoogleカレンダーが教材として良さげということだったので検討してみました。
参考にしたところはカレンダーの予定の中にToDoリストのタスクを混ぜ込んで表示できる機能です。
画面的には
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/4eeceafa-88bf-f4e6-fddd-2653607cecef.png)

こんな感じで2カラムで右はTODOリスト。左はカレンダー表示で、予定と終わったTODOがまぜこぜに表示するような感じで考えました。

#マイクロサービスの機能分け
TODOを取り扱う機能(TODOサービス)とカレンダーを取り扱う機能(カレンダーサービス)のふたつが必要だと考えました。
カレンダー表示の際にTODOの内容を知っていないといけないので、カレンダーサービスはTODOサービスを知っていないといけないのかなと思い、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/8f083d77-cef0-c5b5-0b27-a6acad5e72f9.png)
と想像したのですが、マイクロサービス同士が依存するのは良くないと思いとりあえずお互いに関与しない方向で検討しました。(後述しますが[BFF][]という考え方でなんとかなりました)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/758313b0-d850-11dc-1b9a-e2c6ff028bfb.png)

#フロントエンド
マイクロサービスで構築した際に利点になるのはフロントエンドを選ばないところだと思ったので、デスクトップアプリとWebアプリを用意してみました。このほかにはスマホアプリとかコンソールアプリとかありそうな気はしてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/7b34734a-9ab2-c645-cd45-2a64bb58325b.png)

#マイクロサービスとフロントエンドの関係
何も考えずに想像したら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/d4a201a8-5570-9dec-a662-c9ab942e5781.png)
となってしまい、N対Nになってつらいなあと思っていたら
[マイクロサービスアーキテクチャにおけるAPIコールの仕方とHTMLレンダリング][]
の記事が参考になりました。どうやらあいだにAPIGateWayとかBFF（Backends For Frontends）を用意すればすっきりするそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/b4e8a5fa-35ab-de71-16b3-2a4143be289a.png)
こうすればフロントエンドはBFFに、TODOとカレンダーを混ぜ込んだ一覧をください、とお願いすればマイクロサービスを気にすることなく情報を手に入れられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/38f8fc8d-f2a7-a87a-d7a6-96993fd98222.png)
こんな感じでひとつのAPIGawaWayで全部こなすようになるとAPIGateWayが大変なことになるそうなのでフロントエンドのアプリ一つに専用のBFFを用意してあげたほうが良いそうです。

#マイクロサービスのエントリーポイント
マイクロサービスのエントリーポイントってみなさん何を想像しますでしょうか。
私はマイクロサービスとやりとりをするための方法としては、マイクロサービスがWebサーバ立ててhttpclientで通信する、しか想像できていなかったんですが実際に作ってみるといろいろできました。
とりあえず今回用意してみたのはコンソールアプリとgRPCです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/19aff44f-ed14-face-622b-b72879002f0e.png)
例えば特にスケールとかを気にしない状況で、デスクトップアプリみたいに同一資源上にいるのであれば、マイクロサービスをコンソールアプリ化して、使用する側はプロセス実行を行い、実行結果をjsonとかで標準出力でもらえばやりとりできます。
また、gRPCを用意すればメソッドを非同期で呼び出すような感覚でマイクロサービスやBFFとやりとりできます。

#全体構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/69915f6c-7ba1-5ca7-72c1-f0fec9d6f0a8.png)

フロントエンドのアプリ一つに専用のBFFを用意したほうが良いといっておきながら今回はエントリーポイントの分け方で作ってしまいました。
実業務では通信手段としてWeb(Http)、gRPC、コンソールetcなどからひとつ選ぶはずです。

#結果
WPF
ちょうど良いライブラリがなくお手製でくそみたいなUIで申し訳ないのですが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/f55df384-7ed1-8962-1b0f-9af07dcecae3.png)

Webアプリ
[FullCalendar](https://fullcalendar.io/)と[List.js](https://listjs.com/)を使わせていただきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/6ad0300a-78fa-4e63-2467-3e5344206e54.png)


#作ってみた感想とまとめ

+ デスクトップアプリでもマイクロサービス風に組めた(良い悪いはわからない)
+ 最初にマイクロサービスの分割を間違えるとつらい(と思う)
+ [MagicOnion](https://github.com/Cysharp/MagicOnion)が便利すぎる
+ [ConsoleAppFramework](https://github.com/Cysharp/ConsoleAppFramework)と[ProcessX](https://github.com/Cysharp/ProcessX)の連携も素晴らしい
+ POCO(Plain Old CLR Object)作るのがちょっと面倒(DDD的集約 <-> POCO <--> json で変換している)
+ [C#大統一理論](https://www.slideshare.net/UnityTechnologiesJapan/unite-2017-tokyocunirx)まであと少し(domainの再定義しなくて良いのは嬉しい。後はWebフロントエンドさえ何とかなれば。。)
+ フロントエンドは画面の表現に集中できる


#参考
+ [BFF（Backends For Frontends）超入門――Netflix、Twitter、リクルートテクノロジーズが採用する理由][BFF]
+ [Micro Frontends](https://martinfowler.com/articles/micro-frontends.html)
+ [[翻訳記事]マイクロフロントエンド](https://micro-frontends-japanese.org/)
+ [Microservices design patterns for CTOs: API Gateway, Backend for Frontend and more](https://tsh.io/blog/design-patterns-in-microservices-api-gateway-bff-and-more/)
+ [マイクロサービスアーキテクチャにおけるAPIコールの仕方とHTMLレンダリング][]

[BFF]:https://www.atmarkit.co.jp/ait/articles/1803/12/news012.html
[マイクロサービスアーキテクチャにおけるAPIコールの仕方とHTMLレンダリング]:https://qiita.com/kawasima/items/356d54e253c54d730fb0