mcpField
L
layered-rails

layered-rails

github.com/majesticlabs-dev開発5042 回インストール7 週間前に更新
リポジトリ

layered-rails について

layered-railsは、単純なパターンでは対応しにくくなったアプリを扱うRails開発者向けのガイダンススキルです。4層アーキテクチャ、コード配置の判断、責務を抽出する目安を解説し、小規模アプリでは簡潔さを勧めます。

主な機能

  1. 01Railsの4層構造と依存ルール
  2. 02層ごとのコード配置ガイダンス
  3. 03抽出の目安とコールバック評価
  4. 04パターン選択と関連スキルの案内
  5. 05モデル構成と複雑度の指針

活用シーン

  1. 01新しいRailsコードの配置先の判断
  2. 02層の違反やリファクタリング対象の特定
  3. 03コールバックの評価と副作用の抽出
  4. 04複雑なRailsドメインへの構造追加

インストール

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

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill layered-rails

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

同梱ファイルreferences/extraction-signals.mdreferences/pattern-catalog.md

詳細

レイヤード Rails アーキテクチャ

対象読者: 単一ファイルのパターンでは対応しきれなくなったアプリケーションに取り組む Rails 開発者。 目標: コードをどのレイヤーに配置するか、いつ抽出するか、実装にどの既存スキルを使うかを把握します。

4 層アーキテクチャ

Presentation  →  Application  →  Domain  →  Infrastructure
(HTTP/UI)        (Orchestration)  (Business)   (Persistence/APIs)

基本ルール: 下位レイヤーは上位レイヤーに依存してはなりません。データは上から下へのみ流れます。

レイヤーの責務
レイヤー担当するもの担当しないもの
プレゼンテーションHTTP に関する処理、パラメーター、レンダリング、チャネル、メーラービジネスロジック、直接的な DB クエリー
アプリケーションモデル間のオーケストレーション、認可、フォームの検証永続化の詳細、レンダリング
ドメインビジネスルール、検証、関連付け、値オブジェクトHTTP コンテキスト、リクエストオブジェクト、Current.*
インフラストラクチャActiveRecord、外部 API、ファイルストレージ、キャッシュビジネスルール、プレゼンテーション
よくあるレイヤー違反
違反問題である理由修正方法
モデル内の Current.userドメインがプレゼンテーションのコンテキストに依存しているユーザーを明示的なパラメーターとして渡す
サービス内の request パラメーターアプリケーションがプレゼンテーションに依存しているサービスを呼び出す前に必要な値を取り出す
コントローラー内の料金計算ビジネスロジックがプレゼンテーションにあるモデルメソッドまたはサービスに移す
すべてのロジックをサービスに置き、モデルを貧血状態にするドメインレイヤーが空洞化しているドメインロジックはモデルに置き、サービスはオーケストレーションを担う
モデルからメールを直接送信するドメインがインフラストラクチャの副作用に依存しているデータ変換にはコールバックのみを使い、メール送信は切り出す

仕様テスト

コードの配置場所が適切かを診断します。

  1. オブジェクトが担う責務をすべて列挙します
  2. それぞれについて、「これはこのレイヤーの主な関心事に属するか?」と確認します
  3. いいえの場合 → 適切なレイヤーに抽出します

例: 認証、アバター処理、通知設定、アクティビティログを担う User モデル。

  • 認証 → ドメイン(そのままにする)
  • アバター処理 → インフラストラクチャ(サービス/ジョブに抽出)
  • 通知設定 → ドメイン(コンサーンとしてそのままにする)
  • アクティビティログ → インフラストラクチャ(オブザーバー/イベントに抽出)

手法の全容については、references/extraction-signals.md を参照してください。

コールバックの評価

各コールバックを 1〜5 で評価します。スコアが 1〜2 のものはすべて抽出します。

スコア種類例対応
5変換before_validation :normalize_emailそのままにする
4正規化before_save :strip_whitespaceそのままにする
4ユーティリティafter_create :update_counter_cacheそのままにする
2オブザーバーafter_save :notify_admin抽出を検討
1オペレーションafter_create :send_welcome_email, :provision_account抽出する

目安: コールバックを削除するとモデル自身のデータ整合性が損なわれる場合は、そのままにします。外部への副作用を引き起こす場合は、抽出します。

パターンの選択

「このコードはどこに置けばよいでしょうか?」

