JA Architecture System Design - aku11i/phantom GitHub Wiki
English | 日本語
このドキュメントでは、Phantomの全体的なアーキテクチャ、デザインパターン、アーキテクチャ上の決定事項について説明します。
Phantomは明確な関心の分離を持つレイヤードアーキテクチャに従っています:
graph TD
subgraph "ユーザーインターフェースレイヤー"
CLI[CLIエントリーポイント]
Commands[コマンドパーサー]
end
subgraph "アプリケーションレイヤー"
Handlers[コマンドハンドラー]
Output[出力フォーマット]
ErrorHandler[エラーハンドリング]
end
subgraph "ドメインレイヤー"
Worktree[Worktreeドメイン]
Git[Gitドメイン]
Process[プロセスドメイン]
end
subgraph "インフラストラクチャレイヤー"
GitCLI[Git CLIラッパー]
FileSystem[ファイルシステム]
Shell[シェル実行]
end
CLI --> Commands
Commands --> Handlers
Handlers --> Output
Handlers --> ErrorHandler
Handlers --> Worktree
Handlers --> Process
Worktree --> Git
Process --> Shell
Git --> GitCLI
style CLI fill:#f9f,stroke:#333
style Handlers fill:#9ff,stroke:#333
style Worktree fill:#ff9,stroke:#333
style GitCLI fill:#9f9,stroke:#333
ソース: CLAUDE.md#L26-L31
各モジュールには変更する理由が1つだけあります:
- CLIハンドラー: コマンドインターフェースが変更されたときのみ変更
- コアロジック: ビジネスルールが変更されたときのみ変更
- Git操作: Git統合が変更されたときのみ変更
- プロセス管理: 実行モデルが変更されたときのみ変更
高レベルモジュールは低レベルモジュールに依存しません:
CLIレイヤー → コアレイヤー → インフラストラクチャ
↖ ↙
インターフェース
アーキテクチャは拡張に対して開いており、変更に対して閉じています:
- 既存のコードを変更せずに新しいコマンドを追加可能
- エグゼキューターに新しいGit操作を追加可能
- 出力フォーマットを拡張可能
モジュールは使用するインターフェースにのみ依存します:
- CLIハンドラーはGitの内部を知らない
- コアロジックはコンソール出力を知らない
- Git操作はCLIコマンドを知らない
例外なしの関数型エラーハンドリング:
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E }
利点:
- 明示的なエラーハンドリング
- 型安全なエラー伝播
- 構成可能な操作
- 隠れた制御フローなし
使用例:
function createWorktree(name: string): Result<WorktreeInfo> {
const validation = validateName(name);
if (!validation.ok) {
return validation;
}
const creation = git.addWorktree(name);
if (!creation.ok) {
return creation;
}
return Result.ok(creation.value);
}
各CLIコマンドはハンドラーとしてカプセル化されます:
interface CommandHandler {
execute(args: ParsedArgs): Promise<void>;
}
配置場所: src/cli/handlers/
利点:
- コマンドロジックの分離
- テストが簡単
- 新しいコマンドの追加が簡単
- 一貫したインターフェース
Git操作は簡素化されたインターフェースでラップされます:
class GitExecutor {
execute(args: string[]): Result<string>;
}
これにより以下の複雑さが隠蔽されます:
- プロセス生成
- エラーハンドリング
- 出力解析
- 環境セットアップ
プロセスの異なる実行戦略:
ソース: src/core/process/
-
exec.ts
: 一回限りのコマンド実行 -
shell.ts
: インタラクティブシェルセッション -
spawn.ts
: コア生成ロジック
責任:
- コマンドライン引数の解析
- 適切なハンドラーへのルーティング
- ユーザー向けの出力フォーマット
- プロセス終了コードの処理
主要コンポーネント:
- コマンドハンドラー
- 出力フォーマッター
- エラーハンドラー
設計決定:
- ビジネスロジックなし
- 薄いオーケストレーションレイヤー
- コアに委譲
責任:
- ビジネスロジックの実装
- ドメインモデル管理
- 検証ルール
- コアアルゴリズム
主要モジュール:
ソース: src/core/worktree/
- phantomライフサイクルの管理
- phantom名の検証
- Git操作の調整
ソース: src/core/git/
- Git CLIコマンドのラップ
- Git出力の解析
- Gitエラーの処理
ソース: src/core/process/
- 子プロセスの生成
- プロセスライフサイクルの管理
- I/Oストリームの処理
責任:
- システムとのインタラクション
- 外部ツール統合
- I/O操作
コンポーネント:
- ファイルシステムアクセス
- プロセス生成
- Git CLI実行
sequenceDiagram
participant User
participant CLI
participant Handler
participant Core
participant Git
participant FS
User->>CLI: phantom create feature
activate CLI
CLI->>Handler: route(command, args)
activate Handler
Handler->>Core: validateWorktreeName(name)
activate Core
Core-->>Handler: Result<void>
deactivate Core
alt 検証失敗
Handler->>CLI: formatError(error)
CLI->>User: エラーを表示
else 検証成功
Handler->>Core: createWorktree(name, branch)
activate Core
Core->>Git: getCurrentBranch()
activate Git
Git->>FS: git branch --show-current
FS-->>Git: ブランチ名
Git-->>Core: Result<string>
deactivate Git
Core->>Git: addWorktree(name, branch)
activate Git
Git->>FS: git worktree add
FS-->>Git: 成功
Git-->>Core: Result<WorktreeInfo>
deactivate Git
Core-->>Handler: Result<WorktreeInfo>
deactivate Core
Handler->>CLI: formatSuccess(info)
CLI->>User: 成功を表示
end
deactivate Handler
deactivate CLI
graph TB
A[Gitコマンド失敗] --> B[エラーResultを作成]
B --> C[コアに伝播]
C --> D[ドメインエラーに変換]
D --> E[ハンドラーに返す]
E --> F[ユーザーメッセージをフォーマット]
F --> G[終了コードを設定]
G --> H[ユーザーに表示]
style A fill:#f99
style H fill:#9f9
graph TD
subgraph "エントリーポイント"
bin[bin/phantom.ts]
end
subgraph "CLIレイヤー"
handlers[handlers/*]
output[output.ts]
errors[errors.ts]
end
subgraph "コアレイヤー"
worktree[worktree/*]
git[git/*]
process[process/*]
paths[paths.ts]
types[types/*]
end
bin --> handlers
handlers --> output
handlers --> errors
handlers --> worktree
handlers --> process
worktree --> git
worktree --> paths
worktree --> types
process --> types
git --> types
style bin fill:#f9f
style handlers fill:#9ff
style worktree fill:#ff9
- 上向き依存なし: コアはCLIからインポートしない
- インターフェース境界: モジュールは定義されたインターフェースを通じて通信
-
共有型:
types/
モジュールの共通型 - 循環依存なし: モジュール構造により強制
Phantomはステートレスになるよう設計されています:
- デーモンプロセスなし
- 永続的な設定なし
- バックグラウンドサービスなし
- 各呼び出しは独立
利点:
- シンプルなメンタルモデル
- 推論が簡単
- 状態破損なし
- 並列実行が安全
すべての状態はGitに保存されます:
-
.git/worktrees/
のWorktree情報 - Git refsのブランチ情報
- カスタム状態ファイルなし
-
検証エラー
- 無効なphantom名
- 引数の欠落
- 無効なブランチ
-
Gitエラー
- リポジトリが見つからない
- ブランチが存在しない
- Worktreeの競合
-
システムエラー
- アクセス拒否
- ディスクフル
- プロセス失敗
graph LR
A[操作] --> B{回復可能?}
B -->|はい| C[リトライ/修正提案]
B -->|いいえ| D[クリーンな失敗]
C --> E[ユーザーアクション]
D --> F[コードで終了]
E --> A
- 依存関係ゼロ: 高速起動
- バンドルされた実行可能ファイル: 単一ファイル配布
- 遅延読み込み: 必要なものだけをロード
- 直接Git CLI: 抽象化オーバーヘッドなし
- n個のworktreeに対してO(n)操作
- 指数関数的アルゴリズムなし
- 効率的なGitコマンド使用
- 最小限のメモリフットプリント
すべてのユーザー入力が検証されます:
function validateWorktreeName(name: string): Result<void> {
// パストラバーサルをチェック
if (name.includes('..') || name.includes('/')) {
return Result.error(new Error('無効な文字'));
}
// 追加の検証...
}
安全なコマンド実行:
- デフォルトでシェル補間なし
- インタラクティブセッション用の明示的なシェルモード
- 制御された環境変数
-
プラグインシステム
- コマンドプラグイン
- 出力フォーマットプラグイン
- Gitプロバイダープラグイン
-
設定システム
- ユーザー設定
- リポジトリ設定
- グローバル設定
-
イベントシステム
- ライフサイクルフック
- 進行状況レポート
- テレメトリー
これらは維持されなければなりません:
- ランタイム依存関係ゼロ
- ステートレス操作
- 単一の真実の源としてのGit
- クリーンなレイヤー分離
- 関数型エラーハンドリング
Phantomのアーキテクチャは以下のために設計されています:
- シンプルさ: 理解と保守が簡単
- パフォーマンス: 最小限のオーバーヘッドで高速実行
- 信頼性: 予測可能な動作とエラーハンドリング
- 拡張性: 新機能の追加が簡単
- テスト可能性: 明確な境界と純粋関数
関数型パターンを持つレイヤードアーキテクチャは、Gitワークフローの生産性を向上させる堅牢で保守可能なシステムを作成します。