こんにちは。Raspberry Pi4でようやくギガビットLANにネイティブ対応したことにテンションが上がっているBacklog開発チームの佐藤です。
ヌーラボでは2015年11月から2019年の7月まで、BacklogをJavaからScala / Play Frameworkに移行するという大規模なリプレイスプロジェクト(以下、Play化プロジェクト)を行っていました。
私は2017年の夏からプロジェクト完了までこのプロジェクトに参加していました。
今回の記事では、Play化プロジェクトに途中参加した立場で、プロジェクト中に起きた出来事と当時の心境、問題をどう乗り越えたのか、反省と教訓についてもお届けします。
目次
プロジェクトに参加する前は何をしていたか
出来事:Backlogの機能改善チームからPlay化プロジェクトチームへ移動
心境:不安だがトップダウンで決まったのではなく、自分自身の意思決定だったので覚悟ができた
Play化プロジェクト以前は、主にBacklogのバグや細かな機能改善をするチームに所属しており、半年間ほどそのチームでバグ修正をしていました。
2017年の7月の終わり頃に、私が所属しているチームからPlay化プロジェクトのチームに数人異動させたいという話があり、チームで議論した結果、私ともう1人がPlay化プロジェクトへ参加することになりました。
「あまり知らない環境に行く」というのは多少不安がありましたが、Play化プロジェクトによってBacklogの内部構造が大きく変わるので、どうせなら早いうちに理解できていた方がいいだろうという気持ちで手を上げました。
トップダウンで誰が異動するのかが決められるのではなく、チーム内の相談によって決まったので、この点は心理的不安も少なくてよかったと思います。
プロジェクトに参加したタイミングの開発状況
私が参加したタイミングは、上記の図の一番上(2017年の真ん中あたり)のダッシュボードをJavaからScalaへ置き換え(以下、置き換え)が完了しているタイミングでした。そして、Backlogの主要機能の1つである「課題」まわり、つまり課題の詳細と課題の追加などをこれから置き換えよう、という状況でした。
上記の図の一番上に書かれている機能をご覧いただくとわかるとおり、ダッシュボードはプロジェクトの一番最初に置き換えられた機能です。ダッシュボードは様々な情報が表示される画面であるため、置き換えができているということは、Play化に関して最低限の足回りは固まっていると言えました。
このあと幾度となく発生するバグ発見によるScalaからJavaへのロールバックも、ダッシュボードに関しては私が体験することはありませんでした。
最初にやったこと
出来事:チームビルディングと移植方法をレクチャーされた
心境:手探りで実装を開始するも疑心暗鬼でコードを書いている
チームに加入して最初に移植したのはプロジェクトの設定画面でした。移植する画面の中では比較的内容が単純で書きやすいという理由からです。
コードを書き始める前に、既存メンバーからアーキテクチャや設計思想、移植をするときはどのような流れでコードを書いていくか、軽くレクチャーを受けて、実装を開始しました。
もちろん今まで触っていたJava版Backlogとは何から何まで違うので戸惑いはありましたが、お手本となる既存コードを見つつ、見よう見まねで移植作業を進めていました。
対策:チームメンバーからのレビューで不安を解消
このころは「これで良いんじゃないか?」という感覚すらなかったので、作業途中のコードを時々チームメンバーに見てもらっていました。これをすることで「このまま進んでも良いのか、それともこのやり方は間違っているのか」を定期的に確認でき、手戻りの軽減と精神的不安を減らせました。
定期的な確認はメンバーに頼んで自主的にやっていましたが、この方向性で良いんだと都度確認ができて、迷いなく進めるのでよかったと感じています。
実装”は”割とスムーズに進む
出来事:チームメンバーとして移植を進行させる
心境:悩むこともあるけど思ったよりはスムーズにできた
上記の設定画面の最終プルリクエストのレビューが終わり、無事にmasterブランチに取り込まれたあとは、移植に対する自信もある程度ついていたのでどんどん移植作業を進めました。
作業をガシガシ進められたのは、「作業途中のコードを時々チームメンバーに見てもらう」ことでどう書けば良いか、ある程度掴めてきたこと、お手本となる既存実装があったこと、Scala版Backlogのアーキテクチャによりコードの見通しが良かったことが大きいです。
対策:ガントチャートを移植するときの障壁
一方で、もちろん、既存実装にないトリッキーなことをやることもあり、そのときは悩んだことも事実です。
例えば、ガントチャートを移植する際に、初期実装ではすでに整備されたインフラ・ドメインをできる限り活用して実装を試みました。しかし、ガントチャートで必要な課題の取得条件が複雑で、内部メソッドの呼び出し回数が多すぎて時間がかかりました。
結局、ガントチャートは書いていたコードを捨て、一から整備して実装し直すことを決めました。
「これでいいのかな?」と思うことは時々ありました。順風満帆に進めたか?と聞かれれば答えはノーですが、迷ったらメンバーに聞いたり、書いたコードを見てもらいアドバイスをもらったりすることで解消しました。「最終的にはプルリクエストでのレビューもあるのだから、手が止まるよりはえいやで書いていこう」と思えました。
チームメンバーに意見を求めたりアドバイスを受けやすいチーム状況でなければ、ここまでスムーズに行くことはなかったです。
問題は運用とバグ修正
出来事:規模相応のバグ修正に追われる
心境:移植ほどスムーズに直せないため不安がつのる
しかし、途中参加者(つまり私)にとって苦労を強いられたのは実装ではありません。
Play化プロジェクトはBacklogのほぼすべてを置き換える長期的かつ大規模なプロジェクトでした。当然それ相応のバグも出ていましたが、このバグ修正が私にとって苦労でした。
「バグ修正」と言ってもバグ発見から修正までの流れは主に2種類ありました。1つ目は、テスト環境やローカル上のBacklogですでにバグの発生手順まで確認できているもの、2つ目に、ログからバグらしき挙動を探し出してそのログをもとにバグを修正する、というアプローチです。
私が苦労したのは後者のバグ修正でした。
対策:ログからバグを洗い出す
移植作業である程度アーキテクチャや構造を理解できたとはいえ、まだまだ浅い理解にしかすぎず、チーム参加直後は「このような処理をしている、この値を作っている処理がどこかにあるはず。でも、どこにあるのかはわからない」「おかしいのはわかるけど、どこにバグがあるのか想像もつかない」という状態に頻繁に陥っていました。
他のメンバーがバグを修正するよりも手間も時間もかかってしまったり、どうしてもわからないものは他のメンバーに修正をお願いしたりすることも稀にありました。
また、リリースやデプロイ作業はまだまだ勝手がわからず、一つの手順ごとにチャットツールでメンバーと相談しつつ、不安な時はGoogle Meetで会話しながら作業を進めていました。
慣れることである程度まで問題を解決できました。リリース作業に関しても、急ぎでリリースしないといけないもの以外は徐々にリリースをしていき、そのうち急ぎのリリースにも着手できました。
ログを探りながら取り組むバグ修正もリリース作業も“ある程度時間がかかることをチームが事前に認識していれば” 問題はあまりありません。
しかし、チームが時間をかけることを許さない状況にいる場合があります。今回のPlay化プロジェクトは「サービスを提供しながら移植プロジェクトを進める」という関係で”時間をかけることを許さない”という状況でした。それが次の問題に繋がります。
知識の共有が進みにくい
出来事:バグ修正の依頼が特定の人に集中する
心境:(ある機能)のバグ修正よく○○さんがやってるなあ
インフラやデータベースに近い部分のコードで不具合が発生したときは、そこを実装した、プロジェクトの初期メンバーに対応をお願いしていました。そのようなコードは不具合の影響範囲が広く、早急な問題解決が求められたためです。
そのため、途中参加者である私には、アプリケーションレイヤーに近い部分の知識/経験は溜まっていく一方で、インフラやデータベースに近い部分の知識/経験はなかなか溜まりませんでした。
また、アプリケーションレイヤーにおいても、実装した人にその後の対応を任せきりにしてしまって知識の共有が進まない部分がありました。
反省:知識の共有が進まなかったことへの考察
その理由はいくつかあると思うのですが、私の感想としては、Scala版Backlogはアーキテクチャ・構造上、移植時の画面ごとの分業が極めてしやすいために、分業が進みすぎてしまったのではないかと考えています。
もちろん、Playチームでもプルリクエストのチーム内レビューはしていました。しかしそれだけでは知識の共有には十分でなく、バグ修正などは、そのコードに詳しい実装者に任せがちになってしまっていました。
振り返って考えてみると、情報共有を進めるために、時間的猶予があるバグ修正についてはペア/モブプログラミングで修正するアプローチを取ればよかったのではないかと思います。
プロジェクトを通して
このプロジェクトをやりきってみて、途中参加者として感じた点をあげるなら
- 進行途中のプロジェクトに実装やスピーディなバグ修正が要求されるコアメンバーとして途中参加した場合、その人が自走できるまでにかかる精神的/時間的コストは大きい
- アーキテクチャや実装方法次第では何らかの仕組みを用意しないと知識の共有は思ったようには進まない
の2点です。
それぞれの解決法として「これ!」といったものは無いとは思いますが、あげるとすれば
- そのプロジェクトの成果物(このプロジェクトの場合はScala版Backlogのコード)に将来的にチーム外の人が触れる可能性があるのならば、時間的猶予のあるバグ修正をやってもらうなど、成果物を知る機会を作りあらかじめ慣れてもらう
- ペアプロやモブプロでコーディングし、複数人がコードの中身を把握できるようにする
でしょうか。
教訓:長期プロジェクトに途中参加したときの負担は予め覚悟する
Backlogチームでも、プロジェクト終了後になってしまいましたが、移植チーム主導でScala版Backlogについての勉強会を開催したり、アーキテクチャや構造をまとめた資料などを作成するなどの取り組みを行なったりしています。
理想はプロジェクト発足時にアサインしたメンバーでプロジェクトを完了させることですが、小さいプロジェクトからスタートしたはずが、いつの間にか大きいプロジェクトになっていたり、プロジェクト開始前に見積もった工数よりオーバーすることがわかったりと、途中で人員を追加することはあるかと思います。
その場合、ある程度の期間、途中参加者はもちろん、もともと居たメンバーに負担がかかること、途中参加者が自走できるようになるまでハードルを下げることは可能な一方で、時間がかかることを覚悟するべきだと感じました。
今回の私の経験が同じような状況に直面した方の参考になると幸いです。
■ Play化プロジェクト連載一覧
Play化プロジェクトメンバーが執筆した他の記事もぜひご覧ください。
- 時系列でみる!4年の歳月をかけてPlay Frameworkで「大規模リプレイス」した話
- 開発チームが大規模リプレイスを成功させるために取り組んだ “7つの取り組みと反省”
- Backlogのコードメンテナンス性を向上させるために気をつけたこと
- JVM上で動くWebアプリケーションがリソースを食いつぶす原因を探るためにやったこと
- SREは大規模なリプレイスプロジェクトで発生した様々な問題にどう取り組んだか
- 長期プロジェクトを効果的に “ふりかえる”ためにBacklogチームでやったこと
こちらもオススメ:
プロジェクト管理とは?目的や項目、管理手法について徹底解説! | Backlogブログ
プロジェクト管理の基本や主な項目を紹介。CCPMやWBSなどのプロジェクト管理の代表的な手法やプロジェクト管理全体の流れを解説。これからプロ…
backlog.com