状況パターンレイヤースキル
複雑な複数モデルのフォームForm Objectプレゼンテーション—
リクエストパラメーターのフィルタリングFilter Objectプレゼンテーション—
ビュー固有のフォーマットPresenter / ViewComponentプレゼンテーションviewcomponent-coder
認可ルールPolicy Objectアプリケーションaction-policy-coder
ビジネス操作(1回限り)Service / Interactionアプリケーションactive-interaction-coder
複数モデルのオーケストレーションService Objectアプリケーションactive-interaction-coder
状態ライフサイクルの管理State Machineドメインaasm-coder
複雑で再利用可能なクエリQuery Objectドメイン—
不変の概念(Money、DateRange)Value Objectドメイン—
モデル間で共有する振る舞いConcernドメイン—
型付き設定Config Objectインフラストラクチャanyway-config-coder
ドメインイベント/監査証跡Event Sourcingインフラストラクチャevent-sourcing-coder
JSON に保存される属性Store Modelドメインstore-model-coder
判断ツリー
Is it about HTTP/params/rendering?
  YES → Presentation layer
    Multi-model form? → Form Object
    Filtering params? → Filter Object
    Formatting for view? → Presenter or ViewComponent
  NO ↓

Is it authorization?
  YES → Policy Object (action-policy-coder)
  NO ↓

Does it orchestrate multiple models/services?
  YES → Application layer
    One-time operation? → Service/Interaction (active-interaction-coder)
    Needs typed inputs? → ActiveInteraction (active-interaction-coder)
  NO ↓

Is it a business rule about a single model?
  YES → Domain layer (keep in model or concern)
    Has state transitions? → AASM (aasm-coder)
    Reusable query? → Query Object
    Immutable value? → Value Object
  NO ↓

Is it about persistence/external APIs/caching?
  YES → Infrastructure layer

サービスは待合室

app/services/ は一時的な置き場所であり、恒久的な場所ではありません。

  • 生き残ったサービスは、最終的にそれが表す本当の抽象を明らかにするはずです
  • サービスが単一モデルの操作をラップしている場合 → おそらくモデルに置くべきです
  • サービスが3つ以上のモデルを連携させている場合 → 正当なオーケストレーターです
  • サービスが複雑になってきた場合 → 内部に隠れている Form Object、Policy、Query Object を探します

においチェック: app/services/ にサブディレクトリがなく、ファイルが50個以上ある場合、待合室が恒久的な保管場所になっています。

抽出の兆候

既存の場所からコードを抽出するタイミング:

兆候しきい値対応
メソッドの長さ15行超メソッドまたはオブジェクトを抽出
モデル内の外部 API 呼び出し1回でもサービス/ゲートウェイに抽出
神オブジェクト高い変更頻度 × 高い複雑度分解(references/extraction-signals.md を参照)
仕様がレイヤーの関心事を超えている仕様テストに失敗適切なレイヤーに抽出
コールバックのスコア1~2/5サービスまたはイベントハンドラーに抽出
クエリロジックの重複2か所以上Query Object を抽出
モデル内の Current.*使用箇所がある明示的なパラメーターとして渡す

完全な方法については、references/extraction-signals.md を参照してください。

モデルの整理

モデルファイル内の推奨される順序:

class Order < ApplicationRecord
  # 1. Extensions/DSL (has_secure_password, acts_as_*)
  # 2. Associations
  # 3. Enums
  # 4. Normalizations
  # 5. Validations
  # 6. Scopes
  # 7. Callbacks (transformers/normalizers only — score 4-5)
  # 8. Delegations
  # 9. Public methods
  # 10. Private methods
end

レイヤードスタイルとDHHスタイルの使い分け

このスキルは dhh-coder を補完するものであり、置き換えるものではありません。

状況使用するもの
小規模/中規模アプリ、標準的な CRUDdhh-coder — シンプルに保つ
複雑なドメイン、複数の境界づけられたコンテキストlayered-rails — 構造を追加する
単純なチェックを超える認可レイヤードガイダンス経由で action-policy-coder
500行を超える肥大化したモデルlayered-rails の抽出の兆候
標準的なコントローラーアクションdhh-coder — 7つの REST アクション
複数ステップのビジネス操作レイヤードガイダンス経由で active-interaction-coder

まずはシンプルさを優先してください。 複雑さが求める場合にのみ、レイヤードパターンを採用します。

成功チェックリスト

  • 逆方向の依存関係がない(下位レイヤーが上位レイヤーを参照しない)
  • モデルが Current の属性にアクセスしない
  • サービスがリクエスト/コントローラーオブジェクトを受け取らない
  • コントローラーに含まれるのは HTTP に関する処理のみ
  • ドメインロジックはサービスに漏れず、モデルに置かれている
  • すべてのコールバックのスコアが4以上(または抽出済み)
  • Concern は成果物の種類ではなく、振る舞いごとにまとめられている
  • 各抽象は1つのレイヤーにのみ属している

Cross-References

NeedSkill
Authorization policiesaction-policy-coder
Typed business operationsactive-interaction-coder
State machinesaasm-coder
Operations + state routingbusiness-logic-coder
ViewComponentsviewcomponent-coder
Typed configurationanyway-config-coder
Event sourcing / auditevent-sourcing-coder
JSON attributesstore-model-coder
Refactoring executionrails-refactorer
DHH-style simplicitydhh-coder
Pattern catalog detailsreferences/pattern-catalog.md
Extraction methodologyreferences/extraction-signals.md

コメント