JA Architecture Data Flow - aku11i/phantom GitHub Wiki

データフロー

English | 日本語

このドキュメントでは、ユーザー入力から最終出力まで、Phantomのシステムを通じてデータがどのように移動するかを説明します。

概要

データはPhantomを通じて予測可能な単一方向で流れます:

graph LR
    A[ユーザー入力] --> B[CLIパーサー]
    B --> C[コマンドハンドラー]
    C --> D[コアロジック]
    D --> E[Git操作]
    E --> F[システムコール]
    F --> G[結果]
    G --> H[出力フォーマット]
    H --> I[ユーザー出力]
    
    style A fill:#9f9
    style I fill:#9f9
    style D fill:#ff9
    style E fill:#f9f
Loading

コマンド実行フロー

1. Createコマンドフロー

例: phantom create feature-xyz origin/main

sequenceDiagram
    participant User
    participant CLI
    participant CreateHandler
    participant WorktreeCore
    participant GitModule
    participant FileSystem
    
    User->>CLI: phantom create feature-xyz origin/main
    
    CLI->>CreateHandler: {name: "feature-xyz", branch: "origin/main"}
    
    CreateHandler->>WorktreeCore: validateWorktreeName("feature-xyz")
    WorktreeCore-->>CreateHandler: Result.ok()
    
    CreateHandler->>GitModule: getGitRoot()
    GitModule->>FileSystem: git rev-parse --show-toplevel
    FileSystem-->>GitModule: "/path/to/repo"
    GitModule-->>CreateHandler: Result.ok("/path/to/repo")
    
    CreateHandler->>GitModule: branchExists("origin/main")
    GitModule->>FileSystem: git rev-parse --verify
    FileSystem-->>GitModule: "commit-sha"
    GitModule-->>CreateHandler: Result.ok(true)
    
    CreateHandler->>WorktreeCore: createWorktree("feature-xyz", "origin/main")
    
    WorktreeCore->>GitModule: addWorktree(name, branch, path)
    GitModule->>FileSystem: git worktree add
    FileSystem-->>GitModule: success
    
    GitModule-->>WorktreeCore: Result.ok(WorktreeInfo)
    WorktreeCore-->>CreateHandler: Result.ok(WorktreeInfo)
    
    CreateHandler->>CLI: formatSuccess(WorktreeInfo)
    CLI->>User: "phantom 'feature-xyz'を/tmp/phantom/repo/feature-xyzに作成しました"
Loading

2. Listコマンドフロー

例: phantom list

sequenceDiagram
    participant User
    participant CLI
    participant ListHandler
    participant WorktreeCore
    participant GitModule
    participant OutputFormatter
    
    User->>CLI: phantom list
    
    CLI->>ListHandler: {}
    
    ListHandler->>WorktreeCore: listWorktrees()
    
    WorktreeCore->>GitModule: listWorktrees()
    GitModule->>GitModule: git worktree list --porcelain
    GitModule-->>WorktreeCore: Result.ok(GitWorktreeData[])
    
    WorktreeCore->>WorktreeCore: WorktreeInfo[]に変換
    WorktreeCore-->>ListHandler: Result.ok(WorktreeInfo[])
    
    ListHandler->>OutputFormatter: formatTable(worktrees)
    OutputFormatter-->>ListHandler: フォーマットされたテーブル文字列
    
    ListHandler->>CLI: テーブルを出力
    CLI->>User: フォーマットされたテーブルを表示
Loading

データ変換パイプライン

1. 入力処理

graph TB
    A[生のCLI引数] --> B[解析された引数]
    B --> C[検証された入力]
    C --> D[ドメインオブジェクト]
    
    subgraph "CLIレイヤー"
        A
        B
    end
    
    subgraph "ハンドラーレイヤー"
        C
    end
    
    subgraph "コアレイヤー"
        D
    end
Loading

変換例:

// 生の入力
["create", "my-feature", "origin/main"]

// 解析された引数
{
  command: "create",
  args: ["my-feature", "origin/main"],
  flags: {}
}

