レガシープロダクトをリファクタリングするために単体テストを整備
「プロダクト開発部門に配属されてから取り組んで来た開発環境の改善の話をしたいと思います」
冒頭でこう語り、寺尾氏のセッションは始まった。
寺尾氏は2019年4月に新卒でWorks Human Intelligenceに入社した後、プロダクト開発部門に配属され、1年間、開発環境の改善に取り組んできた。2020年12月より半年間の育休を取得した後、現在はDXエンジニアとして、開発部門全体のDX改善チームの立ち上げに参画している。
Works Human Intelligenceが開発する「COMPANY」シリーズは大規模なソフトウェアだ。「20年間保守しており、ソースコードは数百万規模。それを5~10人からなる、オフショアを含めた複数のチームに分かれて開発している」と寺尾氏は説明する。40~50人の開発者がソースコードを共有して開発しているのだ。
このような大規模プロダクト開発に携わった寺尾氏は、「ソースコードが大規模かつ依存関係が複雑」「ビルドやサーバ起動などに時間がかかる」「テスト自動化が難しく手動テストに頼らざるを得ない」などの問題により、つらさを感じていたという。だが「これらのつらさの原因は、レガシープロダクトだったから」ということに気づいた。
そこで大規模プロダクト開発を楽しくするために、寺尾氏は「脱レガシー」に取り組むことにしたという。
「まずはモノリス分割が必要だと考えた」と寺尾氏。モノリス分割とは全体が複雑に絡み合っている1枚岩の状態から依存関係を分割することだ。こうすることで、開発体制も変わる。
「共有していたソースコードがチームごとに分割されるので、独立したチーム開発が可能。モジュール間の依存関係がシンプルになり、ビルドも高速になる。またチームごとに趨勢するモジュールが独立しているため、責任範囲が明確になり、どこに修正すべきがわかりやすくなる。そのためチーム間の協調も最小限になる」(寺尾氏)
モノリス分割をするために必要になるのが、システムの振る舞いを変えずに内部構造を変えることができるリファクタリングである。リファクタリングをするには、正しい振る舞いであることを保証することが必要になるが、レガシープロダクトでは正しい振る舞いが明確ではない。またそれを保証するのに必要なテストの工数が確保できなかったりするからだ。
いきなりリファクタリングを行うのではなく、そのための第一歩として、「プロダクトコードに単体テストを整備することから始めた」と寺尾氏は言う。
単体テストの整備に乗り出したのは、新卒で配属された2年前の2019年。当時の開発環境について寺尾氏は「セットアップに時間がかかる、コードレビュー時に自動チェックがなく、ビルドが不安定など、問題が山積し、どこから手につけたら良いか分からない状態だった」と振り返る。
そこで「まずはモダンで快適な開発環境の整備しようと思った」と寺尾氏は続ける。具体的には開発者全員が共通の設定のIDEを利用したり、ファイルの編集のたびにフォーマッタやLinterを実行したり、コードレビュー時にビルドやフォーマッタ、Linter、単体テストの自動チェックを行い、その結果をすぐ確認できるように整備していったという。
その際に「快適に仕事ができる仕組みにもこだわった」と寺尾氏。例えばIDEのセットアップの自動化や、自動チェックに時間がかからないよう、実行時間の目標値を設定したり、自動チェックの誤検知が少なくなるような対策を施したりしたという。
しかし「1年かけてモダンで快適な開発環境が整備できたのですが、これだけでは脱レガシーはできませんでした」と寺尾氏は語る。なぜなら単体テストの数がなかなか増えなかったからだ。寺尾氏はその理由を探るため、JUnitダッシュボードで可視化、分析したという。こうすることで、どの部署でテストが書かれているか、概ね把握できたが、「テストを書いていたのは一部の部署だけで、残りの大部分の開発者は単体テストを書いていなかった」と言う。その背景には「単体テストを書いてもE2Eテストもするので、二度手間では」「単体テストをどういう観点で作ればよいかわからない」「データベースがないと動かないテストが多すぎる」などの理由があったという。
当時の開発チームの状態は、「単体テストをどう書いていいかわからない」「習得する時間も無いから今回は手動テストでいいかな」という考えの人が多く、単体テストが書ける人はほんの一握り。中でもレガシーコードに単体テストが書ける人はほとんどいなかったという。多くの人が単体テストを書けず、メリットも感じられていなかったのだ。そんなチームの状態で、いきなりレガシーコードに単体テストを書くのはハードルが高い。
単体テストの数を増やすために、研修を企画
寺尾氏は今後追加される新規コードにテストを書いてもらうことから始めることにした。
そのために寺尾氏が企画したのは、「JUnit dojo」というオンラインハンズオン形式の研修コンテンツ。1回30~60分という限られた時間で10~20名ごとに実施し、合計40人の開発者が研修を受講した。
まず、JUnit dojoマインド編としてt_wada氏の「TDD Boot Camp 2020 Online #1基調講演/ライブコーディング」の鑑賞会を実施。次にJUnit dojo基礎編として単体テストの基本的な書き方を習得するハンズオン形式の研修を行った。
この2つの研修を実施したことで、単体テストのメリットを理解し、新規コードに単体テストを書く人が増えたという。だがそれでも脱レガシーはできなかった。なぜならレガシーコードに対して単体テストが書けなかったからだ。
「リファクタリングを実施するにはテストが必要だが、テストを書くためにはリファクタリングが必要」というレガシーコードのジレンマを克服するための方法論として、寺尾氏が新たに企画したのがJUnit dojo実践編。これは、レガシーコードに単体テストを書くための実践的なスキルを習得するための研修だ。「研修内容が比較的高度になるため、全員を対象とするのではなく、各チームから1~2名を募って実施しました」(寺尾氏)
そして受講した人にJUnitのエバンジェリストになってもらい、各チームにレガシーコードの単体テストを書くスキルを広めてもらうことにしたのだ。この研修用コンテンツはGitHubで公開されている。興味のある人はぜひ、チェックしてほしい。
実践編を実施したことで、レガシーコードにも単体テストが書けるという認識ができ、「気軽に単体テストにチャレンジする人が増えてきた」と寺尾氏は語る。
開発者の意識が変わったことで、開発組織にも次のような変化が起こった。dojo参加者が講師役となり、JUnit dojoの再放送が行われたり、単体テストの勉強会がチームで開催されていたり、単体テストを書きやすくするための共通モックが整備されたりしたという。さらに他プロダクトまで噂が広がり、単体テストの環境が各プロダクトに整備され、実務で単体テストを書いていく定期的な活動「JUnit部」が発足した。開発者からも「テストを書くのが楽しい」「リファクタリングできそう」「JUnitでテストを書くことで、問い合わせの回答がしやすくなった」など、嬉しい声がたくさん寺尾氏の元に届いているという。
単体テストを書く人が増えていることは、数値でも明らかとなっている。「JUnit部が発足したことで書く人が増え、現在は月150件超えるペースで単体テストが作成されている」(寺尾氏)
現在のWorks Human Intelligenceの開発組織は、単体テストを書くのはもちろん、その上でロジックをリファクタリングすることも当たり前のように行われるようになっているという。
「当社のプロダクトはソースコードが数百万行と巨大なので、全コードに単体テストを書くことは難しい。だが、戦略的にテストを書いていくことでリファクタリングが進んでいくと考えている。時間はかかるが必ず脱レガシーを達成し、変化に強い製品開発体制を整えていきたい」
最後にこう力強く語り、寺尾氏はセッションを締めた。