Line 1: Error: Invalid Blog('by Esehara' )

または私は如何にして心配するのを止めてバグを愛するようになったか

>> Zanmemo

あと何かあれは 「esehara あっと じーめーる」 か @esehara まで

git logで生産性は可視化できるのか、Rでグラフを作って調べてみる

はじめに──行数管理とgit commit

 ここ最近に、「プログラマー」の生産性を何かしら指標化する必要があるのではないか、という指摘がありましたが、確かにそういう側面もある一方で、「プログラム」という行為が、実は言われるほど簡単ではなく、何らかの形で指標にしようとすると難しくなるという問題があるかと思われます。

 自分は直接ぶちあたったことはないのですが、たまに悪習として語られる指標の一つとして、「ステップ数」が上げられるでしょう。確かに、多くの人々が指摘しているように、ステップ数の問題は、下のような意味で問題があると言えるでしょう。

  • 「機能」は、コードに直された場合、一行にも百行にもなるが、単純ステップ計算数で数えた場合、後者のほうが生産的と捉えられてしまう
  • コードを手直ししていく作業として、リファクタリングする側面は、ステップの総体を変えないが、コードの綺麗さは、その後の生産性を変えてしまう側面がある

 このように、ステップ数を持ってして生産性を計るのは、その「プログラマーが感じる生産性」との大きなズレを生じさせるという意味で、忌諱される対象として見られてきた印象です。これは自分もまったく同意なのですが、同様に、じゃあ「何らかの指標はないのか」というのを無視するのも、ちょっと変だなという気はしています。

仮説

 「プログラム」の行為を、「書く」という側面から分析すると、たぶんこのようなズレが生じるかと思うわけです。確かに、昔はテスト駆動開発などのプラクティスが無かったために、それこそ「動いているコードはいじるな」といったような、コードの層を肥大化させていく状態があって、だからこそ「ステップ数」という無茶なところに視点が集まっているように感じます

 むしろ、最近考えるのは、プログラムの行為自体は、むしろ「書く」ことではなく「変更すること」のように感じます。例えば、テスト駆動の一つのメリットとして、リファクタリングしやすくなるということがあげられているように感じます。リファクタリングは、コードをよりわかりやすく、正確にしていく作業になります。問題は、「書くこと」ということが、「書き直すこと」であるということが問題だと思うわけです。

 そこで、ヴァージョン管理システムのログを考えてみます。例えばgitであるならば、これらの変更点、つまり「コミット数」を数えることは、恐らく単純にステップ数を数えるよりも、遥かにプログラムという行為を浮き彫りにするのではないか。というのも、コミットというのは、基本的にはなんらかの変更の単位によって行なわれるものである、と感じるからです。

 この変更の単位は、一行であれ百行であれ、それが必要な粒度であるならば、一つになるはずですし、コードを手直しするリファクタリングの部分も回収されるのではないか。

 もちろん、何度も言うように、プログラミングの行為というのは単純なものではないので、コミット数で生産性を計れるとは、素朴には信じませんが、面白そうなので、すこしログをいじってみましょう。

gitからログを引っ張ってくる

 gitには、いままでの変更点を一覧する方法として、git logというのがあります。これらはさまざまな形式で書き出すことが出来ます。例えば、下を見るといいでしょう。

 そこで、git logを橋渡しし、他のプログラムから加工しやすい形式として、擬似的なCSVを使いたいと思います。例えば、下のようにすると、擬似的なCSVとして、git logを吐き出すことができるでしょう。

git log --date=short --pretty=format:'%ad, %an' > foobar.csv

 もちろん、これは名前にコロンが入っていたりするとパースに失敗したりするのですが、これは仮の姿として考えます。

Pythonでデータをまとめる

 もちろん、これでもいいとは思うのですが、さらにPythonで日付毎にどれだけコミットしているのかをまとめてみます。例えば、下のようなスクリプトを書いたりして圧縮してみましょう。

