技術的負債とどうやって戦うか

# プロジェクトが進行するにつれて増える『負債』
長いプロジェクトに携わっていると、技術的負債をいつ返すのかが課題になってきます。
リファクタリングはいつの時点でやるのか、これは長いプロジェクトを運用していく上で問題になっていきますが、今回は負債の種類を整理し、それぞれどう対応をしていけばよいかを考えていきたいと思います。

# 私達の開発では常に時間が足りない
最近読んだ、「アジャイルサムライ」という本には下記のようなことが書いてありました。

**(開発における)3つの真実**

- プロジェクト開始時点にすべての要求をあつめることは出来ない
- 集めたところで要求はどれも必ずと言っていいほど変わる
- やるべきことはいつだって与えられた時間と資金よりも多い

https://www.amazon.co.jp/dp/B00J1XKB6K/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

以上のことからわかるように、私達の開発には時間が無いということが常だということがわかります。実際、技術的負債が多いプロジェクトほどこの傾向が強いのではないでしょうか。
そんな中で私たちは技術的負債を返していく方法を見つけなければいけません。


# 技術的負債を返す頻度について
## 技術的負債を返す頻度によって何が変わるのか
技術的負債を返す時にかかる時間と量は、技術的負債を溜めこんできた時間に比例するイメージです。

