t_wadaさんにTROCCO®︎開発の悩みを壁打ちしてもらいました
primeNumberのSoftwareEngineerの中根(@gtnao) です。
今回、特別講師として和田卓人さん(t_wadaさん)をお招きして社内勉強会を開催しました!
勉強会はprimeNumberのオフィスで実施しました。社内には写真のように、広めのイベントスペースがあり、勉強会や輪読会がよく実施されています。
勉強会は、ローンチから6年ほど経過したTROCCO®︎が抱えるリアルな悩みを、CTO鈴木(@kekekenta)と私中根が、t_wadaさんに公開壁打ちしてもらうスタイルで行いました。ここから先は、勉強会のアジェンダに沿って内容をご紹介していければと思います。
TROCCO®の前提知識
ディスカッションを始める前に、TROCCO®︎の前提知識をt_wadaさんに説明させていただきました。その場で初めて共有する形式だったのですが、すぐに全体感を把握されその後の質問に的確な回答をしていただける様は、さすがt_wadaさんだなとメンバー一同舌を巻いていました(笑)。
ここでは、後述の内容に関連する内容に絞って簡潔に共有します。
サービスの特徴
ETL機能などのデータ分析基盤を構築するために必要な機能が詰まったSaaS。
2018年11月にリリース。丸6年が経とうとしているフェーズ。
2024年10月現在、毎日数十万件のジョブが実行され、Kubernetesで捌いている。
一般的なSaaSとしての側面に加えて、日夜動き続けるお客様のデータパイプラインを支えるジョブ基盤としてのPaaSといった側面もある。
2024年10月現在、約100種類のコネクターが存在している。
技術スタックの特徴
Rails (Ruby)
モノリス
React (TypeScript)
MySQL (Aurora)
Embulk (Java)
AWS
ECS
Railsサーバー部分は当初からECSでホスティングしている。
EKS(Kubernetes)
大量のジョブを実行する基盤としてKubernetesに頼っている。
より詳しい内容が気になる方はカジュアル面談をお気軽にお申し込みください!
メイントピックのディスカッション
テーマ1:有象無象なRailsのapp/servicesディレクトリ
■悩み
1つ目は、Railsのレールに乗らない(本当は乗せられるかもしれない)コードがapp/serviceディレクトリに特にルールもなく散在していることです。たとえば、複数モデルにまたがる保存処理、外部サービス(e.g. BigQuery)のSDK Gemのラッパークラス、AWSやk8sのインフラを扱うコード、永続化されないドメインモデル的なクラス、各種ジョブの手続き的な処理、その他ユーティリティ的なクラス、などなど。
サービスが発展していくに従って、認知負荷を上げ、割れ窓理論的に考え無しのコードが増えていく原因となっていました。
■t_wadaさんからのアドバイス
※ t_wadaさんとのディスカッションの過程で得られた知見を私たちの方で要約したものとなります。
まずは全体の構造、サイズ感、規模感を確かめたい。
rake statsコマンドを叩くと、やはりserviceが多い。
一番よくない状況はcontrollerにロジックがあること。(controller層が薄いことはお褒めいただきました。)
Railsは、標準のMVCディレクトリ以外では比較的自由に名前空間を切ってしまっても問題ない。自分達の中である程度分類ができているのであれば切ってしまえばいい。
逆に言えば、models配下はトップレベルにファイルが並んでいないと何かと不都合がある。
複数モデルにまたがる保存処理がサービスクラスに置かれることは多いが、その必要があることは少ない。
A、Bを同時に更新する必要があるが、本来はイベントモデルのCが存在しないだけなど。
(筆者コメント)イベントモデルの話題は、t_wadaさんが過去に出演されているPodcastでも紹介されていますので参考にしてみてください。
技術的な役割に基づいて切るか(ホリゾンタル)、アプリケーションの機能に基づいて切るか(バーティカル)という観点もある。後者はマイクロサービスやモジュラーモノリスと呼ばれるもの。
マイクロサービスやモジュラーモノリスの動機。
人間の認知負荷には限界があるので限定することで負荷を下げたい。
早く開発したいから切り出すのではなく、開発をあまりしないから、安定させるために切り出すという観点もある。
デプロイ独立性は、枯れさせたいのでデプロイを遅くしたい、という動機にも有効。
(筆者コメント)開発に注力する箇所から切り出そうと考えていたので、このアドバイスは目からウロコだった。
バウンダリーを切ることはえらく難しい。
事業的なドメインでバウンダリーを切るべき。
ここが切り口という点が5年以上事業をやってるので何となくわかるはず。
マイクロサービスで分けるとダメージが大きい。
モジュラーモノリスなら比較的後戻りもしやすい。
モジュラーモノリスを導入するRails企業は増えてきているのでWatchしていくといい。
テーマ2:マルチテナントにおけるセキュリティ担保
■悩み
2つ目は、1つの論理DB(MySQL)の上に、すべての顧客アカウント(テナント)のデータが乗っているマルチテナント構成を取っていることです。DBのレコードが別のアカウントに紐づく事象が発生した場合、大きなセキュリティ事故につながる可能性があるため、どのようにセキュリティを強化していくべきか悩んでいました。
現状は定期的な第3社診断の実施や、セキュリティレビューで担保していますが、より仕組みで解決する方法は無いかと相談させていただきました。
■t_wadaさんからのアドバイス
基本全てのテーブルにtenant_idを付与するべき。
大変なのでじわじわやっていく戦略がいい。
カラム名は同じ名前にする(tenant_id)。
ほぼ全てActiveRecordのクラスが、belongs_to tenantになる状態にする。
t_wadaさんの場合はconcernsに切り出してincludeしている。
(筆者コメント)実際のコードも見せていただきました。
tenant側には全てのテーブルのhas_manyをつける。
全ての検索クエリをtenantからはじめれば事故らない。
current_userが決まっているようにcurrent_tenantを決める。
テーマ3:TROCCO®︎のサービス特性を前提としたテストや品質担保戦略
■悩み
3つ目は、お客様がサービスに期待している最も重要な価値は「想定した時点にデータが想定した場所にある」ようにジョブが正常に実行され成功することに対して、テストピラミット的にユニットテスト層を厚くしていっても、TROCCO®︎特有のサービス価値の品質を上げられず、テスト拡充の方針に迷っていたことです。
■t_wadaさんからのアドバイス
スモールテスト以外のテストも充実させていかないといけない。
たとえば、BigQueryに関しては外部(BigQuery側)にロジックがあるので、実際にリクエストを投げないとテストにならないことが多い。
モックした部分と本物の動きの違いを検出できないと、妄想に対してテストしていることになる。
ラッピングしているクラスを使う部分はモックで良いが、ラッピングしているクラス自体は本物を使ってテストすべき。
レスポンスのスナップショットを取るなども手。
テストをラージからミニマムに下げるためには、Fakeを使うという方法がある。
たとえば、DynamoDB local。
ただし、BigQueryだとFakeを使うとロジックのテストになりにくい。
(Q)なぜDynamoDBは問題ないのか?
(A)DynamoDB側にロジックがないことが多い。
ただのKVSの口がDynamoDBと互換があればよいことが多い。
BigQueryだとBigQuery側にロジックがありそれに依存していることが多い。
(筆者コメント)一口に外部サービスといってもケースバイケースという点は勉強になりました。
質問コーナー
メイントピックの後は、メンバーから随時募集していた質問コーナーに移りました。その中から、リファクタリングに関するディスカッションから得られた知見を共有します。
リファクタリングをやるやらないじゃなくて、問題はいつやるか(直前、直後、後日)。
後日になってしまうとだいたいやらない。タイミングはリリースの直前か直後しかない。
コツは構造だけ変わるPRと、振る舞いが変わるPRときっちり分ける。
前者:Diffは大きいけど振る舞いは変わっていない。
後者:Diffは小さいけど振る舞いは変わっているなど。
振る舞い変更か構造変更かのラベルをつけてもいい。
まとめ&参加者の声
ディスカッションはとても盛り上がり、時間いっぱいまで質問に回答をいただく形となりました。実際に参加したメンバーからは以下のような感想をもらっています。
勉強会を実施中も、実況中継スレッドも立てて、わいわいと盛り上がりました。
私事ですが、t_wadaさんが出演されているPodcastなどを普段から聞いている大ファンなので、始まる数時間前からずっと緊張していたのですが、t_wadaさんのお人柄もあって終始和やかなあっという間の2時間でした。
t_wadaさん、この度はお忙しい中、大変ためになる勉強会をありがとうございました!貴重なアドバイスを頂けて、背中を押してもらえたなと感じます。NextActionも沢山出てきたので、消化し終わった頃合いにまた壁打ちをぜひお願いしたいなと思っています!
さいごに
ここまで記事を読んでいただき、ありがとうございました!
primeNumberに少しでも興味を持っていただけた方は、お気軽にカジュアル面談をお申し込みください!