きのこるエフエムというPodCastに呼んで頂いた時に、
「ソフトウェア開発において、
 暫定対処で書いた(汚い)コードはコントロール下に置いておくことが大事」
というニュアンスの話をしたのですが。

言いっぱなしというのも、良くないと思ったので、
このエントリでは、コントロール下に置く手法を、具体的に提案したいと思います。

ep2. フルリモートで働くフリーランスエンジニア | kinokoru.fm / きのこるエフエム
https://anchor.fm/kinokoru/episodes/ep2---takemikami-e450qk

ここで提案する方法は、
GitHubのPullRequestによるGitFlowで開発を行っていることを前提としています。
(考え方自体は、他のフローでも応用できると思います)

GitHub PullRequestラベルによる暫定対処コードの識別

まず思いつく方法として、
暫定対処として、やむを得ずmasterにマージするコードには、
GitHubのラベル機能を使って、暫定対処ということが分かるようにしておく方法です。

pullreqdeploy01

暫定対処でマージしたPullRequesにtemporaryラベルを付け、
暫定を解消する修正を完了したらラベルを外すという運用をすれば、
暫定コードを含む改修の一覧を、
https://github.com/{ユーザ名 or 組織名}/{リポジトリ名}/labels/temporary
という感じのURLでアクセスすることが出来ます。

GitHubのREST APIを使えば、
シェルスクリプトで、暫定コードを含む改修のPR一覧を取得することも出来ます。

export GITHUB_ACCESS_TOKEN={ユーザ名}:{GitHubのAccessToken}
export GITHUB_REPO={ユーザ名 or 組織名}/{リポジトリ名}

curl -s -u $GITHUB_ACCESS_TOKEN \
  -X GET \
  https://api.github.com/repos/$GITHUB_REPO/pulls?state=closed \
  | jq -r '.[] | select(.labels[].name == "temporary") | [.number, .title] | @csv'

実行結果の例:

7,"Update something"
4,"Create something"

例えば、
crontabなどで定期的に実行して、開発定例会議の資料にし、
暫定コードの積み上げ&解消状況の把握、
担当割り振りを決めて暫定コードの解消計画を立てるという運用が考えられます。

List pull requests | GitHub REST API v3
https://developer.github.com/v3/pulls/#list-pull-requests

masterブランチの暫定対処コード率の算出

次にmasterブランチにマージされた暫定コードの行数を把握することを考えます。

前節のように暫定対処のPRにtemporaryラベルを付与する運用をしていれば、
以下のようなシェルスクリプトで暫定コードの行数を把握できます。

どこかのパスにmasterブランチをcloneしておき、
以下のシェルスクリプトをcrontabで定期的に実行するイメージです。

#!/bin/bash

export GITHUB_ACCESS_TOKEN={ユーザ名}:{GitHubのAccessToken}
export GITHUB_REPO={ユーザ名 or 組織名}/{リポジトリ名}
export GITHUB_MASTER_WORKING_COPY_PATH={masterをcloneしたパス}

cd $GITHUB_MASTER_WORKING_COPY_PATH
git pull

# temporaryラベルが付いたPullRequestの一覧を取得する
TEMPORARY_PR_LIST=$(curl -s -u $GITHUB_ACCESS_TOKEN \
  -X GET \
  https://api.github.com/repos/$GITHUB_REPO/pulls?state=closed \
  | jq -r '.[] | select(.labels[].name == "temporary") | .number')

# temporaryラベルの追加PullRequstに含まれるcommitのhashリストを作る
SHA_ARRAY=()
for num in $TEMPORARY_PR_LIST; do
  SHA_LIST=$(curl -s -u $GITHUB_ACCESS_TOKEN \
    -X GET \
    https://api.github.com/repos/$GITHUB_REPO/pulls/$num/commits \
    | jq -r '.[].sha')
  SHA_ARRAY=("${SHA_ARRAY[@]}" $SHA_LIST)
done

# masterブランチに対して、temporaryのcommitが含まれる行数を集計する
TOTAL_LINES=0
TEMPORARY_LINES=0
for f in $(git ls-files); do
  TOTAL_CNT=$(git blame $f | wc -l)
  TOTAL_LINES=$(($TOTAL_LINES+$TOTAL_CNT))
  for sha in ${SHA_ARRAY[@]}; do
    TEMP_CNT=$(git blame $f | grep ^${sha:0:8} | wc -l)
    TEMPORARY_LINES=$(($TEMPORARY_LINES+$TEMP_CNT))
  done
done

echo "暫定対処行数: $TEMPORARY_LINES"
echo "総行数: $TOTAL_LINES"

実行結果の例

暫定対処行数: 2
総行数: 4

このスクリプトでは、暫定対処行数と総行数を出力しているだけですが。
定期的に実行した値を残しておいて折れ線グラフなど可視化しておけば、
コードの品質の状態を把握でき、危機感も共有しやすくなると思います。
# 必要に応じて、ディレクトリ別・拡張子別の状況を出しても良いと思います。

それ以外に、CIに組み込んでmasterマージ後に、
「(暫定対処行数)/(総行数)」を計算して閾値を上回っている場合には、
slackなどに通知する、という運用も可能かと思います。

本番障害の対処、顧客要望や繁忙期に向けた急ぎの開発などで、
暫定対処のコードが増えてしまうことはやむを得ないとしても。
このように、暫定対処の状態を定量的に測っておけば、
工数を確保して、暫定解消のアクションを起こしやすくなるのではないでしょうか。

# 注:
# ここで書いたシェルスクリプトは、提案手法を説明するためのものなので、
# コードの量が多いリポジトリなどでは現実的な性能で動かないと思います。
# 実際に適用する場合は、
# 必要に応じ、他のプログラミング言語で書き直すなどの対処を行って下さい。