LESSON 40分

ストーリー

佐藤CTO
10チームが10通りのやり方で開発している。ログフォーマットもバラバラ、APIの命名規則もバラバラ、エラーハンドリングもバラバラ

佐藤CTOがため息をつきました。

佐藤CTO
自由は大事だが、共通の土台がないと組織はスケールしない。テクニカルスタンダードは、チームの自律性を保ちつつ、組織全体の一貫性を確保するためのものだ
あなた
ルールを押し付けるということですか?
佐藤CTO
いや、原則(Principles)と標準(Standards)は違う。原則は “なぜ” を示し、標準は “どうやって” を示す。原則が先で、標準はその実装だ

アーキテクチャ原則

原則の設計

architecture_principles:
  format:
    name: "原則の名前"
    statement: "1文で表現した原則"
    rationale: "なぜこの原則が重要か"
    implications: "この原則に従うと何が変わるか"

  examples:
    - name: "API First"
      statement: "すべてのサービス間通信はAPI経由で行う"
      rationale: "サービスの独立性を保ち、チームの自律性を確保するため"
      implications:
        - "データベースの直接参照を禁止する"
        - "API仕様を先に定義してからコードを書く"
        - "APIバージョニングポリシーに従う"

    - name: "Observability by Default"
      statement: "すべてのサービスは構造化ログ、メトリクス、トレースを出力する"
      rationale: "障害の迅速な検知と原因特定のため"
      implications:
        - "ゴールデンパスのテンプレートに監視を組み込む"
        - "ログは構造化JSON形式とする"
        - "分散トレーシングIDを全リクエストに付与する"

    - name: "Secure by Default"
      statement: "セキュリティはデフォルトで有効とし、無効化は意図的な判断とする"
      rationale: "セキュリティの設定漏れを防ぐため"
      implications:
        - "認証・認可はデフォルトで有効"
        - "通信は常にTLS"
        - "シークレットはコードに含めない"

    - name: "Build for Failure"
      statement: "障害は起きるものとして設計する"
      rationale: "分散システムでは部分障害が不可避なため"
      implications:
        - "タイムアウト、リトライ、サーキットブレーカーを必ず実装"
        - "グレースフルデグラデーションを設計"
        - "カオスエンジニアリングを実施"

コーディングスタンダード

組織レベルの標準

カテゴリ標準強制度
言語バージョンTypeScript 5.x + strict mode 必須必須
リンターESLint + 組織共通config必須
フォーマッターPrettier + 共通設定必須
テスト単体テストカバレッジ 80% 以上推奨
コミットメッセージConventional Commits必須
ブランチ戦略Trunk-based Development推奨

共通ESLint設定の例

// @company/eslint-config/index.ts
import type { Linter } from 'eslint';

const config: Linter.Config = {
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
  ],
  rules: {
    // 組織標準: 明示的なreturn typeを強制
    '@typescript-eslint/explicit-function-return-type': 'error',

    // 組織標準: any の使用を禁止
    '@typescript-eslint/no-explicit-any': 'error',

    // 組織標準: console.log を禁止(logger を使用)
    'no-console': ['error', { allow: ['warn', 'error'] }],

    // 組織標準: 未使用変数のエラー
    '@typescript-eslint/no-unused-vars': ['error', {
      argsIgnorePattern: '^_',
    }],
  },
};

export default config;

API ガイドライン

REST API 設計標準

api_guidelines:
  naming:
    base_url: "https://api.example.com/v{version}"
    resources: "複数形の名詞(/users, /orders)"
    actions: "HTTP メソッドで表現(GET, POST, PUT, DELETE)"
    case: "kebab-case(/user-profiles)"

  versioning:
    strategy: "URLパスバージョニング(/v1, /v2)"
    policy: "メジャーバージョンのみ。マイナー変更は後方互換を保つ"
    deprecation: "旧バージョンは最低6ヶ月間サポート"

  response_format:
    success:
      status: "200 OK / 201 Created / 204 No Content"
      body:
        data: "レスポンスデータ"
        meta: "ページネーション等のメタ情報"

    error:
      status: "4xx / 5xx"
      body:
        error:
          code: "VALIDATION_ERROR"
          message: "人間が読めるメッセージ"
          details: "フィールドレベルのエラー詳細"

  pagination:
    strategy: "Cursor-based(大規模データ)"
    parameters: "?cursor=xxx&limit=20"
    response_meta: "{ next_cursor, has_more }"

  rate_limiting:
    headers:
      - "X-RateLimit-Limit"
      - "X-RateLimit-Remaining"
      - "X-RateLimit-Reset"

