layered-rails

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Layered Rails

分层架构的Rails应用

Design and review Rails applications using layered architecture principles.
运用分层架构原则来设计和评审Rails应用。

Quick Start

快速开始

Rails applications are organized into four architecture layers with unidirectional data flow:
┌─────────────────────────────────────────┐
│           PRESENTATION LAYER            │
│  Controllers, Views, Channels, Mailers  │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│           APPLICATION LAYER             │
│   Service Objects, Form Objects, etc.   │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│             DOMAIN LAYER                │
│  Models, Value Objects, Domain Events   │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│          INFRASTRUCTURE LAYER           │
│  Active Record, APIs, File Storage      │
└─────────────────────────────────────────┘
Core Rule: Lower layers must never depend on higher layers.
Rails应用被组织为四个架构层,遵循单向数据流
┌─────────────────────────────────────────┐
│           PRESENTATION LAYER            │
│  Controllers, Views, Channels, Mailers  │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│           APPLICATION LAYER             │
│   Service Objects, Form Objects, etc.   │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│             DOMAIN LAYER                │
│  Models, Value Objects, Domain Events   │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│          INFRASTRUCTURE LAYER           │
│  Active Record, APIs, File Storage      │
└─────────────────────────────────────────┘
核心规则: 下层绝不能依赖上层。

What Would You Like To Do?

你想执行哪些操作?

  1. Analyze codebase - Run
    /layers:analyze
    for full analysis or
    /layers:analyze:callbacks
    ,
    /layers:analyze:gods
    for specific checks
  2. Review code changes - Run
    /layers:review
    for layered architecture review
  3. Run specification test - Run
    /layers:spec-test
    on specific files
  4. Plan gradual adoption - Run
    /layers:gradual [goal]
    to plan incremental layerification
  5. Plan feature implementation - I'll guide you using layered principles
  6. Implement specific pattern - I'll help with authorization, notifications, view components, AI integration, etc.
  1. 分析代码库 - 运行
    /layers:analyze
    进行全面分析,或运行
    /layers:analyze:callbacks
    /layers:analyze:gods
    进行专项检查
  2. 评审代码变更 - 运行
    /layers:review
    进行分层架构评审
  3. 运行规范测试 - 对特定文件运行
    /layers:spec-test
  4. 规划逐步落地 - 运行
    /layers:gradual [goal]
    来规划分层架构的增量落地
  5. 规划功能实现 - 我会基于分层原则为你提供指导
  6. 实现特定模式 - 我会协助你实现授权、通知、视图组件、AI集成等模式

Core Principles

核心原则

The Four Rules

四大规则

  1. Unidirectional Data Flow - Data flows top-to-bottom only
  2. No Reverse Dependencies - Lower layers never depend on higher layers
  3. Abstraction Boundaries - Each abstraction belongs to exactly one layer
  4. Minimize Connections - Fewer inter-layer connections = looser coupling
  1. 单向数据流 - 数据仅从上到下流动
  2. 无反向依赖 - 下层绝不能依赖上层
  3. 抽象边界 - 每个抽象仅属于一个层级
  4. 最小化连接 - 层间连接越少,耦合度越低

Common Violations

常见违规情况

ViolationExampleFix
Model uses Current
Current.user
in model
Pass user as explicit parameter
Service accepts request
param :request
in service
Extract value object from request
Controller has business logicPricing calculations in actionExtract to service or model
Anemic modelsAll logic in servicesKeep domain logic in models
See Anti-Patterns Reference for complete list.
违规类型示例修复方案
模型使用Current
Current.user
在模型中
将用户作为显式参数传入
服务接收request服务中使用
param :request
从request中提取值对象
控制器包含业务逻辑动作中包含定价计算提取到服务或模型中
贫血模型所有逻辑都在服务中将领域逻辑保留在模型中
完整列表请查看 反模式参考

The Specification Test

规范测试

If the specification of an object describes features beyond the primary responsibility of its abstraction layer, such features should be extracted into lower layers.
How to apply:
  1. List responsibilities the code handles
  2. Evaluate each against the layer's primary concern
  3. Extract misplaced responsibilities to appropriate layers
See Specification Test Reference for detailed guide.
如果一个对象的规范描述超出了其抽象层的主要职责,这些功能应被提取到更低层级。
应用方法:
  1. 列出代码处理的所有职责
  2. 逐一评估每个职责是否符合所在层级的核心关注点
  3. 将错位的职责提取到合适的层级
详细指南请查看 规范测试参考

Pattern Catalog

模式目录

