LESSON 40分

「アーキテクチャの劣化は気づかないうちに進む」と佐藤CTOは言った。「フィットネス関数は、アーキテクチャの健全性を継続的に測定する自動化されたチェックだ。ArchUnitのようなツールで依存関係ルールをテストとして書けば、CIで毎回検証できる。」

1. フィットネス関数の概念

“Building Evolutionary Architectures” (O’Reilly) で提唱された概念

種類説明
アトミック単一の特性を測定レイテンシ < 500ms
ホリスティック複数の特性を組み合わせて評価セキュリティ + パフォーマンス
トリガー型イベント駆動で実行デプロイ時にチェック
継続型常時監視SLOダッシュボード

2. 自動化されたアーキテクチャテスト

ArchUnit(Java/TypeScript相当のアプローチ)

// アーキテクチャルールをテストとして定義
// dependency-cruiser を使用(TypeScript向け)

// .dependency-cruiser.cjs
module.exports = {
  forbidden: [
    {
      name: 'domain-must-not-depend-on-adapters',
      comment: 'ドメイン層はアダプター層に依存してはいけない',
      severity: 'error',
      from: { path: '^src/domain' },
      to: { path: '^src/adapters' },
    },
    {
      name: 'domain-must-not-depend-on-application',
      comment: 'ドメイン層はアプリケーション層に依存してはいけない',
      severity: 'error',
      from: { path: '^src/domain' },
      to: { path: '^src/application' },
    },
    {
      name: 'no-circular-dependencies',
      comment: '循環依存を禁止',
      severity: 'error',
      from: {},
      to: { circular: true },
    },
    {
      name: 'adapters-must-not-depend-on-each-other',
      comment: 'アダプター間の直接依存を禁止',
      severity: 'warn',
      from: { path: '^src/adapters/([^/]+)' },
      to: { path: '^src/adapters/(?!$1)' },
    },
  ],
};

// CI で実行: npx depcruise src --config .dependency-cruiser.cjs

カスタムフィットネス関数

// テストとして書くフィットネス関数の例
describe('Architecture Fitness Functions', () => {
  test('APIレスポンスサイズが1MB以下', async () => {
    const endpoints = ['/api/products', '/api/users', '/api/orders'];
    for (const endpoint of endpoints) {
      const res = await fetch(`http://localhost:3000${endpoint}`);
      const body = await res.text();
      expect(body.length).toBeLessThan(1_000_000);
    }
  });

  test('外部依存のライセンスがOSS互換', () => {
    const pkg = require('./package.json');
    const forbiddenLicenses = ['GPL-3.0', 'AGPL-3.0'];
    // license-checker 等で検証
  });

  test('DBマイグレーションが後方互換', () => {
    // 新しいマイグレーションが destructive change を含まないことを検証
    // DROP COLUMN, ALTER TYPE 等がないことを確認
  });
});

3. メトリクスベースのフィットネス関数

// 組織のアーキテクチャ適合度スコアリング
interface FitnessScore {
  category: string;
  metric: string;
  target: number;
  actual: number;
  weight: number;
  score: number;  // 0-100
}

function calculateArchitectureFitness(scores: FitnessScore[]): {
  overallScore: number;
  details: FitnessScore[];
} {
  const totalWeight = scores.reduce((sum, s) => sum + s.weight, 0);
  const weightedSum = scores.reduce((sum, s) => sum + s.score * s.weight, 0);

  return {
    overallScore: Math.round(weightedSum / totalWeight),
    details: scores,
  };
}

const architectureFitness = calculateArchitectureFitness([
  { category: 'Performance', metric: 'p95 Latency (ms)', target: 500, actual: 380,
    weight: 3, score: 95 },
  { category: 'Reliability', metric: 'Availability (%)', target: 99.9, actual: 99.95,
    weight: 3, score: 100 },
  { category: 'Security', metric: 'CVE Count', target: 0, actual: 2,
    weight: 2, score: 60 },
  { category: 'Modularity', metric: 'Circular Dependencies', target: 0, actual: 1,
    weight: 2, score: 70 },
  { category: 'Deployability', metric: 'Deploy Frequency (per week)', target: 10, actual: 8,
    weight: 1, score: 80 },
]);
// overallScore: 84/100

4. フィットネス関数のCI/CD統合

# .github/workflows/architecture-fitness.yml
name: Architecture Fitness Check
on: [pull_request]
jobs:
  fitness:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - name: Dependency Rule Check
        run: npx depcruise src --config .dependency-cruiser.cjs
      - name: Bundle Size Check
        run: npx size-limit
      - name: License Check
        run: npx license-checker --failOn 'GPL-3.0;AGPL-3.0'
      - name: Architecture Tests
        run: npm test -- --testPathPattern='fitness'

まとめ

トピック要点
フィットネス関数アーキテクチャの健全性を自動テストで継続的に検証
依存関係ルールdependency-cruiserで層間の依存ルールを強制
メトリクス評価性能・信頼性・セキュリティ・モジュラリティをスコアリング
CI/CD統合PRごとにアーキテクチャ適合度を自動チェック

チェックリスト

  • フィットネス関数の種類(アトミック/ホリスティック)を説明できる
  • dependency-cruiserで依存関係ルールを定義できる
  • アーキテクチャ適合度スコアリングを設計できる
  • CI/CDにフィットネス関数を統合できる

次のステップへ

フィットネス関数を学んだ。次は 演習 で、アーキテクチャガバナンスを設計しよう。

推定読了時間: 40分