![技術的負債を返す_03.png](https://qiita-image-store.s3.amazonaws.com/0/73446/cc8dfc72-dd8d-4fe8-d8d3-18a3cfe4e5b9.png)


こうして蓄積されてきた技術的負債ですが、リファクタリングなどで技術的負債を返していく頻度によって、一回のリファクタリング作業で手をつける範囲と時間が変わってきます。
リファクタリングなどの間隔が長いほど一回あたりに返す負債がどんどん大きくなっていく傾向があります。つまり、細かく返すほど1回あたりの量が少なく済みます。ココらへんは本当に借金と同じですね。

![技術的負債を返す_07.png](https://qiita-image-store.s3.amazonaws.com/0/73446/c2f64ec6-d8c6-b0e9-e871-23370289b86e.png)


## 負債を返す頻度は多い方が良い
リファクタリングなどの頻度は個人的には多く取れたほうが良いかと思います（小さく返すパターン）。
例えば、年単位で負債が溜まっている場合には、一回のリファクタリングが数ヶ月かかるレベルになったりしますよね。
そうなっていった場合に一回一回の規模が大きくなっていくと、プロジェクトの決裁者になかなかスケジュール確保の申請を通すのが難しくなってきます。
できることなら細かい頻度で、なるべく負債を溜めないようにリファクタリングを行ったりすることをオススメいたします。

実際、数年分溜まった分の負債はそれだけでプロジェクト級になってしまうこともありますし、新しいことをしようにも負債を解消しないことには何も出来ないなんてことを経験したこともありました。


# 技術負債の種類
さて技術的負債と言っても、コーディングのレベルだけではなく様々な種類があります。
ちょっと私が思いつく限りまとめてみますと、

- コーディングのレベル（実装方法）の負債
- 負荷が考えられていない実装による制約などの負債
- バージョンアップすべき言語やライブラリ、OSの放置による負債
- トレンドが変わって乗り換える必要が出てきた場合の負債
- 共有不足で実装内容のブラックボックス化による負債

あたりがあるのではないかと思います。

## コーディングのレベル（実装方法）の負債
これは結構身に覚えがある方も多いと思いますが、よくある言い訳では

- 実装当時の自分の技術レベル的な問題
- タイトな納期で時間がなかった
- 初めて使ったライブラリだった

など色々要因はあると思いますが、むしろ全く負債なしに開発を終えられることは難しいのではないでしょうか。
どんなレベルのプログラマでもここの負債はなかなか減らすことは難しいのではないかと思っています。

### 負債の一例
- 1つの関数の行数が100行を超えた。
- 関数の引数が4つを超えた。
- 1つのクラスに処理を集めすぎて大きいクラスになりすぎた。
- 逆に、上手く設計できずクラスの関係がめちゃくちゃなど。

### 負債返済方法
細かなリファクタリング頻度を設ける方針で、開発で触る場合には必ずリファクタリングをスケジュールに組み込む等による返済が可能です。また、納期優先の開発の後にリファクタリング期間を必ず設けるなども良いと思います。
事前に負債を作らせないためにもチームによるコードレビューがとても効果的です。色んな人にレビューをしてもらって、極力下手な実装をしないように開発していきましょう。

## 負荷が考えられていない実装による制約などの負債
### 負債の一例
- DBの負荷が上がったり、サーバーの負荷が上がったりで負荷対策対応ばかり行って、新規開発が完全にストップする。
- DBをバッチ処理で更新をしたいが、インデックスなどが十分に考えられておらず、そもそも更新が出来ない。

### 負債返済方法
サーバーなどの負荷対策に関しては場合によってはサービス運営にも関わってくるので、負荷レベルによってはすぐさま対策をとるべきです。
こちらも設計のレビューなどを行ってもらうなど、コーディングに入る前に一度経験者に相談に乗ってもらうことをオススメいたします。

## バージョンアップすべき言語やライブラリ、OSの放置による負債
こちらは、結構作業としては重くなりがちなので気が乗らなかったりする場合もありますが、本当に放っておくとセキュリティ面的にも痛いしっぺ返しを受ける場合があります。
また、どうしても一回一回のメンテナンスが規模が大きくなりがちになってしまうのがバージョンアップデートです。

### 負債の一例
- 単純にバージョンアップを怠ったことによりバージョンアップがすんなりいかないパターン(互換性がなかったりアップデートのサポートがされてないなど)。
- フレームワークやライブラリ本体に手を入れてしまったことにより、バージョンアップができなくなったパターン。

### 負債返済方法
最近は各種バージョン管理ツールが出てきたことで、管理もある程度し易い環境になってきていますので、導入していない場合には導入を。
Ansibleなどの構成管理ツールなどで構成を管理し、環境を作っては捨てられるようにしてバージョン変更をなるべく楽に試せる環境を作っておく。
StackOverflowなどの記事で、ライブラリ本体に手を入れるような変更が勧められていても採用しない。

## トレンドが変わって乗り換える必要が出てきた場合の負債
キャッチアップを行っていても、こういった場合に負債が発生する場合があります。

### 負債の一例
- フロントエンドの開発ツールの変化が激しく、マイノリティになってしまった。(Gulp vs Gruntとか…)

### 負債返済方法
キャッチアップを積極的にできているプロジェクトであれば、マジョリティに移るのは比較的許容されやすいのではないでしょうか。
この時、周りの方はその技術を選択した人を責めるべきではありません、早い段階で積極的に取り入れようとしている文化がチームから無くなってしまうほうが大きな損失です。

## 共有不足で実装内容のブラックボックス化による負債
退職や共有不足による仕様のブラックボックス化はある程度は防げるのかなと思っておりますが、どうしても大量に人が入れ替わってしまうとどうしようもない場合があるかもしれません。

### 負債の一例
- 不具合が出た部分の仕様がわからずに、改修に時間がかかる。
- 新機能開発の際に知らなかった機能が出てきて、その対応でスケジュールが遅れる。

### 負債返済方法
開発担当者がいれば、開発担当者に改修の際にアドバイスを貰う。
設計の際にはなるべく多くの人にレビューしてもらう。
防止策としては設計に多くの人を巻き込んでレビューしてもらう。複数人が仕様について知っている状況をなるべくつくること。

# 負債を返すために戦う
技術的負債を返すために必要となるのは時間です。
時間は有限ですので、次にやりたい案件がいくつもある中で負債返済のための時間を確保する努力が必要になってきます。
どんなに気をつけていても負債というのは必ず発生するものですので、負債返済のためにもプロジェクトの決裁者にスケジュール確保のための交渉を行いましょう。

## プロジェクトの決裁者と交渉する
殆どのプロジェクトで決裁者はエンジニアではない場合が多いのではないでしょうか(むしろエンジニアであることのほうが稀です)。

セキュリティ的なリスクが有る場合などの時間は比較的決裁を取りやすいですが、リファクタリングのための時間を下さいという交渉はなかなか作業者のエンジニアからは難しい場合が多いです。

そこで、個人的には交渉の術としていろんな人を巻き込んでみることをおすすめします。
（周りの人を巻き込むのは良いアイデア、取り組みを周りの人に浸透させるのに使われる常套手段でもあります。）

## エンジニアの偉い人で技術的負債を返済することの大切さが分かる人に相談する
決裁者とできるだけ対等に話せるエンジニア長に相談してみましょう。
その際に、負債の返済について同じ意見を持っているエンジニアを集めたりしても良いです。
MTG形式でも飲み会形式で愚痴大会になってもいいかなと思います。チームに合ったやり方で相談してみて下さい。
エンジニアの偉い人からも同じように言ってもらえるようになると、技術的負債返済のための時間の確保がぐっと通りやすくなります。

## 最終的には決裁者に跳ね返ってくる
それでも、技術的負債の返済が認められない場合には、勝手にやってしまう（時間があるたびにこっそり行なう）、新規開発のスケジュールに組み込んどくなども、方法の一つだと思います。しかしそんな状況が続くようではエンジニアのモチベーションも上がりません（自己成長などを考える場合などは特に）。
段々とチームの開発では技術負債部分が毎回ネックになり、リリースが遅くなって開発がなかなか進まなくなります。

ちょうど下記のグラフのような感じです。
![コードと品質.jpg](https://qiita-image-store.s3.amazonaws.com/0/73446/667f028a-eaca-37a1-b235-8e6887b0ac68.jpeg)

出典：http://postd.cc/moving-fast-with-high-code-quality/

こんな状況では優秀なエンジニアはチームに残らないでしょう。

# 技術顧問として負債と戦う
CTOや技術マネージャーなどの立場の方はこれらの問題に積極的に向き合う必要があります。
CTOや技術マネージャーなどの立場の方が向き合わなかった場合、社内の誰が技術的負債の返済をプロジェクトの決裁者と交渉することができるのでしょうか。また、会社のメインのプロジェクトなどでは開発案件が特に活発です。そういったプロジェクトで最終的に開発が進まなくなったり、エンジニアが抜けてしまったりするリスク回避のためにも、積極的に取り組んだ方が私は良いと思います。


# まとめ
技術的負債の返却は個人プレーでは出来ません。
私達は開発する段階での設計のレビューや書いたコードのレビューなど、リリースされる前に出来る、負債を作らない方法もありますので、それらを積極的に取り入れて負債を作らないようにチームで取り組むのが、正しい道なのではないかなと思います。