開発チームの生産性・健全性を客観的に知るためにリポジトリ履歴から機械的に可視化するツールを作った


# はじめに
ソフトウェア開発のチームの生産性や健全性というものは、内部の体感的として理解できるものの、外部の人間からは見えにくいものです。こういった情報の非対称性は開発チーム外の人々との関係の中での問題の原因になってきました。

また、複数の開発チームやプロダクトを束ねるEM、CTOや、管理職にとってそれぞれの状況を客観的な数字やグラフで可視化することは、全体的な戦略を考える上でも重要な参考情報になります。ですが、アンケートやプロジェクト管理を増やすほど、どんどんと開発メンバーに負担をかけてしまうことになり、計測のし過ぎによる疲れなども誘発してしまいます。

本稿では、gitリポジトリのログ情報から、いくつかのグラフを生成し、チームの状況を可視化するためのツール``gilot``を作成したので、その目的と意図、そして使い方、注意点を解説します。

# アプローチ方法
gilotのアプローチは、git logのデータを解析して、開発チームのアウトプットがどれだけ安定しているか、どれだけの出力があるのか、何人が実質的にコミットしているのかなどを分析して、可視化します。生産性や健全性そのものが直ちに判断できるわけではありませんが、ひとつの強力なエビデンスになることを期待しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/3bf537ca-0981-c1eb-2e48-d9a51b38f007.png)


## バージョン管理システムのログを使う：
これまでも生産性や健全性の可視化という観点では、プロジェクト管理ツールや、アンケート調査などを通じてそれらを可視化する試みは多数あります。これらも重要な可視化のための情報ですが、もう一つの情報源としてバージョン管理システムの情報をソフトウェアプロジェクトに活かしていくという試みが近年では増えてきました。

バージョン管理システムのログは

+ 実際の開発者が意識せずとも自然な活動情報が記録されている。
+ プログラム言語の種別や環境によらず統一的に分析できる

などのメリットがあるため、実証的なソフトウェア・エンジニアリングの世界では注目されています。

