この記事はMicroservices Advent Calendarの16日目の記事です。前回は@yasuabe2613さんのマイクロサービスのパターンの話でした。
はじめに
マイクロサービス・アーキテクチャの話は多くありますが、実際にマイクロサービスを新たに設計・開発するとき、どのような手順を踏むか、と言ったことを扱った文献はそれほど多くない印象です。そこで、自身の経験を元に、マイクロサービスの設計をどのようにしているか、ポイントをかいつまんで説明したいと思います。
第一回はまず全体像としてのマイクロサービスの構築プロセスに触れます。第二回がサービスの責務の話、第三回がインターフェイスを考える話になる予定です。
本題
すべてのソフトウェア構築には、本質的作業として抽象的なソフトウェア実体を構成する複雑な概念構造体を作り上げること、および、偶有的作業としてそうした抽象的実在をプログラミング言語で表現し、それをメモリスペースとスピードの制約内で機械言語に写像することが含まれている。
- 銀の弾などない— ソフトウェアエンジニアリングの本質と偶有的事項
ソフトウェア構築の諸原則に従えば、おおよそ以下のようなフローになると思います。
左側が、他のマイクロサービスから見た抽象としてのマイクロサービスです。マイクロサービスのモデリング、モデル化されたマイクロサービスなど色々な言い方がありますが、同義です。右側が、実際に動作するコードやデータベース・スキーマを含んだ、具体としてのマイクロサービスです。上段がマイクロサービスの全体に関わる設計で、下段が個別のインターフェースに関わる設計です。
矢印は各プロセスが与える影響を表わしています。最初は実線だけを見る方が理解しやすいでしょう。つまり、「サービスの責務を定義」→「インターフェースを定義」、「サービスの責務を定義」→「サービス内部の基本設計」などです(ここで最初に考える「サービス内部の基本設計」は、どういったフレームワークやデータストレージを使うのかというような、「インターフェースの実装」や「サービスの責務」の実現可能性に関わる大まかな設計です)。
しかし、そんなに綺麗に行くでしょうか?実際には、欲しいインターフェースを定義してみてから、欲しいマイクロサービスの全体像がより鮮明に見える、あるいはインターフェースを実装する過程で、より適切なインターフェースの定義にたどり着く、と言ったことはあるはずです。これをフィードバックと呼び、破線で書いています。
フィードバック、と言っているのは、例えば "インターフェース定義の集合"すなわち"マイクロサービスの責務"ではない からです。下位のところで遭遇した問題はあくまで上位のことを再考する必要があるかもしれないというシグナルであって、上位のものから下位のものがより具体的に導かれているという関係は維持すべきです。
なおここでは特にスタンスとして、トップダウンな開発を推奨しているわけでも、ボトムアップな開発を推奨しているわけでもありません。それは使い分ければ良いでしょう。ただ、良いソフトウェアを作るのであれば、 全体の設計と個別の設計・抽象的な事柄と具体的な事柄はそれぞれは分けて考えよう ということと 分けたものの間を必要に応じて行き来しよう ということを言っています。
他のマイクロサービスとの相互作用
上記の話は、作ろうとしている単一のマイクロサービス上での相互作用の話でしたが、実は「サービスの責務」「インターフェース」のそれぞれのレベルで、マイクロサービス間での相互作用があります。
「サービスの責務」の場合、各マイクロサービスは自律していて上位・下位という関係はないのが通常なので、対等なフィードバックという形になると思います。「インターフェースの定義」の場合、これもマイクロサービスの自律性から、インターフェースを提供する側からの影響は直接的に、インターフェースを利用する側からの影響はフィードバックという形で現れます。
次回
次回は、マイクロサービスの責務を定義する話です。具体的な道具として、デザイン・ドキュメントを紹介します。