// 検証された入力
{
  name: "my-feature",
  branch: "origin/main"
}

// ドメインオブジェクト
{
  name: "my-feature",
  branch: "origin/main",
  path: "/tmp/phantom/repo/my-feature"
}

2. Gitデータ処理

graph LR
    A[Git CLI出力] --> B[生の文字列]
    B --> C[解析されたデータ]
    C --> D[ドメインモデル]
    D --> E[Result型]
    
    style A fill:#f9f
    style E fill:#9f9
Loading

例: Worktreeリストの解析

// Git出力(porcelainフォーマット)
`worktree /path/to/main
HEAD abc123
branch refs/heads/main

worktree /tmp/phantom/repo/feature
HEAD def456
branch refs/heads/feature`

// 解析されたデータ
[
  {
    path: "/path/to/main",
    head: "abc123",
    branch: "refs/heads/main"
  },
  {
    path: "/tmp/phantom/repo/feature",
    head: "def456", 
    branch: "refs/heads/feature"
  }
]

// ドメインモデル
[
  {
    name: "main",
    path: "/path/to/main",
    branch: "main",
    isMain: true
  },
  {
    name: "feature",
    path: "/tmp/phantom/repo/feature",
    branch: "feature",
    isMain: false
  }
]

エラーフロー

エラー伝播

graph TB
    A[システムエラー] --> B[Gitエラー]
    B --> C[ドメインエラー]
    C --> D[ユーザーエラー]
    
    subgraph "インフラストラクチャ"
        A
    end
    
    subgraph "Gitモジュール"
        B
    end
    
    subgraph "コアモジュール"
        C
    end
    
    subgraph "CLIレイヤー"
        D
    end
    
    style A fill:#f99
    style D fill:#fcc
Loading

エラー変換例:

// システムエラー
Error: Command failed: git worktree add
fatal: 'feature' is already checked out

// Gitモジュールエラー
GitError: Worktree 'feature' already exists

// ドメインエラー
WorktreeError: 'feature'という名前のphantomは既に存在します

// ユーザーメッセージ
エラー: 'feature'という名前のphantomは既に存在します。
別の名前を試すか、既存のphantomを最初に削除してください。

Result型フロー

sequenceDiagram
    participant Git
    participant Core
    participant Handler
    participant User
    
    Git->>Git: コマンドを実行
    
    alt 成功
        Git->>Core: Result.ok(data)
        Core->>Core: データを変換
        Core->>Handler: Result.ok(domainObject)
        Handler->>User: 成功メッセージ
    else 失敗
        Git->>Core: Result.error(gitError)
        Core->>Core: ドメインエラーにマップ
        Core->>Handler: Result.error(domainError)
        Handler->>User: エラーメッセージ + ヘルプ
    end
Loading

状態フロー

Worktree状態管理

stateDiagram-v2
    [*] --> 存在しない
    存在しない --> 作成中: createコマンド
    作成中 --> アクティブ: git worktree add
    アクティブ --> 削除中: deleteコマンド
    削除中 --> 存在しない: git worktree remove
    
    アクティブ --> アクティブ: exec/shellコマンド
    
    作成中 --> 存在しない: エラー
    削除中 --> アクティブ: エラー
Loading

プロセス状態フロー

graph LR
    A[アイドル] --> B[生成中]
    B --> C[実行中]
    C --> D[完了]
    C --> E[失敗]
    
    D --> F[終了コード 0]
    E --> G[終了コード > 0]
    
    style A fill:#ccc
    style C fill:#9f9
    style D fill:#9f9
    style E fill:#f99
Loading

非同期データフロー

コマンド実行パイプライン

sequenceDiagram
    participant Handler
    participant Process
    participant Shell
    participant Output
    
    Handler->>Process: exec(command)
    
    Process->>Shell: spawn(command)
    activate Shell
    
    loop 出力ストリーム
        Shell-->>Process: stdoutデータ
        Process-->>Handler: ストリームチャンク
        Handler-->>Output: チャンクを表示
    end
    
    Shell-->>Process: exit(code)
    deactivate Shell
    
    Process-->>Handler: Result<ExitCode>
    Handler-->>Output: 最終ステータス
