architecture-paradigm-functional-core について
テスト容易性を高めたいチーム向けに、業務上の判断と I/O を分離する Functional Core, Imperative Shell パターンを解説します。段階的な導入、境界の維持、テストと完了条件を扱います。
主な機能
- 01副作用の洗い出しと隔離
- 02純粋関数による業務ルールの表現
- 03コマンドオブジェクトによるコアとシェルの接続
- 04段階的なコアロジックの抽出
- 05アーキテクチャテストと移行条件
活用シーン
- 01業務ロジックと DB や HTTP 処理の分離
- 02高速で決定的なユニットテストの構築
- 03レガシーな命令型モジュールの段階的な改修
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ athola/ claude-night-market --skill architecture-paradigm-functional-coreインストール後、Claude Code で/architecture-paradigm-functional-coreを入力して読み込まれたか確認します。
詳細
関数型コア、命令型シェルのパラダイム
使用する場面
- 純粋なビジネスロジックを副作用から分離する場合
- 不変のドメインモデルによってテスト容易性を高める場合
使用しない場面
- 不変性によるオーバーヘッドが問題となる、パフォーマンスが重要なホットパス
- 関数型のパターンを採用する予定がない、完全に命令型のコードベース
このパラダイムを採用する場面
- ビジネスロジックが I/O 操作(データベース呼び出しや HTTP リクエストなど)と密結合しており、テストが壊れやすく、実行に時間がかかる場合。
- アダプターの書き直しやフレームワークの頻繁な変更への対応に、開発時間の多くを費やしている場合。
- プレーンなデータを扱う、高速で決定論的な単体テストスイートに加え、薄い統合テスト層が必要な場合。
導入手順
- 副作用を洗い出す:データベースへの書き込み、外部 API の呼び出し、UI イベント、ファイルシステムへのアクセスなど、システム内のすべての副作用をマップにまとめます。これらの責務を明示的に「シェル」に割り当てます。
- コアロジックをモデル化する:ビジネスルールとポリシーを純粋関数として表現します。これらの関数は、ドメインデータを入力として受け取り、決定またはコマンドを出力し、共有された可変状態を使わないようにします。
- コマンドのスキーマを設計する:コアが返し、シェルが解釈できる、小さく明示的なコマンドオブジェクトのセットを定義します(例:
PersistOrder、PublishEvent、NotifyUser)。 - 段階的にリファクタリングする:変更頻度が高いモジュールや重要なモジュールから始めます。レガシーな命令型コードをアダプターの背後に配置しつつ、計算処理を段階的に関数型コアへ切り出します。
- 境界を守る:コードレビューと自動化されたアーキテクチャテストを使い、厳格な分離を検証します。シェルが扱うのはオーケストレーション、順序制御、リトライのみとし、コアはフレームワークや I/O ライブラリを直接呼び出さないようにします。
主な成果物
- このパターンを選んだ理由、影響を受けるモジュール、移行の範囲を詳述したアーキテクチャ決定記録(ADR)。
- コアを対象とする単体テストスイート。高い(>90%)決定論的なコードカバレッジを備えます。該当する場合は、幅広い入力を網羅するため、プロパティベーステストまたはフィクスチャベーステストを使用します。
- コマンドの解釈、リトライロジック、テレメトリが正しく機能することを検証する、シェル向けのコントラクトテストと統合テストのスイート。
- アーキテクチャ変更の効果を示す、デプロイリードタイムやシェル層のインシデント率などのロールアウト指標。
リスクと緩和策
- コアとシェルの間でロジックがずれる:
- 緩和策:ビジネスロジックが誤って重複したり、シェルに配置されたりすることはよくあります。コードレビューで「すべての判断はコアが担う」というチェックリストを徹底し、これを防ぎます。
- フレームワークとの不整合:
- 緩和策:命令型シェルでは、フレームワーク固有のライフサイクルフックとの連携が必要になる場合があります。大規模な書き換えを決める前に、小規模な概念実証用アダプターを作成し、統合戦略を検証します。
- チームがこのパターンに不慣れ:
- 緩和策:ペアプログラミングや社内の「ブラウンバッグ」形式の勉強会を通じて、このパターンを導入します。試行段階で発見したよくあるアンチパターンを文書化し、今後の開発に役立てます。
具体的なコンポーネント
このパラダイムの実装で使われる傾向のあるツールや抽象化の用語です。依存関係ではなく、tools: のフロントマターでもありません。
boundary-validator:純粋なコアが全域関数であり続けられるよう、入力を検証しますcore-test-generator:決定論的なコアを対象とするプロパティベーステストを生成しますshell-adapter-generator:コアを I/O に接続する命令型シェルのひな形を生成します
完了条件
- リファクタリングを開始する前に、すべての I/O 操作をシェル層に対応付けた、明示的な副作用の一覧が作成されている。
- コアのユニットテストが I/O モックなし(データベース、HTTP、ファイルシステムへの呼び出しなし)で実行され、決定論的カバレッジが
90% に達している。
- 自動アーキテクチャテスト(インポート解析や名前空間ルールなど)により、コアに I/O ライブラリまたはフレームワークライブラリからのインポートが一切ないことが確認されている。
- ロールアウト指標(デプロイのリードタイム、シェル層のインシデント率)が移行前にベースラインとして測定され、パターンの価値を示すため、移行後の値と比較されている。
コメント
Markdown 対応