PatternLayerUse WhenReference
Service ObjectApplicationOrchestrating domain operationsservice-objects.md
Query ObjectDomainComplex, reusable queriesquery-objects.md
Form ObjectPresentationMulti-model forms, complex validationform-objects.md
Filter ObjectPresentationRequest parameter transformationfilter-objects.md
PresenterPresentationView-specific logic, multiple modelspresenters.md
SerializerPresentationAPI response formattingserializers.md
Policy ObjectApplicationAuthorization decisionspolicy-objects.md
Value ObjectDomainImmutable, identity-less conceptsvalue-objects.md
State MachineDomainStates, events, transitionsstate-machines.md
ConcernDomainShared behavioral extractionconcerns.md
模式层级适用场景参考文档
Service Object应用层编排领域操作service-objects.md
Query Object领域层复杂、可复用的查询query-objects.md
Form Object表示层多模型表单、复杂验证form-objects.md
Filter Object表示层请求参数转换filter-objects.md
Presenter表示层视图特定逻辑、多模型处理presenters.md
Serializer表示层API响应格式化serializers.md
Policy Object应用层授权决策policy-objects.md
Value Object领域层不可变、无标识的概念value-objects.md
State Machine领域层状态、事件、转换state-machines.md
Concern领域层提取共享行为concerns.md

Pattern Selection Guide

模式选择指南

"Where should this code go?"
If you have...Consider...
Complex multi-model formForm Object
Request parameter filtering/transformationFilter Object
View-specific formattingPresenter
Complex database query used in multiple placesQuery Object
Business operation spanning multiple modelsService Object (as waiting room)
Authorization rulesPolicy Object
Multi-channel notificationsDelivery Object (Active Delivery)
Remember: Services are a "waiting room" for code until proper abstractions emerge. Don't let
app/services
become a bag of random objects.
“这段代码应该放在哪里?”
如果你有...考虑使用...
复杂的多模型表单Form Object
请求参数过滤/转换Filter Object
视图特定格式化Presenter
多处使用的复杂数据库查询Query Object
跨多模型的业务操作Service Object(作为过渡)
授权规则Policy Object
多渠道通知Delivery Object(Active Delivery)
注意: Service Object是代码的“过渡区”,直到合适的抽象出现。不要让
app/services
变成存放随机对象的“垃圾袋”。

Commands Reference

命令参考

CommandPurpose
/layers:review
Review code changes from layered architecture perspective
/layers:spec-test
Run specification test on specific files
/layers:analyze
Full codebase abstraction layer analysis
/layers:analyze:callbacks
Score model callbacks, find extraction candidates
/layers:analyze:gods
Find God objects via churn × complexity
/layers:gradual [goal]
Plan gradual adoption of layered patterns
命令用途
/layers:review
从分层架构角度评审代码变更
/layers:spec-test
对特定文件运行规范测试
/layers:analyze
全面分析代码库的抽象层级
/layers:analyze:callbacks
评分模型回调,寻找可提取的候选
/layers:analyze:gods
通过变更频率×复杂度寻找上帝对象
/layers:gradual [goal]
规划分层模式的逐步落地

Topic References

主题参考

For deep dives on specific topics:
TopicReference
Authorization (RBAC, ABAC, policies)authorization.md
Notifications (multi-channel delivery)notifications.md
View Componentsview-components.md
AI Integration (LLM, agents, RAG, MCP)ai-integration.md
Configurationconfiguration.md
Callbacks (scoring, extraction)callbacks.md
Current Attributescurrent-attributes.md
Instrumentation (logging, metrics)instrumentation.md
特定主题的深入探讨:
主题参考文档
授权(RBAC、ABAC、策略)authorization.md
通知(多渠道投递)notifications.md
视图组件view-components.md
AI集成(LLM、Agent、RAG、MCP)ai-integration.md
配置configuration.md
回调(评分、提取)callbacks.md
Current属性current-attributes.md
Instrumentation(日志、指标)instrumentation.md

Gem References

Gem参考

For library-specific guidance:
GemPurposeReference
action_policyAuthorization frameworkaction-policy.md
view_componentComponent frameworkview-component.md
anyway_configTyped configurationanyway-config.md
active_deliveryMulti-channel notificationsactive-delivery.md
albaJSON serializationalba.md
workflowState machinesworkflow.md
rubanokFilter/transformation DSLrubanok.md
active_agentAI agent frameworkactive-agent.md
active_job-performsEliminate anemic jobsactive-job-performs.md
特定库的使用指导:
Gem用途参考文档
action_policy授权框架action-policy.md
view_component组件框架view-component.md
anyway_config类型化配置anyway-config.md
active_delivery多渠道通知active-delivery.md
albaJSON序列化alba.md
workflow状态机workflow.md
rubanok过滤/转换DSLrubanok.md
active_agentAI Agent框架active-agent.md
active_job-performs消除贫血Jobactive-job-performs.md