+  [Microsoft Research の欠陥密度の推定にコードチャーンを用いた研究](https://www.microsoft.com/en-us/research/publication/use-of-relative-code-churn-measures-to-predict-system-defect-density/)
+ [Bugspots](https://github.com/igrigorik/bugspots)


これらの他にも、私自身がかつて自社のプロジェクトの技術的負債の可視化のために、「多くの人」が「多くの修正をしている」箇所を特定し、その技術的負債の重み付けをするという手法と実装し、マネジメントの改善に用いたことがありました。

[Perl Hackers Hub 第8回　Perlによる大規模システム開発・設計のツボ（3） -技術的負債の可視化](https://gihyo.jp/dev/serial/01/perl-hackers-hub/000803)

当時はsvnとgitの２つを用いていましたが、それらのblameの結果から

```
SRP＝R＋U＋((L/100)－5)

R：修正リビジョンのユニーク数
U：修正ユーザのユニーク数
L：モジュールのライン数
```
などから、単一責務原則に違反したモジュールを探索するということを行いました。

## ジニ係数を用いて安定度をする
gilotでは、「チームのコミット量がどれだけ安定しているか」を**ジニ係数**を用いて、可視化します。

ジニ係数は、不平等性をあらわす経済学の指標です。所得格差などが大きくなると１に近づき、小さくなると0に近づきます。

> ジニ係数がとる値の範囲は 0 から 1 で、係数の値が大きいほどその集団における格差が大きい状態であるという評価になる。特にジニ係数が 0 である状態は、ローレンツ曲線が均等分配線に一致するような状態であり、各人の所得が均一で、格差が全くない状態を表す。逆にジニ係数が 1 である状態は、ローレンツ曲線が横軸に一致するような状態であり、たった1人が集団の全ての所得を独占している状態を表す。社会騒乱多発の警戒ラインは、0.4である。
wikipedia : [ジニ係数](https://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%8B%E4%BF%82%E6%95%B0)

ここでジニ係数をもう少しイメージするために、ちょっと懐かしい「世界がもし１００人の村だったら」の寓話を用いて、ジニ係数を計算してみましょう。

> すべての富のうち
６人が５９％をもっていて
みんなアメリカ合衆国の人です
７４人が３９％を
２０人が、たったの２％を分けあっています
 「世界がもし１００人の村だったら」より引用

このストーリーから分かる通り、世界は不平等で一部の人に富が偏っているように思えます。この偏り度合いを数値化するにはどうしたら良いのでしょうか。その１つの方法としてジニ係数は用いられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/01cfde07-478c-962f-32e3-a08379ca6944.png)


カテゴリごとに下から並べて、富の累積比率と人口の累積比をプロットしていきます。この点を結んだ曲線をローレンツ曲線といいます。それに対して、すべての人が同じ富をもっていることを想定した場合の直線を均等分布線といいます。

ジニ係数は、ローレンツ曲線と均等分布線の差の積分を撮ったBの部分と、均等分布線を積分したAの部分の比率で表されます。不平等なほど格差が増えていくわけです。この村の例だと、0.59になります。

### ジニ係数を用いたソーシャルゲームの健全状況の予測
このようなジニ係数は、ソーシャルゲームの健全さを測るためにも用いられてきました。一部のコアユーザのみが重課金をしていて、ライトユーザーの割合が少ないという状況が続き、格差が広がってくるとゲームは面白くなくなっていきます。健全なコミュニティでは、強いユーザーに勝ったり逆転できるかもという期待があるものです。あまりに差が付きすぎてしまうと、面白くなくなってしまいます。

### コミット量の単位時間ごとの格差が大きいチームと小さいチーム

gilotで注目するのは、経済格差ではありません。また、個々人のコミット量の格差でもありません。注目するのは、「あるタイムスロットごと」の「コミット量全体」がどのようにばらついているかです。

たとえば、この１年間のうち、ある2週間には10万行位以上書き換えられたのに、その他の2週間はほとんどソースコードに触れることはなかったというケースを考えてみましょう。このような状況は、開発サイクルが重く、健全さにかけるリリースプロセスや自動テストが充実していないことによる手動テストの手間などの影が見え隠れします。

あるいは、企画フェーズと開発フェーズが極端に分かれていたり、年末・年度末に向けての開発といったロードマップ志向の開発プロセスを行うためにその時期に向けて大量の変化起こるといった場合にもジニ係数は大きく、格差が拡大していきます。

一方、継続的改善を繰り返す安定したチームは、masterなどの「本番」「リリース」ブランチへのマージが早く、ブランチの生存期間が短い傾向があります。継続的インテグレーションやデプロイメントが充実しているほど、安定してソースコードを改善していくことができます。

このように安定したアウトプットができる状態はチームが一定健全に回っていることの１つのエビデンスになりえます。開発者の生産性について、ソースコードの量自体は、なんら直接的なファクトにはなりませんが、全体に対する割合や修正の度合い、ある期間ごとのでの変化などは見る価値のある統計指標になると考えます。

# gilot (ジロー)の使い方
今回開発したツールの使い方を紹介します。
GitHubはこちらです：https://github.com/hirokidaichi/gilot

## インストール
```
pip install git+https://github.com/hirokidaichi/gilot
```

## 簡単な使い方
gilotは、3つのサブコマンド持っています。それをパイプで組み合わせて使います。
あるリポジトリから、グラフを作成するには単純に以下のように行います。

```
gilot log REPO_DIR | gilot plot
```
``gilot log``は対象リポジトリからcsvを生成します。``gilot plot``はそのCSVからグラフを生成します。
``gilot log``は時間がある程度かかりますので、一度CSVをファイル出力して保存し、その上で``gilot plot``を行うことをおすすめします。

```
gilot log REPO_DIR > repo.csv
gilot plot -i repo.csv -o graph.png
```
画像ではなく単に、統計情報が欲しい場合は

```
gilot log REPO_DIR | gilot info > stats.json
```
のように、``info``サブコマンドが使えます。出力はjson形式です。

```
gilot log REPO_DIR | gilot info | jq .gini
```
jqコマンドと組み合わせれば、ジニ係数のみ表示するなど必要な統計情報のみを取得することもできます。

## 期間の指定、ブランチの指定
git logの情報取得にあたって期間を指定することができます。
２つの指定方法があり、何ヶ月間のデータを取得するかの``--month``といつからのデータを取得するのかを指定できる``--since``の２つのオプションがあります。デフォルトは６ヶ月間です。

```
gilot log REPO --since 2020-01-20 -o REPO.csv
gilot log REPO --month 18 -o REPO.csv
```

また、ログを取得するブランチも指定することができます。デフォルトでは``origin/HEAD``を参照してmasterに相当するものを指定するようにしていますが、開発チームのブランチ運用の方法に応じて指定をしてください。できるかぎり多くの人が触れる可能性があり、リリースされていたり、運用されているシステムと同じコードベースのbranchがツールの特性上は望ましいです。

```
gilot log REPO --branch develop -o REPO.csv
```

## 複数のリポジトリにまたがって、チーム運営している場合
現代的なチームでは、１つのシステムを提供するのに複数のリポジトリを１つのチームが管理していることが度々あるかと思います。
モノレポ構成になっていないようなマイクロサービスアーキテクチャではなおさら、多くのリポジトリに１つのチームが手を加えることがあるでしょう。

このような場合にもそれぞれのリポジトリの結果を結合して評価することができます。単純には以下のような方法です。

```
gilot log repo-a > repo-a.csv
gilot log repo-b > repo-b.csv
gilot plot -i repo*.csv
```

## Pythonのライブラリとして用いてnotebookで使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/43063883-ec71-18e1-f93c-c13da99006c5.png)
https://github.com/hirokidaichi/gilot/blob/master/sample/sample.ipynb

# 4つのグラフとその見方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/75e9d58d-8b34-b3c2-72aa-2d033fa8b4f5.png)


## fig.1：ジニ係数とローレンツ曲線のグラフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/86f3c711-7676-87e6-d079-b9952b0861ae.png)
タイムスロットごとのコミット行数量のローレンツ曲線とジニ係数を表示しています。

ジニ係数がどの値以下であれば、安全かそうでないかという統一的指標はありません。個人的な観察としては、0.5以下であれば安定したチームのアウトプットがあり、大きければ何らかのファクターが安定したコード出力を妨げているのではないかというのが所感です。

この値は、絶対値に注目するよりも、複数の事業システムがある場合に比較してみるのがよいかもしれない。いわゆるレガシーと呼ばれるものと、最近作ってチームで開発しているものには、大きな差がでてくることがあります。


## fig.2:タイムスロット(2週間)あたりのコミット量の分布
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/ec4c580c-0c5d-b65b-a85a-3b937a6a667c.png)
あるタイムスロットのコード出力量のヒストグラム。ピークのなだらかな山なりになると、チームの活動の安定がよりわかりやすい。

外れ値がいくつもある場合、大きな機能改修・リファクタリング・棚卸しなどの削除等の影響の可能性もあります。


## fig.3：タイムスロット(2週間)あたりの実際の追加・削除行数とその差
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/3d9483f8-98bd-582d-bde8-345b6e7dfdda.png)
タイムスロットごとの削除行数・追加行数・総変更行数の推移。緑のエリアが多いほど、機能追加がされており、赤いエリアがリファクタリングや棚卸しなどが行われている可能性を示しています。
総変更行数における削除行数の割合をリファクタ指数として表示しています。とはいえ、単なる割合なのでリファクタリングとは限らないため注意が必要です。


## fig.4：タイムスロット(2週間)あたりのコミットした開発者の人数
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/e794b664-1189-358d-fc07-385cdac83397.png)
大規模な組織での開発が進むほど、一体何人くらいが実際にはソフトウェアの開発にたずさわっているのかわかりにくくなります。
それらの実態を可視化するため、ある二週間にコミットしたひとの平均値と推移を表示している。兼務などで一部の人数しか関われていない場合なども含めて、おおよそ定常的にリポジトリに手を入れている人間(ボットも含んでしまうが。。)の数がわかる。

