DMM プラットフォームのコードランクについて

サムネイル

はじめに

こんにちは
DMM.com の N9tE9 です。
プラットフォーム開発本部 Developer Productivity Group 横断チームで働いています。

横断チームは、プラットフォーム開発本部の各チームのコード品質や開発生産性に関するメトリクスを集計/可視化し、それらを活用して開発組織全体の生産性を向上させる活動を行っています。
今回は、コード品質を可視化するコードランクについてお話しします。

コード品質の定義について

"コード品質" と一言で言っても観点は様々です。
パッと思いつく限りでも以下のような観点があります。

  • 可読性の高いコード
  • 変更容易性の高いコード
  • パフォーマンスの高いコード
  • CPU, Memoryなどの消費リソースが少ないコード

本記事で扱うコード品質は、ISO25000 で定義されている保守性について焦点を当てます。
https://www.ipa.go.jp/archive/files/000065855.pdf

保守性を構成する要素は以下です。

  • モジュール性
  • 再利用性
  • 解析性
  • 修正性
  • 試験性

保守性の高いコードは可読性が高かったり、変更容易性が高かったり、テストが書きやすかったりと、結果的に開発生産性の向上に直結します。

DMM プラットフォームのコード品質への取り組み

DMM プラットフォームは、2021年からレガシーシステムを順次リプレイスするプロジェクトを開始したこともあり、リプレイスしたアプリケーションのコードを高品質に維持する必要がありました。
そのため、組織全体としてコード品質の向上にしっかりと工数を割ける開発体制になっています。

Developer Productivity Groupが取り組んでいるレビューシステムもコード品質を改善するための仕組みの1つです。
レビューシステムについては、pospome さんが過去に登壇した資料があるので、それを参考にしてください。
https://speakerdeck.com/pospome/zu-zhi-nokodopin-zhi-woxiang-shang-saseru-rebiyusisutemu-noqu-rizu-mi

レビューシステムを実施していく中で、チームによってコード品質に対するリテラシーに大きな差があることが分かりました。
具体的には以下のような具合です。

リテラシー 実態
静的解析を導入している。
週1の運用定例で解析結果を確認する。
解析結果に応じてリファクタリングを適宜行う。
テストカバレッジは 90% を基本的に超えている。
簡単な静的解析を導入している。
CI でテストカバレッジを計測していて、80 ~ 90% を満たしている。
静的解析は導入していない。
CI でテストカバレッジを計測していない。
計測している場合でも、テストカバレッジは 50% に達していない。

この結果を踏まえて、Developer Productivity Groupは、リテラシーの低いチームのコード品質を改善していく取り組みを本格的にスタートする必要性を感じました。
Developer Productivity Groupでは、コード品質を改善していくために必要な要素として、以下の3つを定義しています。

  1. リファクタリングに工数が割ける環境であること
    システム仕様や非機能要件は変化していくので、それに合わせて随時コードをリファクタリングしていく必要がある。
    リファクタリングに工数を割けない開発組織はコード品質を改善することは難しい。
  2. 静的解析を利用し、自動的に問題となっているコードを検知できること
    検知を自動化することで、エンジニアのレビュー工数やレビュー漏れを防ぐことができる。
  3. 設計スキルの高いエンジニアを配置すること
    元も子もない話になるが、リファクタリングに工数を割き、静的解析を導入したとしても、人による良し悪しの判断は必須である。
    設計スキルの高いエンジニアがいないと、人が適切に判断すべきポイントを取り切れなくなってしまうので、コード品質の改善に限界がある。

前述したようにDMMプラットフォームではコード品質の向上に工数を割ける開発体制があるので、「リファクタリングに工数が割ける環境」は実現できています。
また、「設計スキルの高いエンジニアを配置すること」に関してもレビューシステムによって擬似的に補うことができています(理想は各チームに設計スキルの高いエンジニアを配置することです)。
「問題となっているコードを検知できる」については、静的解析の SaaS を導入することで改善できる余地があったので、DMMプラットフォームでは SonarCloud を採用しました。
しかし、SonarCloud を導入するだけでは各チームの目指すべきレベルにバラツキが出てしまう(例えば "テストカバレッジをどこまで高めるべきか?" など)ので、静的解析の結果を活用して各アプリケーションのコード品質を定量化し、目指すべき統一的な基準を定義する必要がありました。
こうした背景から生まれた仕組みが "コードランク" です。

コードランク とは

コードランクとは、 Sonar Cloud というサービスを活用し、コード品質をランク付けするものです。

