プログラミング
Sloc Cloc and Code 4.0 (scc) – 最も注意が必要なファイルを見つける
Sloc Cloc and Code 4.0 (scc) – Finding the files that need the most attention (boyter.org)
要約
本記事は、コード分析ツール scc (sloc cloc and code) のバージョン4.0.0のリリースについて解説しています。新機能である「ホットスポット」分析は、コードの複雑さと変更頻度を組み合わせて、最も注意が必要なファイル(バグや複雑なロジックが存在する可能性が高いファイル)を特定します。これにより、開発者はコードベースの理解やオンボーディングを効率化できます。
全文翻訳
Sloc Cloc and Code 4.0 (scc) - 最も注意が必要なファイルを見つける
2026/08/23 · 3956 words
本日、sloc cloc and code、別名sccのv4.0.0バージョンをリリースしました。3.7.0から3.8.0への移行を検討していましたが、かなりの新機能が追加されたため、メジャーバージョンを上げるのが妥当だと判断しました。また、その新機能の一部について詳細を説明するブログ記事が必要なほど大規模でしたので、この記事でいくつか紹介し、読者の皆様に最新バージョンを試してもらえることを願っています。
ホットスポット
10年以上前に、Googleのバグ予測について書きました。これは、コミット履歴とバグ修正を比較して、問題のあるファイルが存在する場所を特定するものでした。興味深いものでしたが、引用によると「要するに、開発者はそれが役に立つと感じなかった」ため中止されました。コードがホットスポットであることを知っていても、それを改善する手段を提供しませんでした。滑稽なことに、私はこのことを忘れており、複数のLLMにそれを探すように依頼したところ、私がそれを探していると尋ねたときに、すべて私のブログへのその投稿にリンクバックしてきました。どうやら私はそれに関する「権威ある情報源」になったようです。私はこれを、もっと探求したいこととして常に心に留めていました(だからこそ、再び見つけようとしたのです)。最近、sccは複雑さの推定値を持っているのだから、それを使ってノイズを抑えることができるのではないかと思いました。結局のところ、設定ファイルに多くの修正が加えられたことを知ってもあまり役に立ちませんが、多くのロジックを持つファイルに多くの変更が加えられたことを知るのは有用です。これは、codespelunkerでのランキングに採用したのと同じアプローチです。複雑なファイルが最も注意を必要とします!私が知る限り、これはAdam Tornhillの「Your Code as a Crime Scene」のアイデアの再発明です(この本を発見してからまだ読んでいます)。彼はその結果、CodeSceneという会社まで設立しました。明らかに、このメトリックには何らかの価値があります。私がオリジナルのアイデアを持っていたなんて、まったく。とにかく、scc自身のコードベースに対してsccを実行して得られるものを見てみましょう。
$ scc --hotspots
───────────────────────────────────────────────────────────────────────────────
ホットスポット · 直近1000コミット · 2019-07-21 → 2026-06-26
───────────────────────────────────────────────────────────────────────────────
ファイル Lang Cmplx Commits Lines± Authrs Hotspot
───────────────────────────────────────────────────────────────────────────────
processor/processor.go Go 156 156 1,651 13 100.0
processor/workers.go Go 244 92 3,617 15 92.2
test-all.sh Shell 56 181 3,287 15 41.7
~ocessor/formatters_test.go Go 183 51 2,459 9 38.4
processor/workers_test.go Go 408 21 1,189 8 35.2
processor/formatters.go Go 44 135 5,848 17 24.4
main_test.go Go 261 18 995 6 19.3
processor/detector_test.go Go 133 32 1,175 6 17.5
main.go Go 40 101 1,545 17 16.6
processor/file.go Go 50 73 2,074 12 15.0
processor/detector.go Go 70 45 948 5 12.9
processor/file_test.go Go 75 33 826 5 10.2
cmd/badges/main.go Go 73 31 1,111 5 9.3
processor/history.go Go 173 9 941 4 6.4
processor/structs.go Go 25 42 247 10 4.3
config_test.go Go 199 4 850 3 3.3
~workers_regression_test.go Go 50 13 276 6 2.7
~rocessor/processor_test.go Go 51 12 289 4 2.5
~ocessor/history_authors.go Go 111 5 666 3 2.3
mcp.go Go 71 7 527 4 2.0
───────────────────────────────────────────────────────────────────────────────
複雑さ × 変更頻度、正規化済み · 90ファイル中20ファイル表示
───────────────────────────────────────────────────────────────────────────────
出力は、コードベースのホットスポットがprocessor/processor.goとprocessor/workers.goであることを正しく特定したことがわかります。私自身の経験に基づいて、これが正しいことを確認できます。
なぜ気にする必要があるのか?
なぜなら、その要約は、複雑さやチャーン(変更頻度)だけではできないことを行っているからです。どうやってやるのか説明します!
要するに、ホットスポット = 複雑さ × コミット数(0-100のスケールで正規化)です。現在のHEADファイルの複雑さを計算し、各ファイルが何回変更されたかを確認するために後方にウォークします。これはHEAD内のファイルのみをカウントすることに注意してください。削除された高チャーンファイルはカウントされません。
単純なカウントと比較してみましょう。
$ scc --by-file -i go -s complexity
───────────────────────────────────────────────────────────────────────────────
言語 ファイル 行数 ブランク コメント コード 複雑さ
───────────────────────────────────────────────────────────────────────────────
Go 69 40,137 3,049 2,131 34,957 4,478
───────────────────────────────────────────────────────────────────────────────
processor/workers_test.go 2,156 374 69 1,713 408
main_test.go 992 80 26 886 261
processor/workers.go 966 146 102 718 244
processor/report_test.go 971 98 109 764 237
config_test.go 786 50 85 651 199
───────────────────────────────────────────────────────────────────────────────
単純なカウントを実行し、Goファイルに限定して複雑さでソートすると、workers_test.go、main_test.go、config_test.goがすべて上位にランク付けされていることがわかります。これらのファイルはすべて技術的に複雑ですが、実際の開発作業が存在する場所はどれもありません。複雑さだけでは、if条件が多く存在する大きなファイルがどこにあるかがわかります。それはしばしばテストファイルであることが判明します。それらはリストに残っていますが、ランクが下がっています。もちろん、高チャーンのテストファイルは、予想通り、これでも上位に上がってきます。
それを反転させてチャーン、つまりコミット数でランク付けしてみましょう。すると、test-all.shが181コミットでトップになり、structs.goが42コミットで浮上します。どちらも常に変更されていますが、バグやロジックがある場所ではありません。チャーンだけでは、何が頻繁に変更されるかがわかります。これはしばしば設定、スクリプト、ボイラープレートですが、バグやロジックの代理としては不十分です。しかし、チャーンと複雑さの両方の重複は、合理的な代理となります。どのようなファイルが複雑で、多くの変更があるのか!これはGoogleが試みて失敗したものとは少し違うことに注意してください。このメトリックは「過去にバグが多かった」ポインターではなく、「作業しにくい」インジケーターであり、コードを分割する必要がある可能性を示唆しています。
では、なぜそれが役立つのでしょうか?
さて、複雑なコードが誰も編集しないのであれば、問題ではないでしょう。それは機能しており、あなたは先に進みます。頻繁に変更する単純なファイルもおそらく問題ではありません。設定行を追加し、コンパイラがそれをチェックし、あなたは先に進みます。しかし、複雑で頻繁に変更されるファイルは、問題が潜んでいる場所です。マージコンフリクトが最も多く発生し、テストが最も壊れやすく、変更を加える際に最も苦痛を感じる場所です。
sccコードベースについてはすでに知っていましたが、私がそれに慣れていないと想像してみてください。私はアプリケーションの心臓部がどこにあるかを特定したばかりです。Googleに戻すと、彼らはリスクのあるファイルをフラグ付けしましたが、開発者は気にしませんでした。なぜなら、ホットスポットがどこにあるかを知っても、それに対して何もできないからです。「これはバグがある」と知ることは、CI/CDでさらに多くの作業を増やす(技術的負債のクレジットカードに載せる)だけです。自分が知っているコードベースのホットスポットを知っていても、あまり役に立ちません。しかし、コードベースに慣れていない場合にホットスポットを知ることは、オンボーディングに非常に役立ちます。そして、これはまさにその質問に対する答えを教えてくれます。
Googleが失敗したのは、ホットスポットフラグがアクションを提供しないためですが、見慣れないコードベースに向けられた同様のアイデアは、オンボーディングマップになります。
- 私
もう一つできることは、この計算がどのくらいの深さのgitコミットで行われるかを指定することです。より少ないまたはより多くのコミット(時間)を振り返ることで、ホットスポットがどのようにシフトしたかを見つけることができます。50コミットを振り返るのと10コミットを振り返るのとでは、
$ scc --hotspots --depth 50
───────────────────────────────────────────────────────────────────────────────
ホットスポット · 直近50コミット · 2026-04-13 → 2026-06-26
───────────────────────────────────────────────────────────────────────────────
ファイル Lang Cmplx Commits Lines± Authrs Hotspot
───────────────────────────────────────────────────────────────────────────────
processor/processor.go Go 156 14 415 4 100.0
main_test.go Go 261 8 295 4 95.6
processor/history.go Go 173 9 941 4 71.3
processor/workers.go Go 244 6 130 5 67.0
processor/workers_tes