「可視化からはじめる開発生産性向上への道のり」Qiita Conference 2023 Autumnイベントレポート
昨今では、コードの品質などを指標にチームの能力を測る「開発生産性」を意識するエンジニアが増えてきました。チームや個人の開発生産性を高める方法は、展開する事業や取り扱うプロダクトにより異なるものの、現状を可視化することが鍵となります。
2023年10月に開催した「Qiita Conference 2023 Autumn」では、わずか2年間でメンバー1人あたりの開発生産性を約3倍に向上させたファインディ株式会社 エンジニアマネージャ 浜田 直人 氏とフロントエンドエンジニア/テックリード 新福 宜侑 氏をお招きし、開発生産性向上の秘訣を解説いただきました。本記事では、その一部をご紹介します。
前半ではファインディでの開発生産性の考え方を浜田氏に、後半ではフロントエンドにフォーカスした具体的な内容を新福氏にお話しいただきました。
プロフィール
フロントエンドエンジニア/テックリード
エンジニアマネージャー
開発生産性を向上させるために、ファインディが重視する2つの指標
浜田 : 簡単に経歴を紹介しますと、新卒でSIerとして就職した後にWeb系企業やスタートアップ企業を経て、2022年5月にファインディ株式会社に入社しました。以降は「Findy Team+」というプロダクトを開発しながら、EM(エンジニアマネージャ)として開発チームのマネジメントも行っています。
本題に入る前に、プロダクトの紹介もさせてください。私が担当しているFindy Team+はGitHubやGitLabのコード管理、Jira Softwareのイシュー管理のデータなどを連携して、プルリクエストやレビューのリードタイム、Four Keys、イシューのリードタイムなど、様々な切り口から開発生産性を可視化できます。
開発生産性を可視化することによって、開発プロセスを改善しやすくなったり、文化づくり・自己組織化もしやすくなったりといったメリットが得られます。
また、開発生産性向上のサイクルを継続的に回し続けられる点もメリットと言えます。開発生産性が向上することで事業開発スピードが加速しますし、昨今では開発生産性の高い組織で働くことを希望するエンジニアが増えてきているので、採用面でも開発組織としてのブランディングに役立つでしょう。
浜田 : Findy Team+では「Findy Team+ Award 2023」というオフラインイベントを2023年10月19日に開催しました。このイベントでは、Findy Team+にて組織の開発生産性を可視化します。「開発生産性スコア」*¹において特に優れている企業や、多様な観点から開発生産性が高いと判断されたチームを表彰するイベントでして、当日は受賞した企業を中心に多くの方にご参加いただき、非常に盛り上がりましたね。
*¹開発のアウトプットやリードタイムなどをもとに、ファインディが独自にスコア化
このイベントは1年ぶり2回目の開催でしたが、1回目と比較しても開発生産性を高める取り組みが広がるなど、レベルが高くなっていることを実感しました。開発生産性向上の手助けとなるプロダクトを開発している私自身も刺激を受けました。
今回はQiita Conferenceということで、個人的にQiitaを愛用しているので、そのお話も少しさせてください。Qiitaには、2023年10月25日時点で96本の記事を投稿しています。本題でも触れますが、最近は「開発生産性」に興味があるので、その記事をよく書いています。
2023年、一番いいねがついた記事は「本当にあった開発生産性が爆下がりする話」でした。意外にも、開発生産性が上がる記事ではなく下がる記事が読まれました。この記事には451いいね(2023年10月25日時点)もついているので、皆さん興味を持たれているようですね。
ただ、今回は開発生産性が下がってしまった事例を持ち帰っていただいても有効活用できないと思うので、開発生産性を向上させるポイントについてお話します。
私からは「開発生産性を測る指標」と「ファインディが開発生産性を向上させるために重視している指標」の2点を紹介します。
「開発生産性を測る指標」と言われたら、皆さんは何を思い浮かべますか?
コード行数による開発生産性の管理を連想する方もいるのではないでしょうか。一昔前、開発生産性はコード行数で管理されることが多かったと認識しています。
コード行数で管理する場合、「目標1日500行!」「隣のチームは1日800行」「隣のチームと同じ行数を書けないのか」と行数をもとに比較されてしまうため、ともすれば本質的ではない改善策を選んでしまうこともありました。
例えばコード行数をかさ増ししたり、長時間労働でカバーしたりするといった方法です。
また、ノルマを達成するために、わざわざコード行数が増える書き方をしてしまうこともあったでしょう。「三項演算子ではなく、if文で書いたら3行になるので生産性3倍だ!」というように、コード行数を指標にすると本質的な改善はできません。
浜田 : そもそも、開発生産性はコードの行数だけでは測れません。同じ1行でも内容によって重みがまったく異なることは、コードを書く方なら理解できると思います。
今回お伝えしたい「開発生産性を測る指標」は、Four Keysです。開発生産性が高い企業のデータを集めて分析し、これらの開発チームの特徴を定量的に示した、フォースグレン・ニコール・Ph.D. ほか著(武舎/広幸ほか訳)『LeanとDevOpsの科学』でも、Four Keysが取り上げられています。
2023年版のFour Keysは①本番環境へのデプロイ頻度、②変更のリードタイム、③変更障害率(デプロイにより本番で障害が発生する確率)、④平均復旧時間(本番での障害から復旧に要す時間)という4つの指標からなり、それぞれの項目をEliteからLowまでの4段階で評価します。
浜田 : また同書では、「開発生産性が高い企業は、従業員満足度も高い」ことも触れられています。
先ほども述べた通りコード行数による管理方法だと、コード行数がまるでノルマのように従業員に課せられてしまう側面がありました。しかし、Four Keysによる評価方法だと従業員満足度を高められることから、ボトムアップで従業員の労働環境を改善することにもつながるでしょう。
ファインディでも、開発生産性を評価するための指標としてFour Keysを重視しています。なぜなら、チームのデリバリーパフォーマンスを可視化できるためです。
これにより品質を維持しながら、顧客に対して迅速に価値を届けられるかどうか定量的にチェックできます。またDevOpsのプラクティスを適切に取り入れることで、Four Keysの値が良くなるので、取り組みの善し悪しも定量的に確認できます。
Four Keysの値が高いと、顧客への価値提供も速くなります。ファインディの場合、平均して20時間以内でコミットが本番環境に反映されています。そのため、小規模な変更であれば当日中、あるいは翌日には本番に反映されるようなスピード感で開発できます。
また、ファインディでは障害が比較的発生しづらく、発生してもすぐ解決できる点も特徴的です。変更障害率はEliteでも約5%にとどまっています。1回のパッチサイズが小さいため、変更に起因する障害が発生しづらいですし、発生したとしても対応完了までの時間も速くなっています。障害が発生しづらいがために変更への心理的安全性が高く、価値提供を高めるチャレンジがしやすくなるメリットを享受できています。
ここから言えることは、一定数の障害が起きることは問題ではなく、いかに早く障害を検知して復旧するかが重要だということです。プロダクトの性質にもよりますが、「デプロイは絶対に失敗できない」という前提で進めると、心理的な負担が大きくなってエンジニアがチャレンジしにくくなってしまいます。スピードと品質のバランスを取り、デプロイをカジュアルに行うことが大切です。
また、Four Keysに加えて「プルリクエストの作成数とマージするまでの時間」も重視しています。なぜなら、Four Keysだけでは不十分だと感じているからです。Four Keysはチームのパフォーマンスを測るのに適していますが、個人のパフォーマンスを測る指標としては適していません。また、結果の指標であるために改善結果が反映されるまでにタイムラグが生じてしまいます。
一方でプルリクエストの作成数とマージまでの時間を指標とした場合、チームと個人両方のアウトプット量やスピードを把握できるうえに、改善結果がすぐに反映されます。パフォーマンスの高いエンジニアを周りが真似しやすい点もメリットです。例えば、ロールモデルの数値をベンチマークとして目標に設定することで、ロールモデルに近づくための道すじを定量的に把握できます。
また、プルリクエストの作成数およびマージまでの時間を改善することで、結果的にFour Keysにおけるデプロイ頻度やリードタイムの改善にもつながるでしょう。
浜田 : プルリクエストの粒度が小さく、マージまでの時間が速いと開発がサクサク進みます。ファインディでは、1人あたり1日で3プルリクエストを作って、ほぼ当日中にマージしています。
驚くかもしれませんが、本番で使われなくても既存の環境に影響がなければ積極的にmainブランチにマージしていくことで、このスピードを保っています。
さらにレビュー時間が短く、手戻りが少ない点も特徴です。プルリクエストあたりの平均行数は200行と小さいので、レビュアーの負荷が軽減されて素早くレビューできます。レビュー依頼からレビュー完了までの時間は平均3時間です。また、平均10時間以内にマージできるので、コンフリクトはほぼ起きません。
プルリクエストの粒度が小さく、マージまでの時間が速い開発はかなり快適です。半信半疑の方もいるかもしれませんが、騙されたと思ってぜひ1度試していただければと思います。
ここからはファインディのフロントエンドで開発生産性向上のために行った具体的な改善策を、新福から紹介してもらいます。
「時間がないなら作ればいい」ファインディによる開発生産性向上の取り組み
新福:ファインディ株式会社にて、フロントエンドのテックリードを務めている新福です。今回はファインディで行っている、開発生産性向上への取り組みについてお話しします。
Findyの直近のアップデートで、バッチ機能がリニューアルされました。また、ファインディでは開発生産性をテーマとしたイベントを多数開催してきていますが、いずれも好評だったことから、エンジニアの間で開発生産性への関心が高まっていることがうかがえます。
新福:このようなイベントを主催するファインディ自体の開発生産性はどうなのか気になる方も多いのではないでしょうか。結論から言えば、国内トップクラスにあると自負しています。
下図は直近1年間のフロントエンドのリードタイムとプロジェクト数を表しています。可視化ツールは、先ほどご紹介したFindy Team+がおすすめですね。
新福:まず見ていただきたいのは、リードタイムです。プルリクエストがオープンされてからマージされるまでの平均値は4時間ほどとなっています。1日の営業時間が約8時間とすると、当日中にマージできる計算です。
続いて、プルリクエストがオープンされてからレビューされるまでの平均値は約2時間。この時間も速ければ速いほど高評価です。今後は2時間を切るように改善していきたいですね。
先ほどお伝えしたように、「プルリクエストの粒度が細かい」という特徴があるので、レビューにかかる負担を抑えられます。最近ではプルリクエストが安定してきたので、10件以上扱えるようになりました。開発のサイクルを高速に回せています。
このように、現在は高い開発生産性を実現できていると言えますが、最初からこの数字を記録できていたわけではありません。様々な課題がありました。下図は2020年、今から3年前のデータです。
新福:当時はRuby on Rails のモノリスだったので、フロントエンドとバックエンド両方のデータが入っている点にご注意ください。
当時の状況に「このチーム大丈夫か?」と思われる方もいるでしょう。リードタイムに1週間近くかかっていたので、顧客に届けられる価値は限られていました。レビューが放置されたまま6日経過していたり、プルリクエストも1日に1〜2個しか処理できなかったりと、まったくスピードを出せていませんでした。
加えて、技術面では当時のFindyのフロントエンドは先ほどもお伝えしたようにモノリスだったので、ちょっとした変更でも長いCI(Continuous Integration)待ちが発生しますし、バージョンの古いツールライブラリが多く放置されていました。テストが無く、設計に課題を抱えていたので改修すら難しかった状況です。
そのような状況を打破し、開発生産性を向上させるためにまず取り組んだのが、「モノリスの解体」です。このとき、バックエンドはRailsのAPIモードで動かして、フロントエンドはNext.jsで再実装しました。全体で3ヵ月ほどかかったと思います。
思いきった判断ではありましたが、開発スピードは大幅に改善されました。詳細はファインディのCTOがnoteにまとめていますので、ぜひご覧ください。
現場ではフロントエンドとバックエンドで独立して動けるようになったので、軽微な改修なら即日で対応できるようになりました。モノリスの解体で大きなボトルネックは解消できましたが、まだ改善できることは残っています。
続いて取り組んだことが「技術的負債の返済」です。依存ライブラリのアップデートと、サポートの切れたライブラリの削除を行いました。Dependabotなど、自動化の仕組みもこの時点で導入できるといいですね。
モダンな言語、モダンな開発環境に順次移行し、開発基盤はNxを採用しました。Nxは標準でJestやESLintなどのツールと統合されており、開発環境もすぐに備えられるので一押しのツールです。
新福:続いて、「コンポーネントの設計刷新」を行いました。既存のコードはContainer ComponentとPresentational Componentというよくあるパターンで組まれていたので、それを活かしつつ、URLやAPI、フォームといったデータの流入に合わせた階層を用意して、それぞれにComponentとカスタムフックのセットを用意しました。一番大事なのは、依存の方向性をそろえることです。
テストは、イベントテストを中心に書けそうな部分から着手しました。テストを書くと、先ほどの設計にも効いてきます。「テストしやすいように設計を改善する」というモチベーションが高まりますから、最終的にモジュールが疎結合になっていくためです。
ちなみに、Wallaby.jsなどのツールも導入しています。これを使えばエディター上に、テストの実行結果をリアルタイムに共有してくれます。
これでモノリス解体、技術的負債の返済、開発環境の刷新が完了しましたが、まだ終わりではありません。新たな壁は「CIの待ち時間」です。機能追加やテスト拡充をするにつれて、CIの時間が延びてきました。
CIが遅いとレビューを後回しにしがちですし、レビューが遅いとコンフリクトが発生する確率が高くなります。過去にはFindyがCIを完了するまでに約20分かかることもありました。
そして、ようやくコンフリクトを解決しても、プッシュしたらまた20分待たされるので、とても開発を進められません。
今年実施したアンケート(下図)では、時間に関して興味深い結果が得られました。
新福:多くの方が開発生産性の向上に課題を感じつつも、「工数が足りず進まない」と悩まれているかと思いますが、時間が足りないなら作ればいいのです。開発生産性を向上させるための取り組み、3つ目は「CIの高速化」です。
CIの高速化で行ったことは、「変更検知」と「キャッシュ活用」です。変更したファイルの影響範囲でのみ指令が実行されるようにした後は、実行結果のキャッシュを残してCIを高速化します。この方法によって、1回あたりのCIにかかる平均時間が約5分となり、毎月300時間以上も工数を削減できました。ファインディでは、変更検知とキャッシュ活用の2つを実現するためにNxを活用しています。
これまでの取り組みで、どこまで私たちが生産性を改善できたかをお見せします。これは2021年4月から測定した、フロントエンドのGitHub上でのアクティビティの変化を示しています。
新福:これはモノリス解体以降のデータになるので、2020年以前のデータは割愛しますが、順調に上がってきていることが読み取れます。もちろん当時と比べてメンバーの数も増えたので、「メンバーが増えたから当然ではないか」と思われるかもしれません。ただ、ここで注目していただきたいのは、メンバー1人あたりのアクティビティが約3倍になっている点です。つまり、単純計算でも開発生産性は3倍になっています。
最後に要点を整理します。ファインディでは、3つのことを実施して開発生産性を向上させました。モノリスの解体、コンポーネントの設計刷新、CIの高速化です。
細かなことになりますが、日々改善することが大切です。例えば、技術的負債は一度返済して終わりではなく、継続的に改善する必要があります。技術的負債を溜め込まないように常日頃からアップデートしたり、テストを書いたり、プルリクエストの粒度を細かくしたりして、開発を高速に行えるように心がけましょう。それが開発生産性を高めることにもつながります。
弊社のテックリードによる入門書(開発生産性 実践入門)もありますので、ご興味のある方はぜひ参考にしてください。
文:ノーバジェット