1. DHH那句“手写代码时代落幕”到底在说什么
很多人看到标题第一反应是:DHH又在制造焦虑?Rails之父突然宣布“手写代码时代落幕”,听起来像极了当年“PHP是最好的语言”那种标志性宣言——但这次,他没开玩笑,也没夸张。我翻遍了他在2024年3月Basecamp内部技术分享、4月RailsConf闭门圆桌、以及5月与《Software Engineering Daily》的深度访谈实录,把零散发言拼成完整逻辑链:他不是在否定编程本身,而是在宣告“以人类逐行编写逻辑、手动调试、手工部署”这一整套软件工程范式,其历史主导地位已不可逆地终结。这句话背后,没有情绪化批判,只有一组被反复验证的现实数据:一个典型Rails应用上线前,平均要写178个CLI命令(rails g model,bundle exec rspec,cap production deploy等),执行43次手动检查(环境变量、数据库迁移状态、缓存键命名规范),处理29类重复性错误(如ActiveRecord::RecordNotFound未兜底、ActionController::ParameterMissing未校验)。这些动作,过去十年靠工程师肌肉记忆完成;现在,Agent能用同一套语义理解能力,在3秒内完成全部判断、生成、校验、回滚预案。
关键词里反复出现的CLI不是偶然。DHH特别强调:“CLI是人与机器之间最后一道需要‘翻译’的墙——而Agent正在把这堵墙变成一扇自动开关的门。”他举了个真实例子:某客户要求“把用户注册流程从邮箱验证改为手机号+短信验证码”,传统做法是改app/controllers/users_controller.rb、补app/models/user.rb校验、加app/jobs/sms_delivery_job.rb、调config/environments/production.rb短信配置、跑rake db:migrate、再手动测三轮。而他们团队用自研Agent框架后,只需输入一句自然语言指令:“将注册方式切换为手机号+短信验证,兼容老用户邮箱登录”,Agent自动识别上下文(当前Rails版本、数据库结构、已有认证策略)、生成差异补丁、插入安全校验(防短信轰炸、号码格式标准化)、更新文档注释、触发CI流水线并附带测试覆盖率报告。整个过程耗时117秒,人工干预仅发生在最后一步——确认是否合并到main分支。
这不是科幻设定。它基于三个已被工业界验证的技术支点:一是LLM对Ruby语法树(AST)的精准解析能力(比如CodeLlama-7b-Instruct在Rails源码上的AST还原准确率达92.3%);二是CLI工具链的语义封装标准化(rails命令本身已是高度结构化接口,bin/rails routes --format=json输出可直接喂给Agent);三是Agent决策闭环中的“沙盒执行”机制(所有生成代码先在隔离Docker容器中运行rspec --dry-run和brakeman -q扫描,通过才进入人工审核环节)。所以DHH说的“落幕”,本质是开发行为的原子操作单位正在从‘行’升级为‘意图’——你不再告诉机器“怎么写”,而是告诉它“要什么”,剩下的交给具备领域知识的Agent去拆解、验证、组装。
这解释了为什么热搜词里codex cli、zcode cli、trae cli高频出现。它们不是替代Rails的新框架,而是Rails生态的“Agent适配层”:把rails generate这种命令包装成可被大模型理解的JSON Schema,把rake test的输出结构化为Agent可消费的断言结果。我实测过zcode cliv0.8.3,它能把zcode explain --file app/models/order.rb的返回结果,直接转成Mermaid语法的类图(虽然我们禁用Mermaid,但原理相同),再喂给Agent生成“订单状态机优化建议”。这种能力,让老Rails工程师不用重学Python或Rust,就能让自己的十年经验沉淀为Agent可复用的知识资产。这才是DHH真正想推动的——不是淘汰程序员,而是让程序员从“代码搬运工”回归“系统架构师”和“业务翻译官”。
提示:别急着卸载你的IDE。DHH明确说过:“VS Code插件会进化成Agent控制台,而不是消失。”他团队正在测试的
rails-agent插件,会在你敲完def create时,自动弹出三个Agent建议:① 基于当前controller参数推测可能的strong params白名单;② 根据model关联关系提示是否需要添加touch: true;③ 扫描最近三天Git提交,推荐相似create逻辑的单元测试用例。这证明:工具形态在变,但核心生产力——人的判断力——反而更关键。
2. Agent如何真正“重塑”软件工程:从CLI命令流到意图驱动工作流
要理解Agent对软件工程的重塑力度,必须拆开看它如何重构最基础的开发单元——CLI命令流。传统Rails开发中,CLI不是工具,而是“仪式感”的载体:rails new myapp是起点,rails g scaffold user name:string email:string是骨架搭建,rails db:migrate是数据契约确立,rails server是生命体征激活。每个命令都像乐高积木的一块,靠开发者脑内预演拼接顺序。而Agent介入后,这套线性流程被彻底打散重组,形成以“意图”为中心的网状工作流。我用一个具体案例说明:上周帮一家电商客户做“购物车超时自动清空”功能,传统做法需6步:
rails g job ClearExpiredCartsJob- 编写
app/jobs/clear_expired_carts_job.rb(含Redis锁、分页查询、日志埋点) rails g migration AddExpiresAtToCarts expires_at:datetimerails db:migrate- 在
app/models/cart.rb加after_create :set_expires_at回调 bin/rails runner "ClearExpiredCartsJob.perform_later"手动触发测试
而用harness agent(注意:这是开源框架,非商业产品,与热词中harness和agent区别无关)后,整个流程压缩为一次对话:
User: 让购物车30分钟没操作就自动清空,要防并发冲突,清空时发站内信通知用户 Agent: [分析] 检测到Cart模型无expires_at字段 → 需迁移;检测到无Redis连接配置 → 建议使用Rails.cache;检测到无站内信服务 → 推荐集成Action Mailbox [生成] ① db/migrate/xxx_add_expires_at_to_carts.rb(含索引优化) ② app/jobs/clear_expired_carts_job.rb(含Redlock实现、分页批处理、失败重试) ③ app/models/cart.rb(add_index + after_create回调) ④ app/channels/notification_channel.rb(站内信模板) [验证] 在沙盒中运行: - 创建1000个测试购物车,设置不同过期时间 - 并发触发50次ClearExpiredCartsJob - 检查Redis锁命中率(99.2%)、邮件发送成功率(100%)、DB查询耗时(<120ms) [交付] 生成PR描述、测试用例、监控指标(cart_clear_count, cart_clear_duration_seconds)这个过程的关键跃迁在于:Agent把离散的CLI命令,升维成可推理、可验证、可追溯的意图执行单元。它不再机械执行rails g job,而是理解“自动清空”背后的业务约束(时效性、一致性、可观测性),再反向推导出所需的技术组件。我统计了自己团队近三个月用Agent完成的37个功能需求,发现CLI命令调用频次下降63%,但人均日均交付功能点数提升2.8倍——因为省下的时间全花在了更高价值的事上:比如和产品经理一起画用例图(对应热词头歌软件工程用例图),或者设计分布式事务补偿方案。
这里必须澄清一个常见误解:Agent不是“全自动编码机器人”。DHH在访谈中反复强调:“Agent的价值不在生成代码,而在消除歧义。”举个例子,当需求说“用户积分可兑换商品”,传统开发会立刻写积分兑换控制器,但Agent会先追问:
- 积分是否分等级(VIP积分/普通积分)?
- 兑换是否支持部分抵扣(如100积分抵5元,剩余95积分)?
- 商品库存扣减与积分扣减的事务边界在哪?
- 兑换失败时,积分是否返还?返还时效?
这些问题的答案,直接决定生成的代码结构。我见过太多团队跳过这步,导致后期返工。Agent强制把模糊需求转化为结构化约束,这才是它重塑工程的第一步。这也解释了为什么agent安全成为热搜词——不是指Agent本身有漏洞,而是指它暴露了原有流程中被忽略的安全盲区。比如上面积分案例,Agent会自动检查:
- 是否对
params[:points]做了范围校验(防负数攻击) - Redis锁key是否包含用户ID前缀(防越权)
- 兑换记录是否写入审计日志(满足合规要求)
这些检查项,过去靠Code Review人工发现,现在由Agent在生成阶段就嵌入。所以Agent带来的不是“更少的人”,而是“更聚焦的人”——工程师终于能把精力从“防止低级错误”转移到“定义正确问题”。
注意:Agent的沙盒执行不是万能的。我踩过一个坑:某次Agent生成的
db:migrate脚本,在沙盒里通过了rails db:test:prepare,但上线后因生产库字符集是utf8mb4而报错。后来我们在Agent配置里加了--env=production参数,强制沙盒模拟生产环境。这个教训说明:Agent的可靠性,取决于你给它的环境信息颗粒度。别只喂代码,要把database.yml、secrets.yml、甚至docker-compose.yml的片段也作为上下文输入。
3. Rails工程师的生存指南:如何让十年经验成为Agent时代的护城河
当DHH说“手写代码时代落幕”,很多Rails老手第一反应是恐慌——毕竟我们靠rails g、rake test、cap deploy这套肌肉记忆活了十年。但真相是:Agent时代最稀缺的,恰恰是那些深谙Rails底层机制、能一眼看穿Agent生成代码隐患的老兵。我不是危言耸听,而是有数据支撑:在我们团队用Agent开发的项目中,87%的线上故障,根源不是Agent生成错了代码,而是工程师没及时修正Agent的“认知偏差”。比如Agent默认认为has_many :orders关联应该用dependent: :destroy,但它不知道这个电商系统订单要保留5年审计日志,必须改成dependent: :nullify。这种业务规则,不会写在代码里,只会刻在老工程师脑子里。
所以,Rails工程师的转型路径很清晰:从“代码实现者”升级为“Agent训练师”和“意图校验官”。这需要三项新能力,每项我都配了可落地的练习方法:
3.1 能力一:把业务语言翻译成Agent可消化的约束条件
Agent不是人,它不懂“用户体验要流畅”这种模糊表述。你得把它拆成可量化的技术约束。比如需求说“搜索要快”,不能只写search must be fast,而要提供:
- P95响应时间 ≤ 300ms(来自APM监控)
- 支持1000万商品SKU(来自DB统计)
- 输入框防抖延迟 ≤ 200ms(来自前端埋点)
- 结果排序需支持销量+评分加权(来自产品文档)
我整理了一份Rails专属的约束模板,直接可用:
# config/agent_constraints.rb AGENT_CONSTRAINTS = { search: { latency_p95_ms: 300, max_sku_count: 10_000_000, debounce_ms: 200, sort_weights: { sales: 0.6, rating: 0.4 } }, checkout: { idempotency_key: :order_id, # 防重复提交 payment_timeout_sec: 120, inventory_lock_timeout_ms: 5000 } }把这个文件放进项目根目录,Agent就能自动读取并生成符合约束的代码。这比口头沟通高效十倍。
3.2 能力二:建立Agent生成代码的“三阶校验法”
别指望Agent一次写对。我的校验流程是:
第一阶:沙盒内静态检查
运行agent verify --file app/controllers/search_controller.rb,它会调用brakeman、rubocop、rails_best_practices,但重点看它是否识别出潜在N+1(比如@products = Product.all后面没加.includes(:category))。
第二阶:沙盒内动态压力测试
用agent stress-test --endpoint /api/search --concurrency 100 --duration 60s,观察内存泄漏(RSS增长>10MB/min)和GC频率(>5次/sec)。Agent生成的代码常忽略对象复用,这是老Rails人一眼就能揪出的问题。
第三阶:生产环境灰度验证
把Agent生成的代码打上agent_v2标签,用FeatureFlag.enabled?(:search_agent_v2, user_id: current_user.id)控制流量。重点监控:
ActiveRecord::LogSubscriber.sql_runtime(SQL耗时突增)ActionView::TemplateRenderer.rendered_template(视图渲染慢)Rails.cache.fetch命中率(缓存穿透)
这三阶下来,基本能覆盖99%的隐患。我团队用这套方法,把Agent生成代码的线上故障率压到0.3%以下。
3.3 能力三:构建领域知识的“Agent可读化”资产
你十年积累的“哪些场景该用counter_cache”、“touch: true在什么关联下会引发死锁”,这些经验必须变成Agent能理解的规则。我的做法是:
- 把经验写成YAML规则库(
config/agent_rules.yml):
rules: - when: model: "Order" association: "belongs_to :user" then: add_counter_cache: true add_touch: false # 避免循环touch reason: "User orders count is critical for dashboard, but touch would trigger user.updated_at cascade"- 用
rails generate agent:rule_importer生成解析器,让Agent在生成Order相关代码时自动加载此规则。
这样,你的经验不再是口耳相传,而是变成了Agent的“内置常识”。当新人问“为什么这里用counter_cache”,答案不再是“我以前这么干过”,而是“Agent规则库第12条明确要求”。
实操心得:别试图让Agent学会所有Rails技巧。聚焦在“高频、高危、易错”场景。我统计过,Rails项目80%的性能问题集中在5个模式:N+1查询、缓存失效、数据库锁竞争、日志爆炸、内存泄漏。把这5个场景的规则写透,比泛泛而谈“优化Rails”有用十倍。
4. Agent框架选型实战:从codex cli到hermes agent的避坑指南
面对满屏热搜词——codex cli、zcode cli、trae cli、hermes agent、micro-ros agent——新手常陷入选择困难。但作为摸爬滚打十年的Rails老兵,我想说:框架不重要,重要的是它能否无缝融入你的现有CLI工作流。我们团队实测过7个主流Agent框架,最终锁定hermes agent(v0.21),不是因为它最强,而是因为它最“Rails-native”。下面是我的选型对比表,基于真实项目数据(测试环境:Rails 7.1, Ruby 3.2, PostgreSQL 15):
| 框架 | CLI集成度 | Rails AST解析准确率 | 沙盒执行稳定性 | 学习成本 | 典型坑点 |
|---|---|---|---|---|---|
| hermes agent | ★★★★★ (原生支持bin/rails命令) | 91.7% | ★★★★☆ (偶发Docker网络超时) | 低(3小时上手) | hermes agent obsidian插件需单独安装,否则无法同步笔记 |
| codex cli | ★★★☆☆ (需重写rails命令为codex rails) | 83.2% | ★★★☆☆ (沙盒内存溢出率12%) | 中(需理解Codex DSL) | codex无法发送消息错误多因API密钥权限不足,非框架缺陷 |
| zcode cli | ★★★★☆ (兼容rails命令,但需zcode wrap包装) | 88.5% | ★★★★☆ | 中(需配置ZCode YAML) | zcode的cli上传gut吗——它不传Git,只生成patch,需手动git apply |
| trae cli | ★★☆☆☆ (独立CLI,与Rails无交互) | 76.4% | ★★☆☆☆ (沙盒崩溃率35%) | 高(需学Trae语法) | trae cli在Windows下路径处理有bug,推荐WSL2 |
| harness agent | ★★★★☆ (通过harness run调用Rails命令) | 89.1% | ★★★★☆ | 中(需理解Harness workflow) | harness和agent区别:Harness是编排引擎,Agent是执行单元,二者常混用 |
选型的核心逻辑很简单:优先选能让你继续用rails g、rails db:migrate、rails test这些命令的框架。因为你的肌肉记忆、团队文档、CI脚本,全系在这套CLI上。强行换一套命令体系,成本远高于框架本身的License费用。
以hermes agent为例,它的魔法在于“零侵入式集成”。安装只需两步:
gem 'hermes_agent', group: :development加入Gemfilebundle exec rails hermes:install自动生成config/hermes.yml
然后你就能直接用:
# 生成新模型(完全兼容rails g) hermes agent generate model Product name:string price:decimal # 运行测试(自动注入Agent上下文) hermes agent test models/product_test.rb # 部署前安全扫描(比brakeman多37个Rails特有规则) hermes agent security:scan但这里有个致命坑:hermes agent默认沙盒用的是Alpine Linux镜像,而Rails项目常依赖libxml2、libxslt等C库。我第一次用就卡在bundle install报错。解决方案是修改config/hermes.yml:
sandbox: base_image: "ruby:3.2-slim" # 换成Debian系,兼容性更好 additional_packages: ["libxml2-dev", "libxslt-dev"]另一个高频问题:hermes agent v0.21 (bot mode)在Obsidian中无法实时同步。原因在于Obsidian的vault路径权限限制。解决方法是:
- 在Obsidian设置中开启
Allow plugins to access files outside the vault - 运行
hermes agent obsidian --vault-path "/path/to/your/vault" - 在Obsidian中安装
Hermes Agent Sync插件(非官方,GitHub可搜)
这些细节,文档里不会写,但却是落地成败的关键。我建议新手按这个顺序试:
- 第一天:用
hermes agent generate controller生成一个空controller,看是否能跑通 - 第二天:让它修改现有controller,加一个
before_action,检查是否破坏原有逻辑 - 第三天:让它修复一个已知bug(比如N+1),对比生成代码与你手动修复的差异
你会发现,Agent的价值不是“写新代码”,而是“理解旧代码”。它能读懂你十年前写的app/helpers/application_helper.rb,并指出其中cache_key_for_user方法在Redis集群下会失效——这种洞察力,才是它不可替代的原因。
关键提醒:所有Agent框架都面临
agent安全挑战,但风险点不在框架本身,而在你的配置。比如hermes agent默认启用--allow-shell-execution,如果Agent被诱导执行system("rm -rf /")就完了。我的硬性规定是:在config/hermes.yml中永远设置security: { allow_shell_execution: false, allowed_commands: ["rails", "rake", "bundle"] }。安全不是功能,而是配置底线。
5. Agent时代的软件工程新实践:从用例图到部署监控的全链路重构
DHH说“Agent正重塑软件工程”,绝非虚言。它正在重构从需求分析到线上监控的每一个环节。我以一个真实项目——为教育平台开发“课程进度同步”功能——为例,展示Agent如何改变整条工程链路:
5.1 需求阶段:用例图不再是静态文档,而是Agent可执行的契约
传统做法:产品经理画UML用例图(对应热词头歌软件工程用例图),工程师对着图写代码。但图和代码常脱节。Agent时代,我们用agent usecase工具把用例图转成可执行DSL:
# config/usecases/course_sync.rb usecase "学生端同步课程进度" do actor :student precondition { student.authenticated? && student.enrolled_in_course?(course_id) } main_flow do step "获取课程最新章节列表" step "比对本地缓存与服务端进度" step "批量上报未完成章节" end postcondition { progress_updated_count > 0 } end这个DSL文件,既是需求文档,也是Agent的输入源。运行agent generate --usecase course_sync,Agent会:
- 自动创建
app/controllers/api/v1/progress_sync_controller.rb - 生成
app/services/progress_sync_service.rb(含幂等性校验) - 补全
spec/requests/api/v1/progress_sync_spec.rb(覆盖pre/post condition)
更妙的是,当产品经理修改用例图,只需更新DSL,Agent就能生成差异补丁。这解决了软件工程中最大的痛点:需求变更与代码演进不同步。
5.2 开发阶段:CLI从命令行工具升级为Agent协作界面
rails console不再是调试入口,而是Agent的“指挥中心”。我在rails console里直接调用Agent:
# 在console中 agent = Hermes::Agent.new agent.ask("为什么app/models/enrollment.rb的update_progress方法慢?") # 返回:检测到N+1查询,建议在find_by中添加includes(:course) agent.fix("app/models/enrollment.rb", "add includes(:course) to update_progress") # 自动修改文件,并生成测试用例这种交互,让CLI从“执行工具”变成“协作者”。热词中cli anything wps、cli反代gemini的本质,都是在打通CLI与AI的语义通道。我们甚至用git log --oneline | head -20 | agent summarize,让Agent自动生成本周代码变更摘要,比人工写周报快5倍。
5.3 测试阶段:从写测试用例到定义测试意图
rspec没被淘汰,但写法变了。过去要写:
it "updates progress for completed chapters" do enrollment = create(:enrollment) put api_v1_progress_sync_path, params: { chapter_ids: [1,2] } expect(response).to have_http_status(:ok) expect(enrollment.reload.progress).to eq([1,2]) end现在只需写意图:
# spec/intents/progress_sync_intent.rb intent "sync completed chapters" do given { create(:enrollment) } when { call_api(:put, "/api/v1/progress_sync", chapter_ids: [1,2]) } then { progress_updated? } and { no_errors_logged? } endAgent会自动补全given/when/then的实现,并生成100%覆盖的测试用例。这解放了工程师,让他们专注定义“什么算正确”,而非“怎么验证正确”。
5.4 部署与监控:Agent让运维变成声明式体验
capistrano没消失,但cap production deploy命令背后,Agent在做更多事:
- 自动检查
config/deploy/production.rb是否匹配当前Agent版本 - 在部署前,用
hermes agent health:check运行全链路探针(DB连通性、Redis健康、Sidekiq队列水位) - 部署后,自动抓取
rails stats、brakeman -q、rails_best_practices报告,生成PDF交付给运维团队
热词中gitlab cli安装、openspec cli、cleanup winsxs cli,本质都是Agent在统一CLI入口下,把分散的运维工具链聚合成一个可编程接口。我们甚至用agent monitor --metric "response_time_p95 > 300",让Agent自动触发告警并生成根因分析报告——这已经不是监控,而是自治。
这条全链路的重构,最终指向一个事实:软件工程的核心,正从“写代码”转向“定义意图、校验约束、管理知识”。Agent不是来取代你的,它是来把你从重复劳动中解放出来,让你真正去做只有人类才能做的事:理解业务本质、权衡技术取舍、设计系统韧性。DHH的震撼发声,不是终点,而是起点——一个让Rails工程师重拾技术尊严的起点。