mcpField
S
simplifying-ruby-code

simplifying-ruby-code

github.com/bostonaholic開発264 回インストール1 日前に更新
リポジトリ

simplifying-ruby-code について

構造を簡素化しつつ意味のある振る舞いを保つ、Rubyコードレビューとリファクタリング向けのスキルです。不要なクラスの置き換え、判断とI/Oの分離、削除前の呼び出し元確認を扱います。

主な機能

  1. 01ステートレスなコマンドオブジェクトを関数に置換
  2. 02値に応じてHash、Struct、Dataを選択
  3. 03深い継承よりコンポジションを優先
  4. 04純粋な判断とI/Oを分離
  5. 05クラス削除前に呼び出し元を確認
  6. 06レビューと段階的なリファクタリングを支援

活用シーン

  1. 01Rubyコードの簡素化候補をレビュー
  2. 02RailsのサービスオブジェクトやConcernをリファクタリング
  3. 03クラスを安全に削除する計画
  4. 04計算とデータベースやファイル操作を分離

インストール

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

$npx skills add https://github.com/bostonaholic/skills --skill simplifying-ruby-code

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
review-findings.md
scripts/
find-callers.sh

詳細

Ruby コードをシンプルにする

状態や振る舞いを追加しないクラスよりも、プレーンなデータ(Hash、Array、Struct、Data)と純粋関数を優先してください。判断と副作用を分離します。判断はデータを受け取ってデータを返し、副作用は I/O(データベース、ネットワーク、ファイル、時刻)を扱います。判断をモックなしでテストできるよう、別々のメソッドまたはモジュールに分けてください。

ユーザーがレビューを依頼した場合、指摘事項を報告し、編集は依頼された場合にのみ行ってください。パターンは番号(「Pattern 1」)またはアンチパターン名で示してください。

パターン

  1. コマンドオブジェクトをモジュール関数にする。 唯一の公開メソッドが call、perform、run、execute のいずれかで、コンストラクター引数以外に何も保持しないクラスは、直接呼び出しまたはモジュール関数に置き換えます(UserCreator.new(params).call は User.create(params) になります)。呼び出しをまたいで状態を保持する場合、名前を付ける価値のある複数ステップのアルゴリズムを実行する場合、またはバックグラウンドジョブのようにシリアライズする必要がある場合は、オブジェクトのままにします。

  2. 値オブジェクトを Data、Struct、または Hash にする。 手書きの initialize、アクセサー、または == があり、振る舞いや検証を持たず、属性を保存するだけのクラスは、次のようにします。

    使用する型場合
    Hash一時的なデータ、キーが変化するデータ、JSON の入出力
    Struct属性が固定で、変更可能なデータ
    Data属性が固定で、イミュータブルなデータ(ruby -v >= 3.2 を確認)
    Custom class検証、不変条件、または実際のドメイン動作がある場合
  3. クラスメソッドのみのクラスをモジュールにする。 インスタンス化されず、self. メソッドのみを定義するクラスは、module_function を使うモジュールに置き換えます。

  4. 深い継承をコンポジションにする。 プロジェクト独自のクラスのみを数えて 2 階層を超える場合、または抽象基底クラスにサブクラスが 1 つだけある場合が該当します(ApplicationRecord や StandardError など、フレームワークや標準ライブラリの基底クラスは数えません)。

  5. Ruby プロトコルの不足。 呼び出し側がコレクション風または値風のクラスを手作業で展開している場合は、Enumerable を使った each、to_h、Comparable を使った <=>、または hash と eql? を実装してください。

  6. 判断と副作用の混在。 テストに多くのモックが必要な場合や、1 つのメソッド本体で計算と書き込みを行う場合が該当します。計算を純粋関数に抽出し、I/O を行うメソッドは薄く保ちます。

Rails のアンチパターン

  • サービスオブジェクト: 単一メソッドでステートレスなサービスは、モデルメソッドまたはモジュール関数にします(Pattern 1)。複雑なオーケストレーションはサービスとして維持しますが、判断と副作用を分離してください(Pattern 6)。ジョブはシリアライズされるため、正当なオブジェクトです。
  • モデル: ActiveRecord モデルはクラスのままにし、ビジネス計算は純粋関数に移します。
  • Concern: Concern は複数のモデル間で振る舞いを共有するためのものです。単一のモデルのための寄せ集めとして使われていたら指摘してください。
  • ヘルパー: ビューの整形のみに使います。ビジネスルールはモジュールに置きます。
  • Rails の再実装: スコープ、バリデーション、コールバック、列挙型、または ActiveModel と重複するカスタム DSL や基底クラス。

プレーンな Ruby のアンチパターン

  • テンプレートメソッド: ブロックで実現できるのに、フックメソッドを持つ基底クラスを使うこと。
  • ビルダー: キーワード引数や Data.define で直接構築できるオブジェクトにビルダーを使うこと。
  • ラッパー: Array、Hash、Set、またはその他の標準ライブラリ型をラップし、大半の呼び出しを転送するクラス。
  • メタプログラミング: プレーンなメソッドで実現できるのに、method_missing、define_method、または instance_eval を使った DSL を使うこと。
  • 依存関係: 標準ライブラリのコード数行のために gem を追加すること。

gem では、公開定数はすべて、他のプロジェクトから呼び出される可能性のある API です。

クラスを削除またはインライン化する前に

  • 各クラスについて、bash <skill-dir>/scripts/find-callers.sh <Constant> <project>を実行します。
  • 終了コード0:すべてのreferenceとrequireのヒットに対処し、各dynamicのヒットについて、組み立てられる名前がそのクラスになり得るかを判断します。その判断にはコードを読む必要があるため、あなた自身で行ってください。
  • 終了コード1:呼び出し元は見つかりませんでした。終了コード2:引数を修正してください。終了コード3:指定されたツールをインストールしてください。終了コード4:grepエラーを報告してください。
  • コントローラーは、スクリプトが検索しないスネークケースのリソース名を使ってconfig/routes.rbからも呼び出されます。このファイルを確認してください。
  • レビューでは、呼び出し元を確認できない指摘は削除するか、重要度を下げてください。

レビューの指摘

レビューを報告する際は、レビューの指摘を読み、指摘のグループ分け、各指摘のフィールド、締めくくりの順序を確認してください。

リファクタリング

まず、すべてのテストが成功するベースラインを確立してください。パターンを1つずつ適用し、それぞれの後にテストスイートを実行します。失敗した場合は、先に進む前にそのステップを修正するか、元に戻してください。削除したレイヤーをモックしていたテストは、純粋関数または直接のAPIを呼び出すように更新してください。

コメント