エラーレスポンスの標準

// 組織標準: エラーレスポンス型
interface ApiError {
  error: {
    code: string;          // マシンリーダブルなエラーコード
    message: string;       // 人間が読めるメッセージ
    details?: ErrorDetail[];
    requestId: string;     // トレーシング用
  };
}

interface ErrorDetail {
  field: string;
  message: string;
  code: string;
}

// 使用例
const errorResponse: ApiError = {
  error: {
    code: 'VALIDATION_ERROR',
    message: '入力値に問題があります',
    details: [
      { field: 'email', message: '有効なメールアドレスを入力してください', code: 'INVALID_FORMAT' },
      { field: 'age', message: '0以上の数値を入力してください', code: 'MIN_VALUE' },
    ],
    requestId: 'req-abc123-def456',
  },
};

テクノロジーレーダーの維持

レーダーの更新プロセス

technology_radar_maintenance:
  update_frequency: "四半期ごと"

  process:
    step1:
      name: "提案収集"
      duration: "2週間"
      method: "全エンジニアからの提案をフォームで収集"

    step2:
      name: "評価会議"
      duration: "2時間"
      participants: "レビューボード + テックリード"
      agenda:
        - "新規追加候補の評価"
        - "既存項目のリング変更検討"
        - "Hold移行の判断"

    step3:
      name: "公開と共有"
      duration: "1日"
      method: "全社テック発表会で変更点を説明"

  governance:
    adopt_criteria:
      - "本番運用実績が6ヶ月以上"
      - "2チーム以上で使用"
      - "ドキュメントとテンプレートが整備済み"

    hold_criteria:
      - "セキュリティサポートが終了予定"
      - "より優れた代替技術がAdoptに存在"
      - "運用コストが見合わない"

ゴールデンパスの運用

ゴールデンパスの分類

パス対象内容
新サービス作成バックエンドエンジニアNestJS テンプレート + CI/CD + 監視
フロントエンド作成フロントエンドエンジニアNext.js テンプレート + Storybook
データパイプラインデータエンジニアApache Airflow テンプレート
ライブラリ公開全エンジニアnpm パッケージテンプレート + CI

ゴールデンパスの品質基準

golden_path_quality:
  must_include:
    - "README.md(Getting Started が5分以内)"
    - "CI/CD パイプライン設定"
    - "構造化ログ出力"
    - "ヘルスチェックエンドポイント"
    - "テストフレームワーク設定"
    - "Dockerfile"
    - "セキュリティスキャン設定"

  must_not_include:
    - "ハードコードされた設定値"
    - "特定チーム固有のロジック"
    - "古いバージョンの依存関係"

  maintenance:
    - "月1回の依存関係更新"
    - "四半期ごとのフィードバック収集"
    - "年2回のメジャーアップデート"

まとめ

ポイント内容
原則と標準原則は「なぜ」、標準は「どうやって」を定義する
コーディング標準共通config + 自動チェックで一貫性を確保
APIガイドライン命名規則、バージョニング、エラー形式を統一
テクノロジーレーダー四半期更新で技術の採用・廃止を組織的に管理

チェックリスト

  • アーキテクチャ原則の設計方法を理解した
  • コーディングスタンダードの組織展開方法を把握した
  • APIガイドラインの主要項目を理解した
  • テクノロジーレーダーの維持プロセスを把握した

次のステップへ

次は「フィットネス関数とアーキテクチャ適合度」を学びます。テクニカルスタンダードへの準拠を自動的に検証する仕組みを見ていきましょう。


推定読了時間: 40分