自己紹介
- 名前: 政倉 智 (まさくら とも)
- 所属: codeArts 株式会社
- 所属: html5j 鹿児島
- 趣味: バイク
- 最近は...
- OAuth/Open ID Connect の RFC 読んだり
- ASP.NET Core のソースコード読んだり
はじめに
技術的負債の話って幅が広いですね!
私が混乱してます
今日は特にプログラム方面のお話を中心にします
技術的負債って?
ググるとよさげなドキュメントがいっぱい出てくる
- 長いメソッド
- ドキュメントがない、もしくはドキュメントがあてにならない
- コメントがない、もしくはコメントがあてにならない
- 複雑な構造
- etc...
分かりやすく言うと
「修正をやりたくない」
と思ったら、そこに技術的負債がある
(政治的な負債なこともあるけど...)
例を挙げると
- 修正をしたら、予想がつかないところがバグった
- バグフィックスで、どこを修正すればいいのかわからない
- バグフィックスで、修正箇所がたくさんある
まあ、みんな経験しているよね!
結果として
- 開発速度が落ち、競争についていけなくなる
- 残業が増える
- 利益がなくなる
- やる気がなくなる
- どんどんこれらが進行する
やりたい人、いないよね!
どのように貯めるのか?
どのように貯めるのか?貯まるのか?
本題に入る前にちょっと理解しておいてほしいことです
技術的負債ってこういう感じで貯まると思ってませんか?
「技術的負債」とはよく言ったもんで、利子があります
放置すればするほど増えます!
しかも、出発点ですでに技術的負債は貯まってます
(技術的負債を抱えたプロジェクトを手本にするから)
ちなみに、利子がつかないチームはかなり優秀です!
- 技術的負債は想像以上に貯まります
- 利子が付きます
- 返済しないとジリ貧になりやすい
なぜ貯まるのか?
プレッシャーです
- 納期
- 予算
- 技術的負債により、開発速度は当初の速度を維持できなくなります
- それを取り返すために品質が犠牲になります
- さらに技術的負債と利子が貯まり、どんどん悪化します
- 結果的に、納期と予算にも影響を及ぼします
返済の選択肢
技術的負債の返済方法
- 貯めない
- 少しずつ返す
- まとめて返す
- 流れに身を任せ、返さない
貯めない
それができれば苦労しませんて...
ただし、貯めないための努力は必要
- リファクタリングや振り返りの時間をスケジュールに組み込む
- やりすぎに注意
少しずつ返す
これがベスト
- 技術的負債になるかどうかはやってみないとわからない
- 負債となったらなるべく早く返す
- 機能追加やバグ修正の作業をはじめる前に少しだけ返す
- 負債返却日の導入
書籍「アジャイルソフトウェア開発の奥義」ではこういうルールを紹介している
- 一度目の修正は、技術的負債の貯まる方法で
- 同じ場所への二度目の修正は、その後何度も変更があるとみなし、対処する
大きく返す
少しずつ返すのに比べると難易度が高い
- 返済計画と返済で何がよくなるかを上司や客に説明の必要が出てくる
- チーム内での連携が必要になる
- なるべくこれをせずに済むのがベスト
流れに身を任せ、返さない
- 選択肢としてはあり
- どうしようもなくなってしまい、この状態で安定することも
- 西日本と東日本での交流電源の周波数の違い
- JR 各社で信号の系統が違う
- etc...
探せば日常的にたくさんあると思う
でも、やめてね!
どれがいい?
どれをというより、すべてやる感じで
- リファクタリングは細かくスケジューリングする (貯めない)
- 負債が少し貯まったら対処する (少しずつ返す)
- どうしようもなくなったら計画を練る (大きく返す)
- どうしようもないものは放置! (返さない)
一番の敵はプレッシャーなので、そこを何とかするってのが本当の正解
技術的負債は利子がつくので
対処を遅らせればそれだけ時間がかかるようになることを意識しましょう
対処する技術的負債の選定
個人的には、こういうところが最優先
- 重複 (いわゆるコピペ)
- 修正が集まるところ
- 予想外のところがバグる
重複
重複はリファクタリングがかなり難しいので早めに対処する必要があります
void Method1()
{
// 似たような処理
}
void Method2()
{
// 似たような処理
}
これをリファクタリングしていくわけですが
まずは片方からメソッドを抽出
void Method1()
{
CommonMethod();
}
void Method2()
{
// 似たような処理
}
void CommonMethod()
{
// Method1 の処理
}
異なる部分をパラメーター化
void Method1()
{
CommonMethod("method1", 15);
}
void Method2()
{
// 似たような処理
}
void CommonMethod(string type, int max)
{
// 共通の処理
}
もう片方もそれを使うようにする
void Method1()
{
CommonMethod("method1", 15);
}
void Method2()
{
CommonMethod("method2", 10);
}
void CommonMethod(string type, int max)
{
// 共通の処理
}
この時、Method2
は動かなくなる可能性が高い
-
Method2
はMethod1
と違って書き直しになってる - 実際のコードでは、かなり差異がある
- インデントがくるってる
- 修正のたびにコメント化されていたり
- 横展開で少しずつ展開内容が違ったり
- 後から対処しようとした時のコスト増がすごい
手遅れになりやすいので、最優先で対処!
修正が集まるところ
- 特に、修正の競合が起きる場所
- 長いコードで起きやすいけど、長くても起きないときもある
「単一責任の原則」に違反しているところ
「単一責任の原則」とは?
クラスを変更する理由は複数存在してはいけない
var cost = 0;
var point = 0;
foreach (var rental in rentals) {
if (rental.Type == "new") cost += days *= 300;
else if (rental.Type == "old") {
cost += 300;
if (days > 3) cost += (days - 3) * 150;
point += days;
if (rental.Type == "new") point += 3;
}
}
- 修正の競合が起きやすい
- 競合の解決は失敗する危険性がある
- コミット間隔が開きがちになる
- より競合が起きやすくなり、より失敗しやすくなる
- クラスやメソッドの名前が合わなくなりやすい
- 読みにくい
これに限らず、プログラム設計の原則は非常に重要なので参考にするとよいと思う
- 単一責任の原則
- 安定依存の原則
- 依存関係逆転の原則
- DRY
- etc...
予想外のところがバグる
- この状況はある程度大掛かりな対処が必要になる
- マジ苦しい
ツールを使うんだ!
技術的負債の進行を遅らせるためにも
ツールに頼ろう!
- 性能のいいパソコン
- 静的コード検査 (など)
- テスト自動化ツール
- コードレビューツール
- クラウド
- 統合開発環境
- CI/CD
- etc...
性能のいいパソコン
- SSD にメモリ 8GB over はもう当たり前かと
- お金で解決しちゃいましょう!
- ノートとは別にデスクトップを持つのもオススメ
静的コード検査
- コードの些細な問題を指摘してくれる
- 統合開発環境に組み込んでおくとよし
- 間違っても、納品前に通すだけとかしないこと
テスト自動化ツール
- 返済のための修正の動作担保のため、テストの自動化は必須
- 単体テストからはじめて、慣れたら機能テストとか UI テストにチャレンジ
コードレビューツール
- チーム開発だと必須になる
- Pull Request (GitHub) や Merge Request (GitLab) はまあまあいいツール
- 早めのレビューと早めの修正
クラウド
- 試したい時にすぐに模擬環境を作れるのがベスト
- 一時的に使うなら、大した金額ではない
統合開発環境
- コード検査ツールとか、リファクターとかデバッガとか、超便利
- 重いけど、お金の力でなんとかするとよい
CI/CD
- CI とは、ビルドや自動テストをコミットのたびに自動で行います
- その分、問題の検出が早くなります
- デプロイまで自動でやることもできます
つまるところ...
- ツールで技術的負債がなんとかなったりはしないけど
- ツール無しで技術的負債を何とかすることはできない
おまけ
参考資料
説得をするときの注意
- 説得はかなり大変です!
- 特に、上司がその上司や客に説明する場合
- 許可を出した方は、技術的負債が解消し、そのごの開発速度が飛躍的に向上することを期待しています
- 開発チームはすべての技術的負債が見えているわけではありません
- 開発チームで見積もった時間はすぐに足りなくなります
- 説得に時間がかかりそうなら、辞めちゃいましょう! たぶん長続きしません!
作り直しは避けてください
作り直しはあまりいいことがありません
- 元の状態をちゃんと規定できないといけません
- 動かない状態を長く続けるのはモチベーションの維持が難しい
- ついでに機能追加でもしたらもう大変です
冷静になって考えましょう
- 長いコードもすべてがだめってわけじゃないです
- 再利用できるところもたくさんあります
- まずはリファクタリングで、使えそうなところを抽出しまくります
- それらを組み合わせて新しい部分を書きます
- すぐに戻せるって大事よ!
こういう長いメソッドも...
再利用したいところだけ抽出して...
新しく書き足したところから使う
- 動かなくなるリスクを減らせる
- すぐに元に戻せる
改善をする場合
作り直しはだめ
こう!
アンチパターン
- 遅いパソコンを使わせる
- 出来上がるまでコミットさせない
- データベースやサーバーアプリを開発者全員で共有する
- 修正前に修正計画を提出させる
- 開発環境の構築を難しくする
終わりに
- うまくまとめられなくてごめんなさい
- 技術的負債の返却って、技術だけじゃないのでその辺がしんどい
ご清聴ありがとうございました!