数年来の技術的負債を改修した話 - 2種類のORM並列状態からの脱却 -
はじめに
勝丸と言います。ログラスのエンジニアが毎週記事を発信するLoglass Tech Blog Sprint 2周目に突入しました。前回は「心穏やかにDBバージョンアップ!ロジカルレプリケーションで安全にバージョンを切り戻せるようにした話」という記事を書きました。こちらもよろしくお願いします。普段はログラスの横串組織で活動しています。
この記事では「数年来の技術的負債を改修した話 - 2種類のORM並列状態からの脱却 -」というタイトルで、年末から年始にかけてやっていた作業について共有します。
この記事で得られること
- リファクタリングのやり方や考え方
- リリースへの持っていき方
- 投資判断のタイミングや負債解消について
経緯
- ログラスでは2種類のORMが存在していました。創業時にORMとしてExposedを採用したのですが、後に一部機能が足りないことが発覚し、別のORMを利用し始めました。
- ただ別のORMを使い始めるときには、すでにExposedのコードの量はある程度膨れ上がっていました。また事業の立ち上げフェーズでもあったので、できるだけ新機能追加にリソースを投下したいと思っていました。
- 苦肉の策として、「もし新しく機能追加したい時は、新しいORMで機能追加する。既存のExposedのコードに触る場合は、テストを追加した上で差し替える」 というルールで数年運用していました。
- そこから3年経ち、他のライブラリのバージョンアップ(使っているWebフレームワークやJavaのバージョンアップなど)でExposedがあることでうまく動かないという問題になりました。
- 2023年の年末に開発合宿があり、そこで今まで取り組みたかったけども取り組めなかったことをやるという機会を得ました。そこで1月中旬をリリース予定日として作業を始めました。
戦略
具体的に置き換えをどう進めていくかですが、開発合宿でPJのメンバーと以下のことを合意しました。
リリース戦略
定期リリースに含めないようにする
ログラスでは週に2回のリリースを行っています。ORMの書き換えは定期リリースに混ぜず、Exposed廃止PRのみを別のタイミングでリリースすることにしました。定期リリースに混ぜ込むとなにか問題があったときに分かりづらいからです。
1つずつ細かくリリース出来ることが理想ではありますが、現在のリリース運用がトランクベース開発に対応していないこと、1つ1つ担当チームにレビューをお願いすると工数が膨大になるため、この様なリリース戦略としました。
この時点である程度ビッグバンリリースになることを覚悟しました。
また実際にリリースするまで時間がかかるブランチ戦略を取ると、メインブランチ追従にコストが発生するので、メリット・デメリットを整理した上で判断が必要だと思います。
作業ブランチを作り、細かくそのブランチにPRを重ねていく
ブランチ戦略ですが、developブランチからExposed廃止コミットを集めるブランチ(kaizen/goodbye-exposed)を切り、そのブランチに対して細かくPRを重ねていきました。
PRは出来るだけ小さく作ることを心掛け、1つのメソッドで1PRを目安としました。(kaizen/goodbye-exposed-methodA)
こうすることでレビュアーの負担を減らせるようにしました。この様なリファクタリングタスクでPRを1つにまとめてしまうとレビュアーはレビューしきれません。
個々のPRの戦略
テストが足りていない場合は、まずテストを足す
今回の対応では、創業当初のコードに手を入れるので、テストがない部分も散見されました。(誰だテスト書いていないのは!と思って見たら自分だったり…。)なので書き換えの基本として、テストがない部分にはまずテストを書くことで安全に作業を進めました。
SQLのBefore / Afterをちゃんと用意する
後述しますが、リリース前に開発部全体で最終確認の時間を取りたかったので、PRにできるだけSQLのBefore/Afterを書きました。テストを動かして発行しているSQLを抜き取ってPRに貼り付けるのは、簡単ですが全体の量が多く大変でした。(最終的に細かいPRは50個ぐらいになりました)
余計なことはしない
これが一番重要だと考えています。リファクタリングをしていると、どうしても「ここも直したい」という気持ちに駆られます。そしてそれが1行修正だったりすると、サクッとやってしまいそうになります。しかし今回はそういう対応は一切見送りました。
見送った理由としてはレビュアーのレビューが難しくなるからです。目的外の修正をしてしまうと、なぜこの変更が入っているのかという意図をレビュアーは受け取れず、レビューがストレスになります。あくまでも今回の目標は「ORMの書き換え」なので、その目的に沿わないものは見送りました。
今回の作業をペアプロで進め、作業自体がレビューを兼ねているのであれば、少しの書き換えはやっていたと思います。
実際の作業
以下は作業時の感想です。
効果的なテストを足す → 書き換えるを徹底した
戦略として「テストが足りていない場合は、まずテストを足す」と書きましたが、存在するテストのなかには効果的ではないテストもありました。
存在するテストの中には、一部のデータパターンのケースしか対応できてないものもあり、ありえるデータパターンを書き出し、それらのテストを追加することなども行いました。
また新規でテストを追加することもしました。変更の半分以上はテストコードでした。
Github Copilotが優秀過ぎる
ログラスでは開発時にGithub Copilotを利用できます。Copilotの支援がなければ、終わらなかったかも知れません。今回はほとんど1対1の書き換えだったので、Copilotが活躍してくれました。ただCopilotが吐き出したコードも間違っている部分もあり、テストで見つけることが出来たり、目検をしたりしました。
レビュアーを意識して、コミットを綺麗にすること
こういうリファクタリングタスクではレビューが重要になります。できるだけコミットを綺麗にすることを意識していました。
テストは資産である
今回は「テストを書きやすい環境を整えられていること自体が、資産であること」を痛感しました。Copilotの支援を得ながら進めることができたとは言え、量が多く大変でした。
当初目標としていた年末に全作業が終わることはなく、年始までかかりました。最後のほうは長女に煽られながらも、最後までやり通せました。
リリースに向けて
書き換え作業が終わったらリリースに向けて動き始めます。
QAと観点整理
動作確認を各スクラムチームにお願いしていくのですが、スクラムチームからすると、どういう観点でレビューすればいいのかわかりません。なので、QAエンジニアに今回の作業内容について共有し、レビュー観点を整理しました。
各チームでバグバッシュ
QAと整理した観点をチームに伝えて、いつまでに確認してねと伝えました。
各チームがそれぞれスプリント内で、確認タスクをもちこなしてくれました。
リリースへ
バグバッシュもOKになったのでリリースに進みます。問題なくリリースできました!!
とはならず、リリースまで二転三転ありました。書き換え失敗しているケースをQA作業中に見つけるなどしました。
どれもお客様に影響はなかったですが、ここの進め方は課題があったかなと思います。
「UnitTestがない」は論外ですが、「UnitTestがあるから安全」は必ずしも成り立たないという、初歩の初歩を改めて確認しました。
無事リリースは完了しており、Loglassの数年来の技術的負債を返済することが出来ました。
技術的負債と返済戦略について
以下はポエムです。興味がない人はまとめまで飛んでください。
弊社にとって、ORMが同じアプリケーションに2つ存在することは技術的負債でした。(Exposed自体が悪いわけではないです)
この状態を解消するのに、3年かかりました。作業中、「この負債はいつ回収するのが最善だったか」を考えていました。結論、このタイミングで良かったのではないかと思っています。
そもそも何故今まで対応して来なかったのかを考えると理由は2つあります。
事業フェーズ的に機能開発を優先させていた
今までのログラスは事業を伸ばすために機能開発の優先順位が高く、技術的負債の中でも問題になってこなかったExposed廃止の優先度をあげてきませんでした。
機能開発をフルスピードで推進させつつ、技術的負債をどう扱うのかは過去にも記事を書いたことがありますので参照ください。ログラスの技術的負債を仕組みで返済していく戦略を紹介します
チームを超えた案件を扱いづらかった
ログラスは共有のリポジトリを複数のチームで開発しています。今回のORMの変更は影響範囲が大きく、作業をするチームは1チームに閉じません。ログラスのチームの領域を超える案件をうまく扱えない(優先度がスクラムチームで決定してしまい、全体のタスクを期限までに完了させづらい)という課題がありました。
今回はスクラムチーム外のプロジェクトチームを作ってオリャっと進められたことが良かったと思います。
なぜ今改修するに至ったのか
優先度が上がったからという理由に尽きます。他のライブラリのバージョンを上げる関係でどうしてもExposed関連を剥がしたほうがよいと判断しました。Exposedを魔改造して使っていくという選択肢もあったのですが、それは長期的な視点から見ると最適では無いと判断しました。
また、3年間の間にかなり環境も変わってきており、意思決定をしやすかったという背景もあります。
- 3年間で少しずつ、既存のExposedからの置き換えが進んでいたこと
- テストが少しずつ拡充されていたこと
ここからの学びは何か
- 事業フェーズによって、技術的負債を返せない時はある。そのときは「負債を大きくしないようにする」を考える
とはいえ、影響が無いからと言って、ずっと置いておくことが最良なのか? は考えたほうがいいと思います。
例えば、「過去の経緯を知っている人がいなくなり、後で改修するコストのほうが高くなる」や「負債が大きくなっていないと思っていたが、実は知らないところで利用されて大きくなっていた」などの事態が想定されます。
いずれにせよ、やると決めたらやり切る。その実力を持ち続ける。が重要ですね。
まとめ
結果
2つのORMが併存するという、ログラスの数年来の技術的負債を解消できました。
やり残したこと と Future Work
- 余計なことはしないにも書いたように、敢えて今回はスコープから外したものがあるので、それに対応していきます。
- チームを超えた問題をうまく取り扱うためにチームの練度を上げていく余地があると感じました。
Exposedへ感謝
最後に、Loglassの初期を支えてくれたExposedに感謝を。
我々は2つのORMを使いながら成長してきましたが、Exposed自体の問題で何か起こったことは1度もありませんでした。創業期を支えてくれてありがとう。
We are hiring
お約束のやつです。ログラスでは 「いい景気を作ろう」 というをミッションをともに実現してくれる仲間を探しています。
アプリケーションエンジニア
一緒にLoglassを作っていただける方を探しています。サーバサイドはKotlinを使っていますが、Kotlin未経験の人も積極的に募集しています。(社内のエンジニアの9割方は入社時Kotlin未経験です)
スクラムマスター
スクラムチームの練度をもっと上げたいと思っています。弊社EMの飯田が書いた記事も参照ください。専任スクラムマスターを置くまでの思考過程と置いてどうなったか?
QA/SET
上記でも登場しましたが、スクラムチームに入って活動するAgile QAを募集しています。またテストの自動化をリードいただける方も探しています。ログラスのQAについてはこちらに記事が纏まっています。ログラスのQAについて
SRE/クラウドインフラエンジニア
「Site Riliabilityを高めるには?」をキーワードに、インフラ領域に閉じない活動をしていければと思います。
Discussion