hacomono TECH BLOG

フィットネスクラブやスクールなどの顧客管理・予約・決済を行う、業界特化型SaaS「hacomono」を提供する会社のテックブログです!

モジュラーモノリス導入がもたらした功罪



こんにちは、プラットフォームチーム所属のmaco+(まこたす)です。
ちょうど2年前に「モノリスなRailsにモジュラーモノリスを導入した話」というタイトルで執筆させていただきましたが、その後の取り組み・経過について中間レポートをお伝えできたらと思います。

導入の背景

本題に入る前に導入の背景やポイントについて簡単におさらいしたいと思います。
導入検討当時、今後人数の増加が考えられる開発組織においてhacomonoプロダクトの開発生産性を下げないようにしたいという課題がありました。人数が増えると複数のチームから触れるようなコードに対しては認知負荷があがり責任の所在が曖昧になるものです。当時これらの問題はそこまで顕在化しておらず、予防的な意味合いでモジュラーモノリスの導入がなされました。
なぜモジュラーモノリスだったのかなどより詳しい話は、先述の記事を参照いただければとおもいます。


また当時の自分のポジション、責務についても説明します。
この取り組みは自分が入社直後基盤チームに所属していた際におこなったものです。基盤チームの主な仕事はhacomonoのインフラの運用でした。先述の組織課題に対して基盤チームとして検討していく流れになり、入社直後の私が1エンジニアとしてモジュラーモノリスを用いた機能開発を実践し導入していった背景があります。

導入時の期待値と課題

以前の記事と伝え方は少し変わりますがモジュラーモノリスを導入した際に、ざっくり以下のような期待値をもたせていました。

  • モジュール化という手段で様々な認知負荷をさげる
    • モジュールにコードオーナーを持たせ責任を明確にし、正しい仕様を維持 / 管理できるようにし、安心して開発を可能にする。
    • CI/CDに関しては従来の方法を維持することで、新しい知識を不要なまま開発を可能にする。
    • モジュールの外部とのやりとりは型の決まったAPIを介することで、関心毎を閉じ込めコミュニケーションコストをさげる。
  • モジュール内部はあえてルールを決めないことで、自由な開発を可能にする
    • 自チームのモジュールにあったアーキテクチャ戦略の余地を残す


現在の導入状況

2年が経ち、現在のモジュール数は20にまで増えました。増えたモジュールの中には基盤系のモジュールやhacomonoの1機能など様々ではあります。
最初の3,4モジュールほどは、プラットフォームからのコラボレーションに近い形で連携を行い導入を進めました。同時にモジュール作成ツール(= Ruby製のtemplate generator)を整え、後続して生まれてくるモジュールが作りやすいような整備を行いました。
ある程度軌道にのったと判断したタイミングで、他チームからの相談ベースでファシリテーションを行なっていくスタイルに切り替えました。

功罪

結果的にうまくいったこととうまくいかなかったことがあります。それらを振り返りたいとおもいます。

うまくいった

モジュラーモノリスの取り組みで、効果的に働いたのは新規の基盤系モジュールの開発です。
Webhookやメールなどの基盤系の機能は責務が明確なため提供すべきAPIが明確です。モジュラーモノリスという手段を用いてコードレベル x テーブルレベルでの分離を可能にすることで他と疎結合になり、開発フローがよくなる分離を実現できました。
またこれは狙っていたわけではありませんが、AIとの開発の相性が良いという結果も得られました。hacomonoはモノリスのアプリケーションでAIを用いた開発をする場合に自チームの領域以外のコードベースも読み込んでしまうことがあります。ここでモジュールのコンテキストに限定することでAIに必要な範囲のみを理解させやすくなりました。

うまくいってない

たくさんあります。一言で書くのは難しいので、トピックごとに話したいとおもいます。

既存コア機能のモジュール化

新規に作成されるプロダクト機能系のモジュールがある場合、そのモジュールがプロダクトのコア機能を利用したいケースは考えられます。その際、コア側がモジュール化されていないとどうしてもコア側と密結合ないし、違和感がある形でデータのやりとりをしなければならず開発体験としては辛くなってしまいました。開発体験を良くするという観点においては、先にコア機能のモジュール化を進めるべきでした。

