📐
適応度関数(Fitness Functions):アーキテクチャ特性を自動検証する
Fitness Function の定義・分類マトリクス・実装例を整理する。テストが機能を守るのに対し、適応度関数はアーキテクチャの特性を守る
Fitness Function とは
最適化理論では Fitness Function は「解の良さを測る指標」を意味する。進化的アーキテクチャではこれを借用し、アーキテクチャが守るべき特性(パフォーマンス・結合度・セキュリティなど)を継続的に検証する仕組みを指す。
テストとの違いは検証対象だ。
| テスト | Fitness Function | |
|---|---|---|
| 守るもの | 機能の正しさ(ビジネスロジック) | アーキテクチャの特性(構造・品質属性) |
| 実装場所 | テストファイル(unit/integration) | CI パイプライン・インフラ監視 |
| 例 | 「注文の合計金額が正しいか」 | 「循環依存が存在しないか」「P99 が 200ms 以内か」 |
分類マトリクス
Fitness Function は 3 軸で分類される。
軸1: 原子的 vs 全体的
| 原子的(Atomic) | 全体的(Holistic) | |
|---|---|---|
| 意味 | 単一のアーキテクチャ特性を検証 | 複数の特性を組み合わせて検証 |
| 例 | 循環依存の検出 | レイテンシ × エラーレート × スループットの複合条件 |
軸2: 自動 vs 手動
| 自動(Automated) | 手動(Manual) | |
|---|---|---|
| 意味 | CI/CD で継続的に実行 | レビュー・監査など人間が実施 |
| 例 | ArchUnit での依存関係チェック | アクセシビリティ監査・セキュリティレビュー |
軸3: 一時的 vs 継続的
| 一時的(Temporal) | 継続的(Continual) | |
|---|---|---|
| 意味 | 移行期など特定期間だけ有効 | 恒久的に CI で動かし続ける |
| 例 | データ移行中の整合性チェック | レイテンシ閾値・依存制約 |
実例(カテゴリ別)
原子的 × 自動 × 継続的:循環依存検出
// ArchUnit(TypeScript 版ツールのイメージ)
// src/domain が src/infrastructure を import していないことを検証する
// ビルド時に実行し、違反したら CI を落とす
import { checkDependencies } from 'arch-unit-ts';
checkDependencies({
noCircularDependencies: true,
layerRules: [
// domain は infrastructure に依存してはいけない
{ from: 'src/domain', to: 'src/infrastructure', allowed: false },
{ from: 'src/usecase', to: 'src/domain', allowed: true },
],
});
全体的 × 自動 × 継続的:レイテンシ P99 閾値(k6)
// k6 ロードテストを CI で定期実行し、P99 が 200ms を超えたら失敗とする
import { check } from 'k6';
import http from 'k6/http';
export const options = {
thresholds: {
// Fitness Function: P99 が 200ms 以内であること
http_req_duration: ['p(99)<200'],
// Fitness Function: エラー率が 1% 以内であること
http_req_failed: ['rate<0.01'],
},
};
export default function () {
const res = http.get('https://api.example.com/orders');
check(res, { 'status is 200': (r) => r.status === 200 });
}
全体的 × 手動 × 継続的:アクセシビリティ監査
自動化が難しい特性は手動で定期実施する。WCAG 準拠チェックをリリースサイクルごとにチェックリスト化し、記録を残す。
原子的 × 自動 × 一時的:移行期のデータ整合性チェック
// 旧カラムと新カラムの値が一致していることを確認する(Expand-Contractの移行期だけ有効)
// 移行完了後にこのチェックを削除することを前提に書く
async function validateMigrationConsistency(db: Database): Promise<void> {
const inconsistent = await db.query(`
SELECT id FROM users
WHERE old_email IS NOT NULL
AND new_email IS NOT NULL
AND old_email != new_email
LIMIT 10
`);
if (inconsistent.rows.length > 0) {
throw new Error(`データ不整合が検出されました: ${inconsistent.rows.length} 件`);
}
}
CI/CD への組み込みイメージ
# .github/workflows/fitness-functions.yml
name: Fitness Functions
on: [push, pull_request]
jobs:
architecture-constraints:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pnpm install
# 原子的 × 自動 × 継続的
- run: pnpm arch:check # 循環依存・レイヤー制約
performance-baseline:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 全体的 × 自動 × 継続的(main ブランチのみ)
- run: k6 run fitness/perf-threshold.js
if: github.ref == 'refs/heads/main'
TDD との使い分け
テスト駆動開発と進化的アーキテクチャの Fitness Function は補完的だ。
TDD → 「注文の合計金額が正しいか」 (機能の正しさ)
Fitness Fn → 「注文サービスが決済サービスを直接呼んでいないか」(構造の正しさ)
機能テストが「何をするか」を守り、Fitness Function が「どのように作られているか」を守る。両方を CI で走らせることで、機能もアーキテクチャも継続的に保護できる。
関連概念
- → 進化的アーキテクチャ概要
- → 段階的変更の戦略パターン
- → Expand-Contract パターン(一時的 Fitness Function の応用例)
出典・参考文献
- Neal Ford et al., Building Evolutionary Architectures, Chapter 2 “Fitness Functions”
- 1. 🧬進化的アーキテクチャとは:定義・誕生背景・3原則
- 2. 📐適応度関数(Fitness Functions):アーキテクチャ特性を自動検証する
出典: 進化的アーキテクチャ(O'Reilly / Neal Ford, Rebecca Parsons, Patrick Kua)