mcpField
E
effect-ts-anti-patterns

effect-ts-anti-patterns

github.com/mrevanzakテスト・品質896 回インストール39 週間前に更新
リポジトリ

effect-ts-anti-patterns について

Effect-TSでリソースリークやクラッシュ、未処理エラーにつながる誤用を見つけるためのコードレビュー・デバッグ資料です。Effect-TSを使う開発者向けで、通常のTypeScriptや他の関数型ライブラリは対象外です。

主な機能

  1. 01Effect-TSの代表的なアンチパターンの説明
  2. 02安全なEffect合成の例
  3. 03型付きエラー処理の解説
  4. 04並行処理数の制限方法
  5. 05中断に対応したリソース解放
  6. 06コードレビュー時の警告項目

活用シーン

  1. 01Effect-TSコードのレビュー
  2. 02未処理のPromise拒否のデバッグ
  3. 03過剰な並行処理の防止
  4. 04リソース解放とエラー処理経路の確認

インストール

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

$npx skills add https://github.com/mrevanzak/effect-ts-skills --skill effect-ts-anti-patterns

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

詳細

Effect-TS のアンチパターン

概要

Effect-TS は強力な関数型フレームワークですが、よくある命令型の習慣は、その安全性を保証する仕組みを迂回することがあります。このスキルでは、リソースリーク、プロセスのクラッシュ、未処理のエラーにつながるパターンを特定し、修正します。

使用する場面

  • Effect-TS の実装をコードレビューするとき。
  • Effect のコードで「未処理の Promise 拒否」やプロセスのクラッシュをデバッグするとき。
  • 並列処理のパフォーマンスを最適化するとき。

使用しない場面:

  • シンプルな非 Effect の TypeScript コードの場合。
  • 他の関数型ライブラリ(fp-ts など)を使用している場合。

アンチパターンの一覧

アンチパターン悪いコード良いコード理由
境界の外で実行する関数の途中で await Effect.runPromise(fx)yield* fx(合成する)エラーチャネルとトレーシングを迂回します。
yield* の付け忘れconst user = yield fetchUser()const user = yield* fetchUser()結果ではなく Effect オブジェクトを yield します。
エラーをスローするif (!ok) throw new Error()yield* Effect.fail(new Error())throw は型付きエラーではなく「Defect」(クラッシュ)を発生させます。
上限のない並列処理Effect.all(tasks)(デフォルト)Effect.all(tasks, { concurrency: 10 })OOM とレート制限の上限到達を防ぎます。
エラーを無視するEffect.runPromise(fx)(catch なし)fx.pipe(Effect.catchAll(...))未処理の拒否につながります。
手動でクリーンアップするtry { ... } finally { cleanup() }Effect.acquireRelease(...)finally は中断時のクリーンアップを保証しません。

よくある間違い

1. yield と yield* の落とし穴
// ❌ BAD: Missing *, yields the Effect object itself
const bad = Effect.gen(function* () {
  const user = yield fetchUser(id); // Returns Effect, not User!
});

// ✅ GOOD: yield* executes the Effect
const good = Effect.gen(function* () {
  const user = yield* fetchUser(id); // Returns User
});
2. 上限のない並列処理
// ❌ BAD: 10,000 concurrent requests (OOM risk)
const bad = Effect.all(urls.map(fetch));

// ✅ GOOD: Bounded to 10 concurrent
const good = Effect.all(urls.map(fetch), { concurrency: 10 });
3. コードの途中で Effect を実行する
// ❌ BAD: Effect.runPromise scattered throughout
const bad = async () => {
  const user = await Effect.runPromise(getUser(id));
  const posts = await Effect.runPromise(getPosts(user.id));
};

// ✅ GOOD: Compose effects, run ONCE at boundary
const good = Effect.gen(function* () {
  const user = yield* getUser(id);
  const posts = yield* getPosts(user.id);
  return { user, posts };
});

正当化の一覧

言い訳実態
「速くするために concurrency: 'unbounded' を使います」速さはクラッシュにつながります。外部リソースへの並列処理には必ず上限を設けてください。
「とりあえず throw します」throw はエラーチャネルを迂回し、コードをテスト不能にします。
「ここで実行するほうが簡単です」コードの途中で実行すると、コンテキスト、トレーシング、中断に対する安全性が失われます。

注意すべき兆候

  • ループやヘルパー関数内の Effect.runPromise または Effect.runSync。
  • 大きなリストに対して concurrency オプションなしで使用する Effect.all。
  • Effect.gen ブロック内の throw キーワード。
  • Effect の呼び出しで * を付けずに使用する yield。

関連項目

  • 必須の前提知識: effect-ts-fundamentals
  • 必須のサブスキル: effect-ts-concurrency
  • 参考資料: effect-ts-resources

コメント