Extraction Signals

提取信号

When to extract from models:
SignalMetricAction
God objectHigh churn × complexityDecompose into concerns, delegates, or separate models
Operation callbackScore 1-2/5Extract to service or event handler
Code-slicing concernGroups by artifact typeConvert to behavioral concern or extract
Current dependencyModel reads Current.*Pass as explicit parameter
Callback Scoring:
TypeScoreKeep?
Transformer (compute values)5/5Yes
Normalizer (sanitize input)4/5Yes
Utility (counter caches)4/5Yes
Observer (side effects)2/5Maybe
Operation (business steps)1/5Extract
See Extraction Signals Reference for detailed guide.
何时从模型中提取代码:
信号指标操作
上帝对象高变更频率×复杂度分解为Concern、委托或独立模型
操作型回调评分1-2/5提取到服务或事件处理器
代码切片型Concern按 artifact 类型分组转换为行为型Concern或提取
依赖Current模型读取Current.*作为显式参数传入
回调评分:
类型评分是否保留?
转换器(计算值)5/5
归一化器(清理输入)4/5
工具类(计数器缓存)4/5
观察者(副作用)2/5可考虑
操作型(业务步骤)1/5提取
详细指南请查看 提取信号参考

Model Organization

模型组织

Recommended order within model files:
ruby
class User < ApplicationRecord
  # 1. Gems/DSL extensions
  has_secure_password

  # 2. Associations
  belongs_to :account
  has_many :posts

  # 3. Enums
  enum :status, { pending: 0, active: 1 }

  # 4. Normalization
  normalizes :email, with: -> { _1.strip.downcase }

  # 5. Validations
  validates :email, presence: true

  # 6. Scopes
  scope :active, -> { where(status: :active) }

  # 7. Callbacks (transformers only)
  before_validation :set_defaults

  # 8. Delegations
  delegate :name, to: :account, prefix: true

  # 9. Public methods
  def full_name = "#{first_name} #{last_name}"

  # 10. Private methods
  private

  def set_defaults
    self.locale ||= I18n.default_locale
  end
end
模型文件内的推荐顺序:
ruby
class User < ApplicationRecord
  # 1. Gems/DSL extensions
  has_secure_password

  # 2. Associations
  belongs_to :account
  has_many :posts

  # 3. Enums
  enum :status, { pending: 0, active: 1 }

  # 4. Normalization
  normalizes :email, with: -> { _1.strip.downcase }

  # 5. Validations
  validates :email, presence: true

  # 6. Scopes
  scope :active, -> { where(status: :active) }

  # 7. Callbacks (transformers only)
  before_validation :set_defaults

  # 8. Delegations
  delegate :name, to: :account, prefix: true

  # 9. Public methods
  def full_name = "#{first_name} #{last_name}"

  # 10. Private methods
  private

  def set_defaults
    self.locale ||= I18n.default_locale
  end
end

Success Checklist

成功检查清单

Well-layered code:
  • No reverse dependencies (lower layers don't depend on higher)
  • Models don't access Current attributes
  • Services don't accept request objects
  • Controllers are thin (HTTP concerns only)
  • Domain logic lives in models, not services
  • Callbacks score 4+ or are extracted
  • Concerns are behavioral, not code-slicing
  • Abstractions don't span multiple layers
  • Tests verify appropriate layer responsibilities
分层良好的代码:
  • 无反向依赖(下层不依赖上层)
  • 模型不访问Current属性
  • 服务不接收request对象
  • 控制器轻量化(仅处理HTTP相关逻辑)
  • 领域逻辑位于模型中,而非服务中
  • 回调评分4+或已被提取
  • Concern是行为型的,而非代码切片型
  • 抽象不跨多个层级
  • 测试验证了层级职责的合理性

Guidelines

指导原则

  • Use domain language - Name models after business concepts (Participant, not User; Cloud, not GeneratedImage)
  • Patterns before abstractions - Let code age before extracting; premature abstraction is worse than duplication
  • Services as waiting room - Don't let
    app/services
    become permanent residence for code
  • Explicit over implicit - Prefer explicit parameters over Current attributes
  • Extraction thresholds - Consider extraction when methods exceed 15 lines or call external APIs
  • 使用领域语言 - 用业务概念为模型命名(如Participant而非User;Cloud而非GeneratedImage)
  • 先模式后抽象 - 让代码沉淀后再提取;过早抽象比重复代码更糟糕
  • 服务作为过渡区 - 不要让
    app/services
    成为代码的永久居所
  • 显式优于隐式 - 优先使用显式参数而非Current属性
  • 提取阈值 - 当方法超过15行或调用外部API时,考虑提取