LESSON 25分

ストーリー

高橋アーキテクトがホワイトボードにグラフを描き始めました。

高橋アーキテクト
このプロジェクトは最初、すごいスピードで機能を追加できた。でも半年後、1つの機能追加に3倍の時間がかかるようになった。なぜだと思う?
あなた
バグが増えたから…ですか?
高橋アーキテクト
それは症状だ。原因は”技術的負債”が積み重なったこと。今日はこの話をしよう

技術的負債とは

技術的負債(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分