ご挨拶
techtekt アドベントカレンダー2021 20日目です🎄✨こんにちは、2021年9月に入社した岡部です。
今回は、コードメトリクスというものを使って設計改善を行なったので社内で共有しようと思ったのですが、せっかくいいタイミングですのでアドベントカレンダーに公開させていただきます。少しでも参考になれば嬉しいです!
ここでいうコードメトリクスとは
一般的には弊社が開発するようなソフトウェアに対して、その性質を定量的に計測する手法を指します。今回は特に内部品質についての数値を測定して改善点を調べてみました。
少し前に出版された、「ソフトウェア品質を高める開発者テスト アジャイル時代の実践的・効率的なテストのやり方」という書籍で紹介されていた考え方が良いと思ったので使っています。
この書籍はその後のリファクタリング方法まで紹介しているのですが、今回はそこまでは頼らず自分たちの目で見て改善策を検討しています。
具体的に何を計測したのか
弊社で開発しているHR Spannerという企業ではたらく従業員さまの職場定着をサポートするサービスのバックエンドで、各ソールファイルを対象に下記2点を計測しました。この2つともが高いファイルが要注意、ということになります。
- 循環的複雑度
- 関数やメソッドごとの複雑さ(乱暴に言えば判定の多さ)を計測する。SonarCloudというコードの静的解析を行うSaaSを使って収集しました。
-
ファイルごとにその中のメソッドの値を足しあげて合計値を求めます。
-
ホットスポット
-
Google社で使われているとされるバグ予測アルゴリズム。ある期間、特に直近で多く変更されたファイルでバグが起きる、というシンプルな考え方。
-
今回は単純にGitのログからファイルごとの変更コミット数を取得しました(直近の分への重みづけがない)。
-
少し調べたところ、シンプルに"git log --pretty=format: --name-only | sort | uniq -c | sort -rg"で出力できることがわかりました。
-
結果はどうだったのか
HR Spannerのバックエンドではクリーンアーキテクチャを採用しているのですが、このうちinteractorの特定のファイルが両指標で上位を占めていました。それらの内容を定性的にチェックした結果、以下のことがわかりました。
- 定着傾向のレポートなどグラフ用のデータを集計する処理がいくつものプライベートメソッドで行われていて、コードサイズが巨大化
- 集計用の処理は、複数のSQLとそれを呼び出すアプリ側のメソッド、さらに一部フロントエンド側にも分散しており、見通しが悪くテストを書くのも難しい状態だった
- この処理が比較的変更しづらい箇所になっていることは、本製品の開発経験が長い鈴木さんの見解とも一致
対策の検討
コインの裏返し的な考えをすれば、単に処理を一箇所に集約すればこれら解消できます。しかし、ここでインフラ面を主に担当されている@_k725さんなどとお話ししていく中で下記のどちらかをとるべきという議論になりました。
案1 SQLでまとめて集計する
Pros.
- 全体の処理としては最もシンプルになる
Cons.
- 集計処理の負荷は、基本的にはスケールしづらいデータベースに対してかかるため、サービスが拡大した時に対応できず大変更が必要になる恐れがある
- フロントエンドに強いエンジニアが多い弊社では、SQLでの複雑な処理があまり好まれない
案2 アプリ側のコードでまとめて集計する
Pros.
- 性能面でのスケールが比較的容易
Cons.
- 元々集計が得意なSQLに比べ、長大、かつ属人性の高いコードとなりやすい
結論
論点としては、性能スケーラビリティがどこまで必要なのかだと考えました。具体的な数値はあげませんが、本製品のようなBtoB SaaSではそもそものアクセスユーザー数が比較的小さいため、使っていただける可能性のある企業さまの数、平均滞在時間、典型的なケースで計測したデータベースでの処理時間をもとに必要リソースを計算した結果、十分な余裕あることがわかったため、案1を採用することにしました。
結局のところ、リファクタを行う前に集計レポート機能の新規追加があったため、そちらからこの方針を取り入れています。
まとめ
最終的には開発メンバーの皆さんとも実際のコードを見て会話を進めていくことで、納得感を持って決めて行けたのでよかったと思います。また、リファクタの話となるとエンジニアの皆さんそれぞれの主義・主張がありますが、定量的な指標を使うと少なくとも問題箇所の特定までは議論をスムーズに進められるため、有用と思います。今後もこういった手法は活用していこうと思いました。
岡部 利樹 Toshiki Okabe
エンジニアリング統括部 サービス開発部 第3グループ エンジニア
※2021年12月現在の情報です。