これは Livesense Advent Calendar 2024 DAY 20 の記事です。
はじめまして、アルバイト事業部の星 id:watasihasitujidesu です。
idがwatasihasitujidesuですが、執事ではありません。エンジニアです。
今回はタイトルの通り、創業時から運用が続いていたレガシーコードから脱却に取り組んだプロジェクトについて、その背景や課題、そして具体的な対策を紹介します。
背景
リブセンスが運営するマッハバイトは創業時から続くサービスです。*1
このマッハバイトのシステムはもともとPHPで書かれていたシステムでしたが、技術的負債の返済を少しずつ行うことで、PHPからRubyへの移行を進めてきました。
過去記事でも言及されていますが、社内向けの管理画面システムはPHP5.3で動き続けていました。
また、その社内管理画面はビジネスオペレーションの根幹となるものだったのですが、テストコードが存在しないレガシーコードになっていました。
当然の事ながら事業は成長し外部環境も変わり続けます。 それに伴いオペレーションも変化していくわけですが、このレガシーコードが改善の障害となり「あの画面はPHPで動いているので修正ができない」という認識になっていました。
このままでは、技術的負債がやがて事業成長のボトルネックになることが目に見えているので、このタイミングでレガシーコードからの脱却を決意しました。
状況と課題
システムの状況
このPHP製社内管理画面は、大きく2つに分かれていました。
- PHP 5.3のみで書かれたシステム
- symfony 1.4で書かれたシステム
1のシステムは1画面につき1つのPHPファイルが動作する非常にシンプルな構造でした。
それ故に1つの.phpファイル内に以下の処理がまとめて記述されているという代物でした。
- 直接DBに接続
- 生のSQLを発行
- 返ってきた値を加工
- HTMLでレンダリング
一方、2のシステムはsymfonyの作法に則ったシステムでした。
また、移行対象は合計50件(37画面、13バッチ)存在しました。
エンジニアのチームメンバーの状況
アルバイト事業部のバックエンドエンジニアは若手が中心でした。
その中にはPHPを扱った経験があるはいます。しかし長い時を経た結果、symfonyの開発経験がある人がいなくなりました。
また、社内管理画面がPHPでできているということ自体は知っているが、コードレベルで具体的にどのような処理をしているかを知る方はいませんでした。
そのため、特定の画面の処理の仕様が知りたい場合は、ステージング環境で画面を動かして把握することが最善であるという状況でした。
当時の私の状況
Ruby on Railsを使用した開発経験がキャリアの大半を占めており、PHPを使ったシステム開発経験はありませんでした。
また、先述の通り、このPHP製の社内管理画面が今後の事業成長のボトルネックになることが目に見えていたので、入社3週目の時に「年末までに全てRubyのコードに置き換えます」と目標設定しました。
6月15日が入社日だったのですが、その3週間目から作業開始し、年末までの営業日数を考えると、約2.4日に1機能をリリースしていかないと間に合わないペースとなります。
さらに、もし自分が若手だった場合「自分のキャリアにおいて今後使うことのないPHP5.3 / symfony1.4の知識をつけるのはあまり意味がない」と直感的に感じるだろうと思いました。
- 入社間もないため、ドメイン知識が0からの状態からスタート
- 50機能を2.4日に1機能リリースするスピードを半年間維持する
- チームメンバーにコードレベルで仕様を把握している方がいない
- チームメンバー(若手)に今後のキャリアにおいて必要性のない技術スキルを学んでもらうのは忍びない
このような状況でしたが、私はオペレーションの根幹を成すシステムの対半をRailsに移行することで、ドメイン知識を貯めるチャンスなのではないかとポジティブに捉え直しました。
また、チームメンバーの状況を鑑みると、比較的エンジニア経験が長い私がPHP/symfonyをキャッチアップして単独で遂行していくことが合理的であると判断し、プロジェクトをスタートすることにしました。
レガシーコードから脱却のコツ
対象システムの解像度を上げ切る
システムが大きく複雑であることや、言語やフレームワーク自体の知識が乏しいが故に、プロジェクト開始直後は分からないものが分からないという解像度が極めて低い状態でした。
その状況を打開すべく、一度冷静になり「対象と解決方法が明瞭か不明瞭か」に分けて考えることにしました。
- 対象が不明瞭、解決方法も不明瞭
- 対象が明瞭、解決方法が不明瞭
- 対象が明瞭、解決方法が明瞭
※対象が不明瞭で解決方法が明瞭なケースは理論上存在し得ますが、極めて限定的かつ、不確実性の高い解決方法になるため割愛します。
上記の通り、何をどこまでわかっているのかを大まかにカテゴライズし、全ての対象を3の象限に持っていくことができれば解像度が高まるはずなので、この方法でアプローチしていきました。
そのため、まずは自分は何が分かっていないのかを言語化とリストアップすることから始めました。
そして、その対象1つずつについて解決方法を導き出す期間と実際に取り組んでみることで全ての対象が「3. 対象が明瞭、解決方法が明瞭」となり、解像度が高まったといえる状態にしました。
簡単な一例を挙げると以下です。
- PHPとsymfonyのコードが読めないが故に仕様が把握できない(不明瞭な対象)
- PHPとsymfonyの書籍を購入し学習(解決方法)
- PHPとsymfonyのコードを脳内でRubyとRailsのコードに変換できるようになった(得られた結果)
- PHPのコードから仕様が把握できるようなった(得られた結果)
- 上記の状態を作り上げた上でコードリーディングを進め、特定の機能がどのような処理をしているのかが把握でき、コードから全体の仕様や難易度の高低が把握できた(即ち解像度が高まった)
- PHPとsymfonyの書籍を購入し学習(解決方法)
プロジェクト進捗を可視化してスケジュール管理をする
プロジェクトを進める上で進捗を管理 & 可視化し、それを対外的に示すことは重要です。
なぜなら、事業運営(連続性のある営み)において、限られた資源を効率的に配分し、ROIを考慮しながら収益を最大化する必要があるためです。
また、収益や再利用可能な資源を基に、事業を拡大再生産し続けることが企業経営において不可欠であると考えています。
そのためには、事前に綿密な計画を立てるとともに、計画通りにプロジェクトが進んでいるかを管理する必要があります。
特にソフトウェア開発においては、進捗を適切に把握し、「いつプロジェクトが完了するのか」「なぜその見通しが立つのか」といった問いに答えることが、計画の実行責任を果たしている証明となります。
このような進捗管理は、単に内部管理のためだけでなく、対外的な信頼を得るための重要な手段でもあります。
進捗の管理の手段は目的や用途によって様々ですが、ソフトウェア開発においては、ガントチャートとバーンダウンチャートは多くのプロジェクトで採用されている手法です。
また、どちらを採用した方が良いかはプロジェクトの特性に依ります。
今回のプロジェクトの特性は以下の通りです。
- 対象と解決方法を明確にしたものの不確実性は高く、計画変更が起こりうる
- プロジェクト初期のメンバー数は少ないが、増員することもできる
- 50機能それぞれ独立しているため、依存関係はほぼないと考えられる
そのため、進捗の可視化がシンプルかつリスクを早期発見/適応しやすいバーンダウンチャートとベロシティ計測による進捗管理の方法を採用しました。
こちらがプロジェクトで実際に使用していたバーンダウンチャートです。
実際に、10月中に進捗が悪化しはじめたタイミングでうまく業務委託の方のJOINが決まったこともあり、リカバリすることができました。
移行対象数を減らす
本格的にプロジェクトが動き出す前の調査段階では70機能(画面/バッチ)前後の移行が必要であることが朧げに分かっている状態でした。
また、実際に使用しているか曖昧な機能も存在することや、無理にRailsで作る必要もないほど簡易な作りの画面も存在していました。
そのため、これらを整理することで移行不要なものが出てくるだろうと仮説を立て、1つずつ整理することにしました。
具体的に行ったことは以下の通りです。
- 対象画面の移行要否を判断をする
- 画面の中からさらに機能レベルで移行要否を判断し削ぎ落とす(例: 一覧画面においてCSVダウンロード機能は不要など)
- 必要な機能と判断されたものでも、コードリーディング中に不要と思われる処理がある場合は都度確認し、手数を減らす
- 簡易な画面は代替案を示す。
- SQLのSELECT文の結果を表示しているだけの画面はBIツールで見てもらうことにするなど
上記を整理しきった結果、当初70前後移行しなければならないと思っていたものが、50にまで減らすことができました。
30%弱も減らすことができ、相当インパクトがあったと振り返っています。
この作業は到底エンジニア単独で行えるものではなく、社内管理画面を実際に使用する非エンジニアの方に協力していただく必要があります。
また、一度必要と判断されたものでも、実際のユースケースをヒアリングをすると実は不要であったり、粘り強く代替案を示しながら移行要否判断を仰ぐことが非常に重要でした。
まとめ
今回の記事では、創業時から続くレガシーコードの脱却に取り組んだプロジェクトについて、その背景、課題、そして具体的な対策を紹介しました。
PHP 5.3やsymfony 1.4といった古い技術が扱われていたことや、コードレベルで仕様を把握している方がいなかったため、当初は不確実性が高く困難な状況も多々ありました。
- 対象と解決方法の明確化
- 進捗の管理と可視化
- 移行対象の削減
しかし、これまで述べた上記のアプローチを通じて、どうにか全て移行することができました。
本プロジェクトの成功は、技術的課題に対するアプローチだけでなく、エンジニアチームの協力や、非エンジニアの方々との連携があってこそ実現できました。
また、これまでリブセンスに所属していた数々のエンジニアの方がこのレガシーコードと格闘していたことは、コミットログから分かりました。
組織的に継続して取り組んできた改善の積み重ねがあったからこそ、最後のレンガを積むことができました。
この場を借りてそのご尽力にあらためて敬意を表します。
この記事が、同様の課題に直面している方々にとって少しでも参考になれば幸いです。
*1:2017年にサービス名をジョブセンスからマッハバイトに変更しました。