モジュールの再編

モジュールの粒度は、packwerkを利用することで事業成長やピポッドに応じて変更できる形にしていました。しかしプロダクト機能系のモジュールとして現在最適な形かどうかは、事業への深い理解と見通しが必要でそれは容易なことではありません。仮に先が見えていたとしてROIを考えると今やるべきではないという判断が取られる場合が多くなるとおもいます。見直しをするならば、モジュールのマイクロサービス化だったり、別の大きなペインが生まれたタイミングでの対応になるかとおもいます。

コードオーナーの導入

モジュールには必ずコードオーナーを設定することで、自チームのモジュールの仕様を把握し、他チームによる予期せぬ変更を気付けるようにする狙いがありましたが、この辺りも100%での浸透はできていません。
コードオーナーという仕組みが悪いわけではなく、会社としてどう運用していくかの目線を合わせるステップを踏まずに仕組みを導入したことで形骸化してしまい正しく運用できていないという現状です。

モジュール内のコーディングルールを設けなかったこと

モジュール内の構造は、モジュールの特性に応じて変える必要があることや、新しい技術的な取り組みを行いやすいようにあえてルールを設けませんでした。
その結果、最初に作られたモジュールが基盤系のCRUDなAPIを提供していたこともあり、後続で提供されるモジュールもCRUDなAPIのみを提供するものが増えていってしまいました。高度なモジュールだとCRUDだけのAPIでは使いにくいケースもあり、これも開発体験が悪くなってしまう結果に繋がっています。

Platformチームとしての関わり方

Platformとして開発生産性の維持を目標にモジュラーモノリスを導入しましたが、当時のミッションに開発者へのカスタマーサクセスが含まれてなかったことから、組織変遷や責務の変更のタイミングでモジュラーモノリスの推進の優先度が下がってしまったという点があります。
現場目線で状況を把握し、伴走期間を長くとっていれば上記のような失敗もより早く気づき軌道修正できたのではないかと振り返っています。うまくいかなかったトピックのほとんどの原因はここに尽きるとおもいます。

結局モジュラーモノリスを導入してよかったのか?

結論から申し上げますと、導入してよかったと考えています。
当初の目的の「開発体験の維持」は全てのケースでの達成はできていません。しかし開発体験がよくなかった類のモジュールにおいて、切られたモジュールの粒度が最適なインターフェースでない可能性に気づけたり、コア側で整理すべきモジュールがあることがわかったことなどプロダクトが正しいレイヤー分けになっているかに向き合えるきっかけになりました。
もし最初からマイクロサービス化に舵をきっており、物理的に分離されてしまっていたら、そこからあるべき形に修正していく作業が大変なのは想像に難くありません。既存のCI/CDやコードベースを活用することで最小限の労力でこれらの問題に気づけ、逆にマイクロサービスに切り出せそうなものがわかってきたのは大きな収穫でした。
またこの話を経てプロダクト開発チームの有志のメンバーで、何をモジュールにすべきか、何なら最初からマイクロサービスにすべきかを話し合う場が設けられるようになりました。

Platformチームという観点でも、過去の機能を開発し提供するだけのチームからPlatform Engineeringを実践するチームとして何が足りないかを考え始めるようになりました。
直近のOKRのObjectiveには「開発者の高い生産性と体験を提供できている状態を目指す」というミッションを掲げており、より開発者の声を聴きながら本当に必要な機能を提供していこうという目線合わせができるようになってきました。

まとめ

以上がモジュラーモノリス導入における中間レポートでした。
うまくいってないケースをやや強調して書いておりますが、モジュラーモノリスという手法を否定しているわけではありません。モジュラーモノリスという手法はとても良い手段の一つになり得ます。これまでPlatform Engineering観点の取り組みが足りないがためにうまくいってない部分がありました。
今後は反省を活かしプロダクト開発チームとのコラボレーションという形で導入ないし改善をしていけたらと考えております。また一定の結果がでたタイミングでTechBlogにてレポートを綴ろうと思います。



💁 関連記事