- マネーフォワードを支える Rails プロダクト群のこれまで - 共有リソースの課題 - 我々は共有リソースとどう向き合っているのか - 有志での取り組み - 専門チームでの取り組み - 全社的な取り組み
についての資料です
マネーフォワードの Rails プロダクト群を支え、同時にくっついてなかなか離してくれない共有リソースとの向き合い方
View Slide
自己紹介
自己紹介● GitHub: furuhama● 名前: 古濱 有佑(ふるはま ゆうすけ)● マネーフォワード ビジネスカンパニークラウド横断本部 わり算グループ リーダー● マネーフォワードには新卒で入社して 3 年目● 最近のプチ自慢: ISUCON 10 でRuby を使ったチームで唯一本選に行きました ● 最近の悲しいこと: ISUCON 10 本選で最終結果が 0 点(失格)でした
所属組織についてもう少し● プロダクトの数が多い● ほとんどが Rails バックエンド● 誕生した時期は様々● それゆえインフラ構成や共有リソースとの関わり方も複数パターン存在する(FY20 3Q 決算説明会資料より引用)
今日話すこと
今日話すこと● マネーフォワードを支える Rails プロダクト群のこれまで● 共有リソースの課題● 我々は共有リソースとどう向き合っているのか○ 有志での取り組み○ 専門チームでの取り組み○ 全社的な取り組み● 補足: 目指したい世界のその先に見えている課題 (時間があれば)
マネーフォワードを支えるRails プロダクト群のこれまで(今の選択だから得られたこと)
マネーフォワードを支える Rails プロダクト群のこれまで● ざっくり以下の流れで会社のプロダクトが増えていった○ 家計簿プロダクトができる○ 個人の確定申告ニーズに応えるために確定申告プロダクトができる○ 小規模法人向けの会計機能が確定申告プロダクトを拡張する形で追加される○ そこから toB のバックオフィス領域向けにいくつかプロダクトができていく
マネーフォワードを支える Rails プロダクト群のこれまで● 大きく 2 つのリソースを共有している○ ライブラリ○ DB● 共有度合いによって大きく 3 つのパターン○ どちらも共有(パターン①)○ DB の一部とライブラリのみ分離 (パターン②)○ どちらも分離(パターン③)
マネーフォワードを支える Rails プロダクト群のこれまで● パターン①がメインの時期があった● 以下のメリット○ 共有のライブラリがプロダクト提供のための汎用的な機能を吸収してくれている○ 共有の DB によってトランザクションやJOIN が利用可能○ ActiveRecord の強みを活かしやすい● シリーズとして関連し合うプロダクトの開発において 0->1 や 1->10 がスムーズに
共有リソースの課題(くっついて離してくれない)
共有リソースの課題● プロダクトの成長と共に様々な変更を共有リソースに加える○ 共有ライブラリ上のモデルに新しいコールバック追加したり既存のメソッドに新しい条件を追加したり ...○ 共有の DB にどんどんテーブルを追加したり一部のテーブルレコードが膨れ上がったり...
共有リソースの課題● 共有リソースにより思わぬ副作用が○ 共有ライブラリ上のコードがすべてのプロダクトで想定した通りに動かなかったり...○ 特定のプロダクトの実行したクエリによる性能劣化で全プロダクトが影響を受けたり...● 副作用によって以下の課題が露呈○ 開発速度の低下○ 安定性の低下
ひとまず目指したい世界● プロダクトをまたぐ副作用が極力発生しない、当たり前の世界を目指したい● 開発者の関心事を自身のプロダクトに閉じさせることによる開発速度の向上● 共有 DB をなくすことによる障害単位の縮小
我々は共有リソースとどう向き合っているのか(どうやって離れる?)
我々は共有リソースとどう向き合っているのか(有志での取り組み編)● DB の安定性の向上のためにアプリケーション開発者とインフラから有志が集まった○ ディスク容量の大きいテーブルを分割○ スロークエリの改善、もしくは参照分割○ ActiveRecord 経由で実行されるクエリにバックトレース情報をコメントとして付与■ アプリケーションコードと DB のクエリのコンテキストを繋ぐ
我々は共有リソースとどう向き合っているのか(専門チームでの取り組み編)● 有志での活動だとどうしても優先度が上がりきらないという問題があり、共有リソース分割のための専門チームを組成● それがわり算グループ● ライブラリと DB の解体を主眼に置いている● 例えば以下のようなことをやってきた○ ライフサイクルとコールバックを考えてモデルを持ち帰る○ まず更新を特定のプロダクトに集約してライブラリでは参照専用モデルにする○ ライブラリが提供する機能のオプショナル化○ ライブラリアップデートの自治活動
我々は共有リソースとどう向き合っているのか(専門チームでの取り組み編)● ライフサイクルとコールバックを考えてモデルを持ち帰る○ create, update, delete それぞれのタイミングと実行されるコールバックを整理○ read をどのプロダクトで行っているのかを整理○ 実は create, update, delete のタイミングをread に間に合うようにずらして特定のプロダクトに集約できるケースがあった (整理によって見えてきた)
我々は共有リソースとどう向き合っているのか(専門チームでの取り組み編)● まず更新を特定のプロダクトに集約してライブラリでは参照専用モデルにする○ 更新タイミングがバラバラかつ更新者となるプロダクトがバラバラだと不整合が起きやすいし、将来のバグも生みやすい○ なるべく参照専用にしていけるとシンプルに考えることができるようになる○ 以下のようなコードを共有ライブラリに置く
我々は共有リソースとどう向き合っているのか(専門チームでの取り組み編)● ライブラリが提供する機能のオプショナル化○ 汎用的な機能の各プロダクトへの持ち帰りに際してどうしても進捗に差異が生まれてしまう○ Configuration クラスを導入し、どちらのケースもサポートするために Rails の initialize フェーズで渡すフラグを設定○ フラグが増えすぎると全パターンの考慮が難しくなる(boolean のフラグだとして 2^N)のであまり積極的にはやりたくない...
我々は共有リソースとどう向き合っているのか(専門チームでの取り組み編)● ライブラリアップデートの自治活動○ 共有ライブラリは gem の形式で提供している○ どうしてもプロダクト側でのアップデートが疎かに○ その他にも主要ライブラリの脆弱性対応の進捗管理などもしたかった○ バージョン一覧をさっと取れるようなコードを書いてみんなのお尻を叩いている
我々は共有リソースとどう向き合っているのか(全社での取り組み編)● ライブラリの機能や DB のテーブルの役割を分解していくと、どうしてもプロダクト間で共有したい箇所が出てくる○ 基盤サービスとして切り出して API の通信経由での機能利用をする形に置き換え○ 利用側の置き換えはすべてのプロダクトで行う必要がある○ Ruby の client であれば gem として実装を提供○ 全社的な取り組みとして推進
我々は共有リソースとどう向き合っているのか(全社での取り組み編)● 基盤サービスにはそれぞれ専門のチームがついて開発 /運用を行っている● 例えば以下のようなサービスをはじめ現在では 20 を越えるサービスができはじめている○ ユーザー管理/認証部分を担うサービス○ toB 向けの事業者管理を担うサービス○ ユーザーの金融機関情報の参照や更新を担うサービス○ toC/toB 向け課金を担うサービス○ メール配信を担うサービス○ PDF 生成を担うサービス○ etc● これらだけでなく特定のプロダクト内での機能を切り出したサービスもできはじめている (今回は省略)
目指す世界とユーザーへの価値提供● 紹介してきた取り組みがすべて結実してようやくこの状態になれるか...???というところ○ とはいえあと 1 年くらいでだいぶ近づくのではと思っている● 会社としてこういった内部的な改善ばかりやっていればいいわけではない○ ビジネス要件を折り込み、走りながら直しているような状態
We’re hiring!カジュアル面談もあるので気軽にどうぞ今日時間の関係で端折ってしまった話も結構あるので話聞きに来るだけでも歓迎です!
補足:目指したい世界のその先に見えている課題(時間があったら)
目指したい世界のその先に見えている課題● まだまだ課題はある○ 通信によるデータの更新・参照がメインとなった世界での■ 整合性の担保■ 最適なメッセージングの方法の模索○ プロダクト間のインフラ構成の差異を減らす■ プロダクトの誕生時期によって構成が異なり運用コストが増加○ インフラ運用をプロダクト横断のチームが行っている■ プロダクト開発チームに運用を委譲しないとインフラ運用チームがボトルネックに■ そもそもスモールチームでのスムーズな開発には開発・運用のサイクルがチームで閉じていることが不可欠● 最終的には一貫して開発運用を行える、リソースを共有せず疎に繋がった自律的なチームの集合として会社が存在するような状態になるといいのかな、と個人的に考えている