# -*- coding: utf-8 -*-
import sys
import csv
"""
gitlog complete:
    usage:
        git log --date=short --pretty=format:'%ad, %an' > foobar.csv
"""


def main(inputfile, validate_name, outputfile):
    date_matrix = {}
    csv_file = open(inputfile)
    for row in csv.reader(csv_file):
        print row
        date = row[0]
        name = row[1].rstrip().strip()
        print name
        if name == '%s' % validate_name:
            if date in date_matrix:
                date_matrix[date] += 1
            else:
                date_matrix[date] = 1
    w = open(outputfile, 'w')
    w.write("date, num_commit\n")
    for w_date in sorted(date_matrix.keys()):
        w.write('"%s", %s\n' % (w_date, date_matrix[w_date]))
    w.close()

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print "Usage:"
        print "  gitlog_date.py inputfile.csv validate_name outputfile.csv"
        sys.exit(0)
    inputfile = sys.argv[1]
    validate_name = sys.argv[2]
    outputfile = sys.argv[3]
    main(inputfile, validate_name, outputfile)

 このスクリプトは、引数に入力するデータ、名前、吐き出すデータを渡してあげると、名前でフィルターをかけてまとめたCSVデータを吐き出してくれます。そのとき使うバリデート形式は、スクリプトに書かれたような形になります。30分程度で書いたので多々おかしいところもあると思いますが、それは修正して使って頂ければありがたいです。

Rで可視化する

 最後に、Rでデータを可視化してみましょう。これらのデータをRで噛ませてみます。

library(zoo)

# データの読み込み
gitlog <- read.csv('gitlog_comp.csv')

# 日付オブジェクトに変換
date_obj <- as.Date(gitlog$date)

# 移動平均
ma <- rollmean(gitlog$num_commit, 3)

# サイズを変更する
png('work.png', width=600, height=600)
plot.new()

# 画像を三分割
par(mfrow=(c(3,1)))

plot(date_obj, gitlog$num_commit, type="l", xlab="期間", xaxt="n", ylab="", col="red", main="コミット数")
plot(ma, type="l", ylab="", col="blue", main="移動平均", xlab="期間", xaxt="n")
hist(gitlog$num_commit, main="ヒストグラフ", prob=T)
lines(density(gitlog$num_commit), col="blue")

dev.off()

 これで出力した結果を見てみましょう。

満足出来たプロジェクトの場合

 例えば、満足できたプロジェクトの場合を使って表示してみましょう。

 移動平均に着目してみると、平均的なコミットが続いているように感じます。また、ヒストグラムをみてみると、10回以上、つまり粒度のあるコミットがあると言うことが出来るかもしれません。

満足出来なかったプロジェクトの場合

 満足できなかったプロジェクトの場合のログを見てみましょう。

 期間が長かったこともあり、少しギザギザになっているのがわかります。また、最頻であるコミットが5回であり、粒度としては大きい形のことが多い感じになっている、ということができるかもしれません。その辺が、モチベーションと関係しているかもしれません。

自分のサービスの場合

 短いですが、自分が作っているサービスの場合も参考にしてみましょう。

 土日であったり、あるいは暇なときにちょこちょこといじっているために、比較的5回が多いというのがあげられるでしょう。ただ、右の30-35回もたまに出てきたりしますね。

まとめ

 さすがに三つのサンプルで何を結論しようという感じではないのですが、結論というか、新しい仮説として、次のようなことが考えられるでしょう。

  • モチベーションが高くなるほどコミットが多くなる傾向にあるのではないか
  • モチベーションが低いと、コミットが少なくなるのではないか
  • モチベーションが高いときは、波を描く。逆にモチベーションが低いほど、ギザギザになるのではないか

 言われてみれば、そりゃそうだろうという感じではあるのですが、こうやって図にしてみると、改めて自分のプログラミングパターンがわかって面白いなと思います。是非皆さんも暇な時は"git log"に溜まったデータを集めてみて、いろいろと遊んでみると、何かしらの「プログラマーとしての行動」が浮き彫りになるかもしれませんね。