より詳細な情報が取得したい場合には、次のようにinfoコマンドを用いてデータを取得することができる。

```
gilot info -i.csv | jq .authors                                                                              
{
  "mean": 13.357142857142858,
  "std": 4.70036238958302,
  "min": 4,
  "25%": 10,
  "50%": 15,
  "75%": 16,
  "max": 21
}
```
標準偏差が大きくなったり、maxとmeanの差が激しくなる場合も不健全な状態を暗喩している可能性があります。

# 注意点と実態把握のための手段

gilotの出力は、あくまでリポジトリに対するアクティビティの統計データでしかありません。チームやシステムの実態を、健康診断的にあるいは、毎朝の検温と同じレベルに手軽に観察・アセスメントするためのものです。これを持って病気であるとか、不健全であるとするためのツールではありません。

より詳しい実態についての評価や比較を行いたい場合は、日本CTO協会で公表しているDX Criteriaの調査項目を利用するのがよいでしょう。こちらは、システムと企業全体の人間ドックにあたります。

 + [DX Criteria](https://github.com/cto-a/dxcriteria)

ビジネスインテリジェンスのためのデータ活用が叫ばれていますが、今後エンジニアリングインテリジェンス(ソフトウェア開発のデータ分析と見える化）も重要になってきています。そのための１ツールとしてご利用ください。

# 活用への期待
このツールは何しろ手軽にリポジトリの状態を可視化します。情報の中にほとんど機微な情報が含まれないため、外部に公開しても問題はないのではないでしょうか。むしろ、現在我々はこんなかんじでシステム開発をしているよということがわかるようにリアルタイムで採用ページに乗ってくれたりすると、ああ、こんなかんじなんだーとわかって便利ですね。

# サンプルケース
以下、著名なOSSプロジェクトのこの半年間のgilot結果を掲載します。

### facebook/react
![image](https://raw.githubusercontent.com/hirokidaichi/gilot/master/sample/react.png)


### microsoft/TypeScript
![image](https://raw.githubusercontent.com/hirokidaichi/gilot/master/sample/TypeScript.png)

### tensorflow/tensorflow
![image](https://raw.githubusercontent.com/hirokidaichi/gilot/master/sample/tensorflow.png)

### pytorch/pytorch
![image](https://raw.githubusercontent.com/hirokidaichi/gilot/master/sample/pytorch.png)

### optuna/optuna
![image](https://raw.githubusercontent.com/hirokidaichi/gilot/master/sample/optuna.png)

# あわせて読みたい
+ ["技術的負債"論の道案内 - アーキテクチャの資本コストと情報の非対称性](https://qiita.com/hirokidaichi/items/c66682a64ac2fc59cdf3)
+ [なぜ、組織のつくりとソフトウェアアーキテクチャは似てしまうのか]
(https://qiita.com/hirokidaichi/items/d12fcce80ee593bcf34d)
+ [エンジニアリングマネージャ/プロダクトマネージャのための知識体系と読書ガイド](https://qiita.com/hirokidaichi/items/95678bb1cef32629c317)