mcpField
B
better-result-adopt

better-result-adopt

github.com/dmmulroy開発2.0k578 回インストール9 週間前に更新
リポジトリ

better-result-adopt について

better-result Adopt は、既存のコードベースに better-result を段階的に導入するスキルです。型付きエラー処理と範囲を絞った移行を案内し、全面的な書き換えを避けます。

主な機能

  1. 01try/catch を Result API に置換
  2. 02null 可能な戻り値を Result に変更
  3. 03ドメイン固有の TaggedError 型を定義
  4. 04andThen や Result.gen で処理を合成
  5. 05移行時にエラーのコンテキストを保持

活用シーン

  1. 01I/O 境界を Result に移行
  2. 02モジュール内の null による代替値を置換
  3. 03サービス全体のエラー型を統一
  4. 04ネストしたエラー処理をリファクタリング

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dmmulroy/better-result --skill better-result-adopt

インストール後、Claude Code で/better-result-adoptを入力して読み込まれたか確認します。

同梱ファイルreferences/tagged-errors.md

詳細

better-result の導入

既存のコードベースを一度にすべて書き換えるのではなく、better-result を段階的に導入します。

使用する場面

ユーザーが次のことを希望する場合に、このスキルを使用します。

  • try/catch から Result.try または Result.tryPromise に移行する
  • nullable な戻り値を型付きの Result<T, E> に置き換える
  • ドメイン固有の TaggedError 型を定義する
  • ネストしたエラー処理を andThen チェーンまたは Result.gen にリファクタリングする
  • サービスやモジュール全体でエラー処理を標準化する

読む順序

作業読むファイル
モジュールに better-result を導入するこのファイル
エラー型を定義またはレビューするreferences/tagged-errors.md
ライブラリの実装詳細を確認する存在する場合は opensrc/

前提条件

コードを編集する前に、次のことを確認します。

  1. 対象のプロジェクトに better-result がすでにインストールされていることを確認します。
  2. opensrc/ ディレクトリがあるか確認します。存在する場合は、現在のパターンを把握するため、そこにあるパッケージのソースを読みます。
  3. まず移行範囲を特定します。1 つのファイル、1 つのモジュール、または 1 つの境界レイヤーを対象にします。

移行戦略

1. 境界から始める

I/O 境界や例外処理の多いコードから始めます。

  • HTTP クライアント
  • データベースアクセス
  • ファイルシステム操作
  • パースと検証
  • フレームワークアダプター

コードベース全体を一度に変換しないでください。

2. 既存のエラーを分類する
カテゴリー例移行後の形
ドメインエラー見つからない、検証、認証TaggedError + Result.err
インフラストラクチャエラーネットワーク、DB、ファイル I/OResult.tryPromise + マッピングしたエラー
プログラマーの不具合誤った前提、null 参照throw のままにします。不具合は Result コールバック内で Panic になります
3. 次の順序で移行する
  1. エラー型を定義します。
  2. throw する境界を Result.try / Result.tryPromise でラップします。
  3. null またはブール値のセンチネル戻り値を Result に置き換えます。
  4. 呼び出し元をリファクタリングし、Result 値を伝播させます。
  5. ネストした分岐を andThen、mapError、または Result.gen にまとめます。

主な変換

Try/catch → Result.try
function parseConfig(json: string): Result<Config, ParseError> {
  return Result.try({
    try: () => JSON.parse(json) as Config,
    catch: (cause) => new ParseError({ cause, message: `Parse failed: ${cause}` }),
  });
}
非同期の throw → Result.tryPromise
async function fetchUser(id: string): Promise<Result<User, ApiError | UnhandledException>> {
  return Result.tryPromise({
    try: async () => {
      const res = await fetch(`/api/users/${id}`);
      if (!res.ok) throw new ApiError({ status: res.status, message: `API ${res.status}` });
      return res.json() as Promise<User>;
    },
    catch: (cause) => (cause instanceof ApiError ? cause : new UnhandledException({ cause })),
  });
}
null センチネル → Result
function findUser(id: string): Result<User, NotFoundError> {
  const user = users.find((candidate) => candidate.id === id);
  return user
    ? Result.ok(user)
    : Result.err(new NotFoundError({ id, message: `User ${id} not found` }));
}
ネストしたフロー → Result.gen
async function processOrder(orderId: string): Promise<Result<OrderResult, OrderError>> {
  return Result.gen(async function* () {
    const order = yield* Result.await(fetchOrder(orderId));
    const validated = yield* validateOrder(order);
    const result = yield* Result.await(submitOrder(validated));
    return Result.ok(result);
  });
}

実行ワークフロー

  1. 対象モジュールを調べ、try、catch、.catch(...)、throw、null、undefined、ステータスフラグによるエラー処理を確認します。
  2. 制御フローを変更する前に、TaggedError クラスを定義または更新します。
  3. まず境界関数を変換し、シグネチャを Result<T, E> または Promise<Result<T, E>> に変更します。
  4. 直近の呼び出し元を更新し、新しい Result を処理または伝播させます。
  5. Result を返す複数のステップを合成する場合は、Result.gen または andThen を使用します。
  6. cause、ID、メッセージ、その他の構造化フィールドを保持し、エラーのコンテキストを維持します。
  7. テストを実行し、成功パスとエラーパスの両方のカバレッジを追加します。

完了条件

次の条件を満たすと、移行は完了です。

  • 対象の関数が、想定されるドメインエラーに対して try/catch に依存しなくなっている
  • nullable な戻り値やセンチネルエラー戻り値が、明示的な Result 値に置き換えられている
  • ドメインエラーに型付きの TaggedError クラスを使用している
  • 呼び出し元が Result を伝播するか、明示的にアンラップまたはパターンマッチしている
  • テストで少なくとも 1 つの成功パスと、代表的なエラーパスがカバーされている

よくある落とし穴

  • 境界から始めず、あらゆる処理を過剰にラップする
  • エラーをマッピングする際に、元の失敗のコンテキストを失う
  • 同じフローの深い部分で throw ベースと Result ベースの API を混在させる
  • 根本原因の不具合を修正せずに Panic を捕捉する

このリファレンスの内容

ファイル目的
references/tagged-errors.mdTaggedError のパターン、照合、型ガード、例

opensrc/ が存在する場合は、実装の詳細と現在の API の動作について、その内容を信頼できる情報源として扱ってください。

コメント