SonarCloud は、GitHub などのソースコード管理の SaaS と連携することで、コードの静的解析やテストカバレッジのレポートを行うことができ、その結果を可視化するサービスになります。


WebUIだけでなく、API を通じて各アプリケーションコードのコード品質に関するメトリクスを取得できます。
SonarCloud API から取得できるメトリクスは、以下のようなものがあります。

  • テストカバレッジ
  • 信頼性
  • メンテナンス性
  • セキュリティ
  • セキュリティホットスポット

これらのメトリクスは、SonarCloud 側で A ~ E にランク付けされます。
コードランクは、SonarCloud API から取得できる各メトリクスをメトリクススコアというコードランク用の独自の点数に変換します。
メトリクススコアを元にコードランクを算出します。

アーキテクチャ

アーキテクチャ図は以下のようになります。

Sonar Cloud APIからのデータ取得はCloud Functionsを定期的に実行しています。
取得したデータは BigQuery にそのまま保存しています。

BigQueryに保存したデータはLooker Studioにて表示していますが、BigQueryに保存したデータはSonar Cloudの生データなので、表示の際に UDF(User Defined Function) を利用してデータを加工しています。
"生データ保存 & UDF" にした目的は、中長期的にランク付けのロジックを変更した場合でも対応できるようにするためです。

バッチの冪等性を担保するために、 Cloud Pub/Sub でメトリクスを取得する期間を指定し、実行する機能も提供しています。
手動実行時は、BigQuery に保存されている指定された期間に該当するデータを削除し、SonarCloud API から取得できるメトリクスを保存します。
SonarCloud は過去のコードの解析結果を保存しており、SonarCloud API から過去の解析結果を取得できるので、それを利用しています。

メトリクススコア

SonarCloud API から取得できるメトリクスを元にメトリクススコアを計算します。
各種メトリクスは、それぞれ 0 ~ 2 の値に変換されます。
それぞれのメトリクスの 0 ~ 2 の値に変換するロジックは以下のようになっています。

テストカバレッジ

SonarCloud API からアプリケーションコード全体のテストカバレッジの値を取得できます。
以下は、SonarCloud API から取得する値とメトリクススコアの対応表および説明になります。

アプリケーション全体のカバレッジの値(%) メトリクススコア 説明
91 ~ 100 2 単体テストのテストの設計が適切にできています。
単体テストにおいて高度なテスト戦略やテスト設計ができているとみなせます。
80 ~ 90 1 Developer Productivity Group が求める最低限のテストカバレッジは満たしています。
単体テストにおいてDeveloper Productivity Group が求めるテスト戦略やテスト設計ができているとみなせます。
~ 79 0 Developer Productivity Group が求める最低限のテストカバレッジのスコアを満たしていない状態です。
単体テストのテスト戦略や設計ができていないとみなせます。

コードの信頼性

SonarCloud API から取得するコードの信頼性の値からメトリクススコアを算出します。
以下は、SonarCloud API から取得する値とメトリクススコアの対応表および説明になります。

SonarCloud のコードの信頼性のメトリクス メトリクススコア 説明
A 2 静的解析で検知できるバグが存在しない状態です。
信頼できるコードが実装できています。
B ~ C 1 重要度は高くないものの、静的解析で検知できるバグが存在しています。
致命的な不具合はないものの、意図しない挙動をするコードが実装されている可能性があります。
D ~ E 0 静的解析で検知できる重要度の高いバグが存在しています。
ランタイムが停止するなどの、アプリケーション実行において重大な影響を与える実装がされている可能性があります。

メンテナンス性

SonarCloud API から取得するメンテナンス性の値から、メトリクススコアを算出します。
以下は、SonarCloud API から取得する値とメトリクススコアの対応表および説明になります。

SonarCloud のメンテナンス性のメトリクス メトリクススコア 説明
A 2 技術負債がほとんどない状態です。
B ~ C 1 技術負債は存在するものの、開発に大きな影響を与えるものではないです。
リファクタリングをする必要がありますが、緊急度は高くありません。
D ~ E 0 多くの技術負債が存在しており、開発に大きな影響を与えている可能性が高いです。
早急なリファクタリングや設計の見直しが必要になります。

セキュリティ

SonarCloud API から取得するセキュリティの値から、メトリクススコアを算出します。
以下は、SonarCloud API から取得する値とメトリクススコアの対応表および説明になります。

SonarCloud のセキュリティのメトリクス メトリクススコア 説明
A 2 コード上に脆弱性となるコードは存在しない状態です。
B ~ C 1 脆弱性となるコードが存在しますが、軽 ~ 中度のリスクのものになります。
早急な対応は必要ないですが、状況に応じて修正する必要があります。
D ~ E 0 重度の脆弱性となる実装が存在します。
早急に対応する必要があります。

