何でも屋エンジニアのブログ

ソフトウェア関連技術、コミュニティ、日々の雑貨

Ruby コードの内部品質に関するメトリクスを取得する

はじめに

この記事は Ruby Advent Calender 2024 の25日目の記事です。

qiita.com

内部品質に関するメトリクスとは

ソフトウェアの内部品質に関するメトリクスとは、大まかに言うと読みやすさに関するメトリクスのことを指します。プログラムの長さ、呼び出しの回数、条件分岐の多さ・深さ、代入の回数等を計測し、これらが悪化すると読みづらいプログラムになってくる、というものです。

メトリクスを用いたソフトウェア品質定量評価・改善 (GQM, Metrics, ET2013) ではプロダクトの分野として6つのメトリクスが定義されています。

ソフトウェアメトリクスのうち主なメトリクスに関する表

Ruby を書く方であれば Rubocop の MetricsCop に指摘をもらったことのある方もいらっしゃるのではないでしょうか。まさに当該 Cop の内容が内部品質に関するメトリクスで、2024年12月22日現在10個の内部品質に関するメトリクスの Cop が定義されています。 詳しく知りたい方は以下の公式ドキュメントをお読みください。

docs.rubocop.org

CodeKeeper について

上述のように、Rubocop では内部品質に関するメトリクスについて違反を指摘してくれます。しかし必ずしも推奨の閾値を守れるとは限らず、閾値を緩めるもしくは指摘を無視するという対応をしてしまう現場もあるのでないでしょうか。一方で、改善活動の結果、コードの品質が向上するケースも存在します。このような日々のアクションの結果を継続的に取得し、観察できるようにしておくことは意義があると考え、CodeKeeper という Gem を開発しました。

github.com

使い方

メトリクス・出力形式

対応している内部品質に関するメトリクスは

  • 循環的複雑度(ファイル)
  • ABC ソフトウェアメトリクス(ファイル)
  • クラスの行数

です。

前者2つは、実装の簡便さを鑑みファイル単位とし、出力については取得したメトリクスを S3 や BigQuery などに取り込み解析できるように、csv もしくは json にて標準出力に吐き出す形としました。

設定

以下のような設定で、

  • 取得するメトリクス
  • 実行スレッド数
  • 出力フォーマット

を選択できます。

CodeKeeper.configure do |config|
  # If you choose metrics, specify as follows:
  config.metrics = %i(cyclomatic_complexity abc_metric class_length)
  # The number of threads. The default is 2. Executed sequentially if you set 1.
  config.number_of_threads = 4
  # The default is json
  config.format = :csv
end

以下は例として Gitlab の適当なファイルに実行した結果です。

$ bundle exec code_keeper app/models/user.rb app/models/ability.rb > metrics.json
$  cat metrics.json                                                                                             
{"cyclomatic_complexity":{"app/models/ability.rb":10,"app/models/user.rb":28},"class_length":{"Ability":100,"User":2033},"abc_metric":{"app/models/ability.rb":95.5092,"app/models/user.rb":2047.3842}}

用途

どのケースも S3 や BigQuery などのデータストアに内部品質に関するメトリクスの数値を貯め、活用することを想定しています。

  • リファクタリング・技術負債の返済・カイゼン活動の結果として眺める

    現状を改善していく何らかの活動の結果としての指標の一つとして、活用します。

  • Four Keys などの生産性指標と同時に観察する

    現在開発生産性の指標の一つとして Four Keys があります。

    • デプロイの頻度 - 組織による正常な本番環境へのリリースの頻度
    • 変更のリードタイム - commit から本番環境稼働までの所要時間
    • 変更障害率 - デプロイが原因で本番環境で障害が発生する割合(%)
    • サービス復元時間 - 組織が本番環境での障害から回復するのにかかる時間

    引用: エリート DevOps チームであることを Four Keys プロジェクトで確認する | Google Cloud 公式ブログ という4つの指標を測り、チームの開発のパフォーマンスを測定するというものです。 (詳しく知りたい方や興味のある方は「LeanとDevOpsの科学」や「State of DevOps Report」などをお読みください。) cloud.google.com book.impress.co.jp

    Four Keys と内部品質に関するメトリクスを観察することにより、生産性と内部品質に相関がある場合に改善活動を始めるという手段が取れます。

  • 閾値を定めアラートをあげる( Slack などに通知する)

    上述の通り Rubocop の指摘を必ずしも守り続けられるとは限りません。その場合、徐々に当該メトリクスの品質が悪化し続けることが想定できるので、暫定で新たな閾値を設け Slack にアラートを通知する等の手法をとり、Rubocop の指摘以外の強制力を働かせます。

今後について

まず、メトリクスについて増やしていきたいと考えています。Groovy でメトリクスを取得するライブラリの GMetrics を目指していきたいです。

dx42.github.io

Ruby の表現力を網羅できるよう仕上げるのは利用者の FB がないとかなり難しいので、Rubocop の private API を積極的に利用するのはありな気がしています。自身で実装するのは楽しいので、とても迷うのですが...。

また、上記の用途で上げたように基本データストアに保存したいはずなので、S3 などにアップロードする機能は早めにサポートしたいなとおもっています。

これは Gem でサポートする話ではないですが、解析してグラフを表示するような Web サービスを作りたい気持ちでいます。

最後に

CodeKeeper は、自身が携わっていたプロダクトでのソフトウェアマネジメントに活用しようと思い作ったものです。しかしより優先順位の高い事項が多く活用ができないまま、私自身が独立しフリーランスになってしまいました。趣味プロジェクト等で使おうとは思っていますが、より本格的に活用した事例など聞けるととても嬉しいです。荒削りですが、FB や要望等お待ちしています。