Loading

データ検証フロー

入力検証パイプライン

graph TB
    A[ユーザー入力] --> B{有効なフォーマット?}
    B -->|いいえ| C[フォーマットエラー]
    B -->|はい| D{有効な文字?}
    D -->|いいえ| E[文字エラー]
    D -->|はい| F{名前は利用可能?}
    F -->|いいえ| G[競合エラー]
    F -->|はい| H[続行]
    
    C --> I[エラーメッセージ]
    E --> I
    G --> I
    
    style B fill:#ff9
    style D fill:#ff9
    style F fill:#ff9
    style I fill:#f99
    style H fill:#9f9
Loading

検証段階:

  1. フォーマット検証

    • 空でない名前
    • パスセパレーターなし
    • 特殊文字なし
  2. 文字検証

    • 英数字とハイフンのみ
    • スペースやドットなし
    • パストラバーサルなし
  3. 利用可能性チェック

    • 名前がまだ使用されていない
    • 既存との競合なし

出力フォーマットフロー

テーブルレンダリングパイプライン

graph LR
    A[ドメインオブジェクト] --> B[フィールド抽出]
    B --> C[幅を計算]
    C --> D[行をフォーマット]
    D --> E[ヘッダーを追加]
    E --> F[テーブルをレンダリング]
    
    subgraph "データ準備"
        A
        B
    end
    
    subgraph "レイアウト計算"
        C
    end
    
    subgraph "レンダリング"
        D
        E
        F
    end
Loading

例: リスト出力

// ドメインオブジェクト
[
  { name: "main", branch: "main", path: "/repo" },
  { name: "feature", branch: "feature/new", path: "/tmp/phantom/repo/feature" }
]

// 抽出されたフィールド
[
  ["main", "main", "/repo"],
  ["feature", "feature/new", "/tmp/phantom/repo/feature"]
]

// 計算された幅
{ name: 7, branch: 11, path: 25 }

// フォーマットされた出力
NAME     BRANCH       PATH
main     main         /repo
feature  feature/new  /tmp/phantom/repo/feature

パフォーマンスに関する考慮事項

データフロー最適化

graph TB
    A[変換を最小限に] --> B[可能な限りストリーム]
    B --> C[高価な操作をキャッシュ]
    C --> D[早期失敗]
    
    E[Git呼び出し] --> F[バッチ操作]
    F --> G[Porcelainフォーマットを使用]
    
    H[出力] --> I[プログレッシブレンダリング]
    I --> J[遅延評価]
Loading

最適化戦略:

  1. ストリーム処理

    • 出力全体をバッファしない
    • 行ごとに処理
    • 即座のユーザーフィードバック
  2. 効率的なGit使用

    • 解析には--porcelainを使用
    • 可能な場合は操作を組み合わせる
    • リポジトリ情報をキャッシュ
  3. 早期失敗

    • 早期に検証
    • 前提条件を最初にチェック
    • 不要な作業を避ける

データフローパターン

1. コマンドパターン

interface Command {
  validate(input: Input): Result<ValidatedInput>
  execute(input: ValidatedInput): Result<Output>
  format(output: Output): string
}

2. パイプラインパターン

const pipeline = 
  parseArgs
  .andThen(validate)
  .andThen(execute)
  .andThen(format)
  .mapError(handleError)

3. ストリームパターン

spawn(command)
  .stdout
  .pipe(lineParser)
  .pipe(transformer)
  .pipe(output)

まとめ

Phantomのデータフローアーキテクチャは以下を保証します:

  1. 予測可能性: データは一方向に流れる
  2. 追跡可能性: 明確な変換ポイント
  3. 型安全性: 境界で強く型付け
  4. エラーハンドリング: 明示的なエラー伝播
  5. パフォーマンス: 効率的なデータ処理

単一方向のフローと明確な変換境界により、システムは理解、デバッグ、拡張が容易になります。

⚠️ **GitHub.com Fallback** ⚠️