セキュリティホットスポット

SonarCloud API から取得するセキュリティホットスポットの値から、メトリクススコアを算出します。
以下は、SonarCloud API から取得する値とメトリクススコアの対応表および説明になります。

SonarCloud のセキュリティホットスポットのメトリクス メトリクススコア 説明
A 2 コード上にセキュリティリスクとなるものが存在しない状態です。
B ~ C 1 コード上にセキュリティリスクとなるものが存在しますが、軽 ~ 中度のリスクのものになります。
早急な対応は必要ないですが、状況に応じて修正する必要があります。
D ~ E 0 コード上に重度のセキュリティリスクとなるものが存在します。
早急に対応する必要があります。

コードランクのランク付けロジック

各種メトリクススコアを足し合わせ、アプリケーションのコード品質のメトリクススコアとします。
以下は、アプリケーションのコードランクの算出ロジックおよび説明になります。
現在のDMMプラットフォームでは「全アプリケーションがBランクを獲得すること」を目標にしています。

コードランク 算出ロジック 説明
A "テストカバレッジが2点" かつ "各メトリクスのスコアの合計が 8 ~ 10" Developer Productivity Group は、現在テスト戦略を重要視しています。
そのため、高度なテスト戦略やテスト設計ができていない場合は、A になれないようにしています。
それ以外のメトリクスについても、高度な品質を保証している必要があります。
B "アプリケーションのコード品質のメトリクススコアが 8 ~ 10" かつ "全てのメトリクスのスコアが1以上である" 高度なテスト戦略やテスト設計が運用できていなくても、一定以上のテスト戦略やテストの設計が実施できており、高度なコード品質を維持できている状態です。
C "アプリケーションのコード品質のメトリクススコアが 5 ~ 7" かつ "全てのメトリクスのスコアが1以上である" 一定以上のテスト戦略やテストの設計の実施ができていますが、コード品質においては懸念点があります。
テスト戦略以外にも見直しの余地がある状態です。
D "メトリクススコアに0が存在する" コード品質において致命的な課題が存在します。
テスト戦略の他にも早急に対応すべき課題がある状態です。

目指すべき世界をランク付けロジックに反映させる

メトリクススコアやコードランクのロジックは「Developer Productivity Groupが目指したい世界」から逆算したものになっています。
例えばDeveloper Productivity Groupはテストカバレッジを高く維持することによる開発生産性の向上を高く評価しており、各チームにそれを目指してほしいと思っています。
そのため、テストカバレッジのメトリクススコアはカバレッジが80%未満の場合は 0 になります。
そして、テストカバレッジのメトリクススコアが 0 の場合、他のメトリクススコアに関わらず、コードランクは最低評価の D になります。
厳しいように思えるかもしれませんが、これはテストカバレッジを重要視している我々の思想を反映しているものであり、開発者がランクをハックできないようにするための仕組みでもあります。

コードランクの限界

コードランクによるコード品質の可視化は、SonarCloud による静的解析結果がベースになっています。
そのため以下のような静的解析では判断できないコード品質要素は、人間がコードレビューによって保証する必要があります。

  • 関数名と関数の振る舞いが適切であるか
  • 構造体の設計が適切であるか

コードランクによって、各チームに「このくらいは最低でもやってほしい」という程度を認識してもらえるようになりましたが、Developer Productivity Group としては「あくまで最低限の品質を保証する程度のものでしかない」という課題もしっかりと認識しています。
これを補うために、前述した "レビューシステム" のような、人の手によるコード品質改善にも取り組んでいます。

どのように活用していくのか?

コードランクが C, D のチームは、リファクタリングやユニットテスト実装といったアプリケーションの保守に工数をかけることができていない可能性があります。
そのため、コードランクが C, D といったチームを B 以上にできるように働きかける予定です。

まとめ

コードランクの仕組みについて説明しました。
コードランクの次のステップとしては、SonarCloud 以外のコード品質に関するメトリクスを増やしていく予定です。
具体的には、循環複雑度、認知複雑度、コードの変更頻度やパッケージ間の依存度といったものになります。

宣伝

Developer Productivity グループでは、DMMプラットフォームの開発効率とセキュリティレベルの向上を目指して一緒に取り組むメンバーを募集しています。興味がある方は、以下記事も合わせてご確認ください。

DMMプラットフォームのマイクロサービスアーキテクトグループのエンジニア募集について