開発の進み具合を計測し、モチベーションを維持するために rails stats を保存しよう
こんにちは。Freespk、Copipedia というウェブサービスを個人で開発しています、Beyond です。
さて仕事で開発を行うときは Issue などでバーンダウンを作成し、順調に開発が進んでいるかを「見える化」していますが、個人で気ままに作る際にはチケットとか Issue とか面倒で作ってられません。
とはいえ何も指標が無いと、ペースが落ちているのかどうか判断することすら感覚的なものとなってしまいます。幸い、Rails には、rails stats
というコマンドがあり、コードやテストの有効行数(コメントを除いた行数)を簡単に計算してくれます。下の図の、Code LOC とか Test LOC がそれになります。
$ rails stats
+----------------------+--------+--------+---------+---------+-----+-------+
| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| Controllers | 4 | 3 | 1 | 0 | 0 | 0 |
| Helpers | 2 | 2 | 0 | 0 | 0 | 0 |
| Jobs | 7 | 2 | 1 | 0 | 0 | 0 |
| Models | 3 | 3 | 1 | 0 | 0 | 0 |
| Mailers | 4 | 4 | 1 | 0 | 0 | 0 |
| Views | 90 | 55 | 0 | 1 | 0 | 53 |
| Stylesheets | 10 | 10 | 0 | 0 | 0 | 0 |
| JavaScript | 23 | 16 | 0 | 0 | 0 | 0 |
| Libraries | 0 | 0 | 0 | 0 | 0 | 0 |
| Controller tests | 0 | 0 | 0 | 0 | 0 | 0 |
| Helper tests | 0 | 0 | 0 | 0 | 0 | 0 |
| Model tests | 0 | 0 | 0 | 0 | 0 | 0 |
| Mailer tests | 0 | 0 | 0 | 0 | 0 | 0 |
| Integration tests | 0 | 0 | 0 | 0 | 0 | 0 |
| System tests | 0 | 0 | 0 | 0 | 0 | 0 |
+----------------------+--------+--------+---------+---------+-----+-------+
| Total | 143 | 95 | 4 | 1 | 0 | 93 |
+----------------------+--------+--------+---------+---------+-----+-------+
Code LOC: 95 Test LOC: 0 Code to Test Ratio: 1:0.0
コード行数の推移を記録してみた
そこで、CI でテストが成功するたびに、Mackerel に rails stats の値を自動で記録するようにしてみました。1月から始めたので、約半年間(~6月13日まで)の推移が以下の図となります。グラフを見れたから何と言うことも無いのですが「基本、線形にコード量が増えているな」とか「テストの方が伸びが速いな」ということがわかります。
Claude Code で特異点発生!
なお、6月13日までのグラフを見ていただきましたが、開発は 100% 人力ということはなく、Github Copilot(途中から、エージェント mode も活用), ChatGPT を使いつつ開発しています。人+AIのベロシティーがこのグラフです。それで、最近は Claude Code が良いらしいので、1週間前に Claude Code MAX を使って開発を始めました。
そして、Claude Code を使い始めてからの期間を足したものが以下のグラフになります。コードの伸び率はあまり変わっていませんが、テストの伸び率がとんでもないことになっています。まさに微分不可能、特異点が発生してるようです。
この伸び率が本物か、単にものめずらしさで色々タスクを頼んだので伸びが良かっただけか、はたまた無駄なテストが多すぎるのか、これからの推移を見ていく必要があります。「見える化」しておくと、こんなことも分かるので、ぜひ皆さんも記録してみてください。
補足:coverage も記録していますが、Claude Code の前後で大きな変化はありません。
参考:Mackerel に stats を送信するコード
私が、Mackerel に rails stats を記録するのに使っているコードが以下のものになります。
要点としては、rails stats は標準出力に結果を出すため、perform_stats の中で標準出力を hook して取り込んでいます。外部コマンド実行はしたくないので、 Rails::Command
を直接実行しています。Rails の仕様が変更した場合、もしかしたら変える必要があるかも知れません。
class MackerelStats
attr_accessor :api_key, :service_name
def initialize api_key: nil, service_name: nil
@api_key = api_key || ENV["MACKEREL_API_KEY"]
@service_name = service_name || ENV["MACKEREL_SERVICE"]
end
def run
stats = perform_stats
stats =~ %r"Code LOC: (\d+)"
code_loc = $1.to_i
stats =~ %r"Test LOC: (\d+)"
test_loc = $1.to_i
now = Time.zone.now.to_i
values = [
{ name: "loc.code", value: code_loc, time: now },
{ name: "loc.test", value: test_loc, time: now },
]
mackerel = Mackerel::Client.new mackerel_api_key: api_key
mackerel.post_service_metrics service_name, values
rescue Mackerel::Error => e
raise unless e.message.match? %r"failed: 50[34]"
end
def perform_stats
original_stdout = $stdout
$stdout = StringIO.new
stats_command.perform
$stdout.string
ensure
$stdout = original_stdout
end
def stats_command
Rails::Command.find_by_namespace("stats", "stats").new
end
end
MackerelStats.new.run if $PROGRAM_NAME == __FILE__
Discussion