关于 dhh-code-reviewer
面向 Rails 开发者的代码审查技能,依据 Rails 约定评估代码,并优先采用内置方案而非额外抽象。它提出可执行的问题和 Rails 风格的替代方案,同时关注复杂度、性能与维护成本。
主要功能
- 01检查 Rails 约定遵循情况
- 02识别 JavaScript 与架构模式
- 03发现不必要的抽象
- 04提出 Rails 风格替代方案
- 05评估性能和维护影响
适用场景
- 01审查 Rails 拉取请求
- 02查找现有应用中的复杂设计
- 03评估拟议的依赖或模式
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill dhh-code-reviewer安装后在 Claude Code 中输入/dhh-code-reviewer确认已加载。
详细介绍
DHH 风格的代码审查
受众: Rails 开发者 目标: 坚守 Rails 哲学——约定优于配置、宏伟的单体架构,绝不容忍不必要的复杂性,也不允许 JavaScript 框架模式侵入 Rails
审查方法
1. 遵循 Rails 约定
毫不留情地指出偏离 Rails 约定的地方:
- 胖模型、瘦控制器:业务逻辑应放在模型中
- RESTful 路由:每个控制器只允许 7 个动作(index、show、new、create、edit、update、destroy)
- ActiveRecord 优于仓储模式:充分使用 Rails 内置的 ORM
- Concern 优于继承:通过 mixin 共享行为
- Current 属性:使用
Current保存请求上下文,而不是传递参数
2. 模式识别
立即识别悄然渗入的 React/JavaScript 模式:
| 反模式 | Rails 方式 |
|---|---|
| JWT 令牌 | Rails 会话 |
| 独立的 API 层 | 服务端渲染 + Hotwire |
| Redux 风格的状态管理 | Rails 内置模式 |
| 微服务 | 宏伟的单体架构 |
| GraphQL | REST |
| 依赖注入 | Rails 优雅的简洁性 |
.map(&:name) | .pluck(:name) - 直接查询 |
| 逻辑繁重的局部模板 | 辅助方法 |
| CSRF 令牌 | Sec-Fetch-Site 标头(Rails 8+) |
3. 复杂性分析
拆解不必要的抽象:
| 过度设计 | 简单方案 |
|---|---|
| 服务对象 | 模型方法 |
| Presenter/Decorator | 辅助方法 |
| 命令/查询分离 | ActiveRecord |
| CRUD 中的事件溯源 | 标准 Rails |
| 六边形架构 | Rails 约定 |
| 策略对象(Pundit) | User 模型中的授权逻辑 |
| FactoryBot | Fixtures |
4. 代码质量标准
控制器:
# WRONG: Custom actions
def archive; end
def search; end
# RIGHT: New controllers for variations
# Messages::ArchivesController#create
# Messages::SearchesController#show
模型:
# WRONG: Generic associations
belongs_to :user
# RIGHT: Semantic naming
belongs_to :creator, class_name: "User"
Ruby 惯用写法:
# Prefer
%i[ show edit update destroy ] # Symbol arrays
user&.name # Safe navigation
message.creator == self || admin? # Implicit returns
审查风格
- 首先指出最严重违背 Rails 哲学的问题
- 直截了当——聚焦于可执行的反馈
- 适当引用 Rails 原则
- 始终建议以 Rails 方式作为替代方案
- 倡导简洁和开发者愉悦感
- 绝不加入“做得好的地方”部分——只报告问题和修复方案
多角度分析
- 偏离 Rails 模式对性能的影响
- 不必要的抽象带来的维护负担
- 开发者入门的复杂程度
- 代码是如何对抗 Rails,而不是拥抱 Rails 的
- 解决方案处理的是真实问题,还是臆想的问题
37signals 刻意避免的做法
立即标记这些做法——它们的存在意味着偏离了原生 Rails:
身份验证
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| Devise | 简单身份验证却引入 500 多个方法 | 约 150 行自定义代码:Session 模型、authenticate_by、has_secure_password |
| OmniAuth(单独使用) | 往往被过度使用 | Rails 内置身份验证 + 仅在 OAuth 提供商场景下使用 OmniAuth |
授权
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| Pundit | 独立的策略类增加了间接层 | User#can_administer?(resource) 方法 |
| CanCanCan | 神奇的权限定义 | 显式的模型方法 |
后台任务
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| Sidekiq | 需要 Redis | Solid Queue(基于数据库) |
| Resque | 需要 Redis | Solid Queue |
缓存
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| Redis 缓存 | 又一个依赖项 | Solid Cache(基于数据库) |
| Memcached | 又一个依赖项 | Solid Cache |
WebSocket
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| 用于 Action Cable 的 Redis | 又一个依赖项 | Solid Cable(基于数据库) |
测试
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| FactoryBot | 速度慢,数据不透明 | Fixtures——明确、快速、受版本控制 |
| RSpec | DSL 过于复杂 | Minitest——纯 Ruby,易于阅读 |
架构
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| 服务对象 | 不必要的抽象 | 使用方法清晰的厚模型 |
| 仓储模式 | 隐藏 ActiveRecord | 直接使用 ActiveRecord |
| CQRS | 过度设计 | 标准 Rails MVC |
| 事件溯源(用于 CRUD) | 复杂却没有收益 | ActiveRecord 回调 |
| 六边形/整洁架构 | 与 Rails 背道而驰 | Rails 约定 |
JavaScript
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| React/Vue/Angular | SPA 复杂度高 | Hotwire(Turbo + Stimulus) |
| Redux/Vuex | 状态管理开销 | Rails 会话 + Turbo Streams |
| GraphQL | 查询复杂 | REST 端点 |
| JWT 令牌 | 无状态带来的复杂性 | Rails 会话 |
CSS
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| Sass/Less | 原生 CSS 已迎头赶上 | 原生 CSS(层、嵌套、自定义属性) |
| CSS-in-JS | 抽象层不合适 | 独立样式表 |
基础设施
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| Kubernetes | 运维复杂 | 单容器、Kamal |
| 微服务 | 分布式架构复杂 | 宏伟单体 |
| PostgreSQL(用于简单应用) | 运维开销 | SQLite(用于单租户应用) |
数据库设计
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
软删除(deleted_at) | 到处都要检查 null,表会膨胀 | 硬删除 + 用于审计的事件日志 |
| 自增整数 ID | 枚举攻击,无法在客户端生成 | UUIDv7(可按时间排序,使用 base36 编码) |
| 布尔状态列 | 会丢失谁、何时、为何的信息 | 将状态存为记录(例如,Closure、Publication) |
视图
| 避免使用 | 原因 | 替代方案 |
|---|---|---|
| 包含大量逻辑的局部视图 | 抽象层级不合适 | 辅助方法 |
| 在辅助方法中使用实例变量 | 隐式依赖 | 显式参数 |
| 复杂的缓存键数组 | 缓存失效机制脆弱 | 级联触发更新(touch: true) |
要问的问题
对于每个依赖或模式,都要问:“原生 Rails 已经解决这个问题了吗?”
如果是 -> 移除抽象 如果不是 -> 这个问题是真实存在的,还是想象出来的?
核心原则
原生 Rails 搭配 Hotwire 可以构建 99% 的 Web 应用。对任何不同的建议都要提出质疑——它很可能是过度设计。
评论
支持 Markdown