ストーリー
高橋アーキテクトがホワイトボードにグラフを描き始めました。
技術的負債とは
技術的負債(Technical Debt)とは、短期的な都合で妥協した設計やコードが、将来の開発速度を低下させる現象です。
// 技術的負債の例:急いで書いた注文処理
function processOrder(data: any) {
// TODO: バリデーション追加する
// TODO: エラーハンドリング追加する
const db = require('./db'); // 直接依存
db.query(`INSERT INTO orders VALUES ('${data.id}', '${data.name}', ${data.price})`);
// SQLインジェクションの危険性
// テスト不可能な構造
// 変更のたびに影響範囲が不明
}
負債が蓄積するとどうなるか
| 期間 | 開発速度 | 品質 | チームの状態 |
|---|---|---|---|
| 初期(0-3ヶ月) | 非常に速い | 問題なし | 意欲的 |
| 中期(3-6ヶ月) | やや低下 | バグ増加 | 不安を感じ始める |
| 後期(6-12ヶ月) | 大幅低下 | 頻繁な障害 | 疲弊 |
| 末期(12ヶ月以降) | ほぼ停滞 | 全面書き直しの議論 | 離職者発生 |
コード品質の4つの柱
1. 可読性(Readability)
他の開発者(未来の自分を含む)がコードを素早く理解できるか。
// 低い可読性
function calc(a: number[], t: number): boolean {
let s = 0;
for (let i = 0; i < a.length; i++) {
s += a[i];
}
return s >= t;
}
// 高い可読性
function isBudgetSufficient(expenses: number[], threshold: number): boolean {
const totalExpenses = expenses.reduce((sum, expense) => sum + expense, 0);
return totalExpenses >= threshold;
}
2. 保守性(Maintainability)
変更を加えやすいか。1箇所の変更が他に波及しないか。
// 低い保守性:変更が波及する
class OrderProcessor {
process(order: Order) {
// 税計算、在庫チェック、メール送信が全部ここに...
const tax = order.price * 0.1; // 税率変更時にここを探す必要がある
// ... 500行のコード
}
}
// 高い保守性:関心事が分離されている
class OrderProcessor {
constructor(
private taxCalculator: TaxCalculator,
private inventoryChecker: InventoryChecker,
private notificationService: NotificationService
) {}
process(order: Order) {
const tax = this.taxCalculator.calculate(order.price);
this.inventoryChecker.reserve(order.items);
this.notificationService.sendConfirmation(order);
}
}
3. テスト容易性(Testability)
ユニットテストを書きやすい構造か。
// テストしにくい:外部依存が埋め込まれている
class PriceCalculator {
calculate(productId: string): number {
const db = new Database(); // 直接生成
const product = db.find(productId);
const rate = fetch('https://api.exchange.com/rate'); // 外部API
return product.price * rate;
}
}
// テストしやすい:依存が注入される
class PriceCalculator {
constructor(
private productRepository: ProductRepository,
private exchangeRateService: ExchangeRateService
) {}
calculate(productId: string): number {
const product = this.productRepository.find(productId);
const rate = this.exchangeRateService.getRate();
return product.price * rate;
}
}
4. 信頼性(Reliability)
エッジケースや異常系を適切に処理しているか。
// 低い信頼性
function divide(a: number, b: number): number {
return a / b; // b が 0 のときは?
}
// 高い信頼性
function divide(a: number, b: number): Result<number, DivisionError> {
if (b === 0) {
return { ok: false, error: new DivisionError("0で除算できません") };
}
return { ok: true, value: a / b };
}
コード品質への投資対効果
高橋アーキテクトはこう言います。
「品質への投資は、最初はコストに見える。でも2週間を超えたあたりから、高品質なコードのほうが開発速度で逆転する。これは経験則ではなく、多くのプロジェクトで実証されている事実だ」
品質を保つための活動:
- コードレビュー — 問題を早期に発見する
- リファクタリング — 継続的に構造を改善する
- テスト — 変更の安全性を保証する
- 設計原則の適用 — 最初から良い構造を作る
まとめ
| ポイント | 内容 |
|---|---|
| 技術的負債 | 妥協した設計が将来の開発速度を低下させる |
| 可読性 | コードを素早く理解できるか |
| 保守性 | 変更を安全に加えられるか |
| テスト容易性 | ユニットテストが書きやすいか |
| 信頼性 | 異常系を適切に処理しているか |
チェックリスト
- 技術的負債の概念を理解した
- コード品質の4つの柱を説明できる
- 品質への投資が長期的に速度を生むことを理解した
次のステップへ
次は「コードの臭いを嗅ぎ分けよう」です。品質の低いコードに共通する特徴 — コードスメル — を学び、問題を検出する目を養います。
推定読了時間: 25分