MoreRSS

site iconJustYY | 小赖子修改

小赖子的英国生活和资讯,以及投资和个人生活。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

JustYY | 小赖子的 RSS 预览

代码交给 AI 以后, 程序员还需要什么能力?

2026-09-09 23:25:57

从聊天到动手:AI 把不可思议变成了日常 From Chat to Action: AI Is Making the Extraordinary Ordinary 三年前惊叹它会聊天,如今 AI 已经能看、能听、能行动 Three Years Ago, AI Could Chat. Now It Can See, Hear, and Act 当 AI 有了“眼睛、耳朵和手脚”,程序员的工作变了 AI Has Eyes, Ears, and Hands—And Programming Is Changing 昨天的 AI 奇迹,今天的理所当然 Yesterday’s AI Miracles Are Today’s Expectations 从复制粘贴到交代任务:程序员与 AI 的三年 From Copy and Paste to Delegating Tasks: Three Years with AI 代码交给 AI 以后,程序员还需要什么能力? When AI Writes the Code, What Skills Do Developers Still Need? 以后的编程语言是英语?事情没那么简单 Is English the Next Programming Language? It’s Not That Simple 从 ChatGPT 到 AI 智能体:变化比想象中更快 From ChatGPT to AI Agents: Faster Than We Imagined 翻看三年多前的视频,才发现当时让我们惊叹的 ChatGPT 对话能力,如今早已成为日常。从文字聊天到能看、能听、能调用工具执行任务,AI 正在改变软件开发的方式。随着 Vibe Coding 和 Harness Engineering 的发展,程序员可以将更多编码工作交给 AI,而清晰表达需求、阅读代码、理解业务和验证结果的能力,也变得更加重要。

从聊天到动手:AI 正在把昨天的不可思议变成今天的日常

最近翻到一段三年多前的视频,里面的我们还在惊叹 ChatGPT 居然能这样聊天。再看三年前的视频,连 AI 回复时一个字一个字往外蹦的速度,都明显没有现在快。当时我们还会盯着屏幕,耐心等它把话说完,觉得这种边生成、边显示的过程很神奇。如今,回复更快了,能完成的任务也复杂得多,我们却开始嫌它思考太久、执行太慢。人的适应能力就是这么强:技术不断进步,我们的期待也跟着水涨船高,曾经让人惊叹的体验,很快就变成了习以为常的标准。 [video_links] https://www.youtube.com/watch?v=garlKUEw1oA https://www.bilibili.com/video/BV1U7Ya6dE6d/ https://x.com/doctorzlai/status/2097787493303132295 https://www.facebook.com/reel/2286365265485326 https://www.threads.com/@doctorlai/post/DdFJHvqlwO0 https://mp.weixin.qq.com/s/AEROXgN2ywe5GM3CabgkNQ https://weibo.com/1858482220/RhoyKktvL https://www.xiaohongshu.com/explore/6aa1c4f90000000011034765?xsec_token=YBzuIAKY7pihIWdkWQN75biZ6gVBs0e1sOBYjVZpLsn0M=&xsec_source=pc_creatormng https://www.instagram.com/p/DdFJnjdAamr/ https://weixin.qq.com/sph/AvVCzre9g [/video_links] 你问一个问题,它能像模像样地回答;你让它解释代码,它能逐行分析;你让它写个函数,它也能给出一段实现。那时我已经觉得,这东西会改变世界。 现在回头看,那个阶段的体验竟然显得有些朴素了。当时的惊叹完全可以理解,只是后来的变化,比想象中还快。

从 Stack Overflow 到直接问 AI

以前程序员遇到问题,通常先搜索,再去 Stack Overflow 找答案,翻文档、看讨论,从几个页面里拼出一个适合自己的解决方案。Copy & Paste 当然只是玩笑式的概括,真正费时间的,往往是判断哪个答案适用,以及怎样把它改成自己需要的样子。 ChatGPT 把其中不少步骤压缩成了一轮对话。它可以根据问题整理资料、解释概念、给出示例,我们还可以继续追问。这种不用在一堆网页之间来回切换的体验,当时已经足够让人兴奋。 只是那时,大多数时候它负责“说”,我们负责“做”。它给出命令,我们复制到终端;它生成代码,我们粘贴到编辑器;运行报错以后,再把错误信息贴回去。

AI 开始拥有“眼睛”“耳朵”和“手脚”

没过多久,AI 的能力就从文字对话扩展到了看、听和行动。它开始能“看”图片、截图和视频,理解其中的内容;能“听”语音,识别我们说的话,并通过语音交流;还可以借助工具调用,读取文件、修改代码、执行命令,再根据运行结果继续调整。 当然,这些“眼睛”“耳朵”和“手脚”是比喻。背后是多模态理解、语音交互,以及连接外部系统的工具与执行环境。不同模型和产品具备的能力也不完全一样。 MCP(Model Context Protocol,模型上下文协议)为连接数据源和工具提供了统一方式,让 AI 更容易与外部系统配合工作。它像是连接“手脚”的标准接口之一,而不是让 AI 获得所有这些能力的来源。 这样的变化很直接:以前我需要把看到的问题打成文字,把 AI 给出的代码和命令搬到电脑里执行;现在可以直接给它一张截图、一段语音,或一个明确的任务,让它在授权范围内完成分析、修改、运行和检查。 聊天框还是那个聊天框,背后却已经多了感知信息和采取行动的能力。 参考:Anthropic:Introducing the Model Context Protocol

从解释编程题,到参与前沿数学研究

与此同时,模型本身的能力也在继续增长,甚至开始触及前沿数学研究。 2026 年 9 月 8 日,OpenAI 宣布其内部 AI 系统给出了 Navier–Stokes 存在性与光滑性问题的一项证明。这个问题涉及三维流体运动是否可能在有限时间内出现奇异性,相关研究可以追溯到 1934 年,后来被列为千禧年数学难题之一。 按照公告,约一万个智能体参与了找到结果的协作组,在约 88 小时后得到解答;GPT-6 Astra 又参与了约 17 小时的 Lean 形式化与验证。 参考:OpenAI:On the Navier–Stokes Millennium Prize Problem

令人震撼,也需要把事实说准确

这里需要说准确:提出证明的是比 Astra 更强的内部系统,不能简化成“在 ChatGPT 里问了一句,Astra 就解出了百年难题”。 而且,截至本文写作时,克雷数学研究所的页面仍将该问题列在未解决问题中。公司发布证明、形式化验证与数学界充分审查和认可,是需要区分的事情。 参考:克雷数学研究所:千禧年数学难题 即便保留这些必要的区别,这件事仍然令人震撼。三年多前,我们还在为 AI 能解释一道编程题而惊叹,如今已经需要认真讨论它在重大数学研究中扮演什么角色。

从 Vibe Coding 到 Harness Engineering

回到程序员的日常,变化同样明显。

用自然语言把想法做出来

Vibe coding 所代表的体验,是用自然语言描述想法,让 AI 先做出来,再通过不断反馈调整结果。做原型、写小工具时,这种方式尤其直观:很多过去要逐行实现的东西,现在可以先说清楚,再让 AI 生成。 不过,能快速做出一个演示,和能长期维护一个可靠的软件,仍然有距离。

让 AI 持续、可靠地完成任务

这也是 harness engineering 值得关注的原因。它是一种工程思路:为 AI 准备合适的工作环境、上下文、工具、约束和反馈机制,让它能够持续、可靠地完成任务。 OpenAI 在一篇工程文章中介绍,他们曾实验性地用 Codex 构建一个产品,代码全部由智能体生成,而工程师负责定义目标、设计环境和建立反馈循环。 参考:OpenAI:Harness engineering 这让我越来越觉得,在不少开发任务里,程序员确实已经可以把大量手动编码交给 AI。不过,要说“现在程序员基本不需要写代码了”,还是太笼统。不同项目的复杂度、历史包袱和可靠性要求,差别很大。 我们花在敲代码上的时间可能减少了,花在定义问题、审查结果和判断取舍上的精力,却未必会减少。

以后的编程语言是英语?

我有时会开玩笑说,以后的编程语言是英语。 更准确一点,是自然语言。英语可以,中文也可以。过去,我们需要把需求翻译成编程语言;现在,越来越多的翻译和实现工作可以交给 AI。 但“只需要提需求”这句话,很容易让人低估提需求本身的难度。

把需求说清楚,本身就是能力

“帮我优化这个服务”,听起来很清楚,其实什么都没说清楚。
  • 是降低平均延迟,还是改善 P99?
  • 是提高吞吐量,还是减少成本?
  • 允许改变接口吗?
  • 可以牺牲多少准确性?
  • 怎样判断这次改动真的有效?
这些问题没有答案,AI 再会写代码,也可能非常高效地朝错误的方向前进。

代码可以交给 AI,判断力仍然需要自己练

阅读代码的能力

你可以不亲手写每一行,但需要能在关键位置检查逻辑、追踪数据流、识别不合理的假设。 测试也很重要,但测试通过只能说明它通过了这些测试,不能自动证明需求理解正确。

领域知识

Domain expertise,也就是领域知识,同样重要。了解业务规则、数据含义和实际使用场景,才能判断一个看起来漂亮的实现是否真的解决了问题。 有些错误不会报异常,甚至性能很好,只是结果根本不是用户需要的。

软件工程能力

软件工程能力也不会因为代码生成变容易而失去价值。架构、接口、可维护性、可观测性、发布和回滚,都需要有人认真考虑。代码产出越快,这些约束越需要跟得上。 因此,把 AI 用好,正在成为一种新的能力。这不只是记住几个好用的提示词,还包括拆解任务、提供上下文、定义验收标准,以及在 AI 给出答案时,知道应该相信什么、检查什么、继续追问什么。

昨天的不可思议,正在成为今天的默认要求

AI 最让我感慨的,是它不断改变我们对“正常”的认识。 第一次看到它写出能运行的代码,会觉得不可思议。用上一段时间以后,就开始嫌它为什么没有顺便写好测试。等它能自己修改、测试、修复,又会期待它直接交付完整功能。 曾经的惊喜,很快就变成了默认要求。昨天还觉得不可能的事情,一旦实现,我们适应得比自己想象中更快。 三年多前,我看着 ChatGPT 的回答,觉得它会改变世界。现在再看那段视频,我依然认同当时的判断,只是对“改变”有了更具体的体会。 它已经进入我们的工作流程,改变了从一个想法到一个可运行成果之间的距离。 而我也需要不断调整自己:少把能力等同于亲手写了多少代码,多问问自己,能不能发现真正值得解决的问题,把它讲清楚,并判断最后交付的东西是否经得起检验。 [show_file file="/var/www/wp-post-common/justyy.com/software-engineer.php"] [show_posts keyword="人工智能"] 英文:When AI Writes the Code, What Skills Do Developers Still Need?

京东Joybuy在英国越来越火: 从中国零食到宇树机器人都能买

2026-09-08 21:42:19

京东邀请码:SBJG45 首单10英镑省3英镑。

Joybuy登陆英国后:便宜、方便、优惠多,我媳妇已经快买上瘾了 京东Joybuy在英国越来越火:从中国零食到宇树机器人都能买 Joybuy英国使用体验:价格便宜、配送快,就是纸箱太多 从Amazon到Joybuy:英国网购正在多一个强劲选择 Joybuy登陆英国后,我家的快递明显变多了 Joybuy英国体验:优惠券、签到积分、低价会员,确实很会“拿捏”用户 京东Joybuy进入英国及部分欧洲市场后迅速受到不少消费者欢迎。中国零食、饮料、日用品甚至电器都能方便购买,再加上签到积分、优惠券、本地仓配送和低价会员服务,整体体验颇具竞争力。相比Amazon和TEMU,Joybuy既有价格优势,又更贴近日常消费需求。不过频繁购物也带来了一个很现实的问题:家里的纸箱越来越多了。

再说京东JoyBuy: 可以打卡积点还可以买宇树机器人

今年京东 Joybuy 登陆英国以及法国等部分欧洲国家后,确实很快就火了起来。 虽然也有人批评,说 Joybuy 这样的电商平台会冲击本地实体零售行业,但我对此倒不是特别在意。对普通消费者来说,购物更方便、价格更便宜,本身就是好事,而且有竞争总比没有竞争强。至少可以让一些当地中超也感受到点压力,省得东西卖得又贵,质量还参差不齐。 很久以前我甚至听说过,有无良中超遇到蛋糕表面长毛了,直接把上面那一层刮掉继续卖。真假暂且不论,但这些年来我对英国一些中超的购物体验确实一般,尤其是退货,经常比较麻烦。 相比之下,Joybuy 的体验就简单多了。 我媳妇最近用得特别频繁,基本上属于“三天一大买,两天一小买”。尤其是中国零食,在上面买特别方便。像东方树叶这种零卡饮料,她基本都是一箱一箱地往家里搬。 上次她更夸张,一口气买了五箱、每箱 24 瓶的矿泉水——因为每单最多只能买五箱。 [caption id="attachment_72890" align="alignnone" width="1152"]Joybuy上的矿泉水和泡面,屯粮/隔几天就去露营了。 Joybuy上的矿泉水和泡面,屯粮/隔几天就去露营了。[/caption] 京东邀请码:SBJG45 首单10英镑省3英镑。 送货小哥估计当场就后悔接这一单了。 他得从货车里一箱一箱搬到我家门口,搬到最后还开玩笑地说: “这是世界上最后的水了吧?” 最近英国政府也一直建议民众准备一些应急饮用水和食物,以防极端天气或者其他突发情况。我估计我媳妇看到这种新闻以后,很快又要有所行动了。

京东打卡积点抵现

Joybuy 的 App 里面还有一个我觉得设计得挺聪明的功能:每日签到赚积分。 而且还可以设置手机提醒。 最关键的是,这些积分不是那种看起来很多、实际上不知道能干什么的虚拟数字,而是真的可以直接抵现金。 这一下签到就有动力了。 从产品设计的角度来看,我觉得这一招其实很妙:每天签到,可以增加用户打开 App 的频率和用户黏性;而一旦账户里攒了一些积分,很多人又会产生一种“这些积分不用掉好像亏了”的心理。 比如我媳妇就是这样。 [caption id="attachment_72891" align="alignnone" width="945"]Joybuy每日提醒打卡积点/抵现 Joybuy每日提醒打卡积点/抵现[/caption] [caption id="attachment_72892" align="alignnone" width="945"]Joybuy积点历史 Joybuy积点历史[/caption] 而且我发现 Joybuy 和 TEMU 有点类似,经常会给你发各种 Voucher,比如满 £40 减 £5、满 £60 减 £20之类的。有时候刚下完一单,又给你送新的券,感觉永远都用不完。 于是你本来觉得: “这次买完了,最近应该不用买了。” 结果第二天打开 App: “咦?又有一张券。” 然后又开始凑单。 不过 Joybuy 和 TEMU 对我来说有一个很大的区别。 Joybuy 上买的东西,大多数至少都是正常生活中会消耗掉的东西,比如吃的、喝的、日用品,所以即使买得频繁,也不太容易买一堆完全没用的东西。 TEMU 就不一样了。 前两年我在 TEMU 上买过不少“有的没的”。下单的时候觉得特别便宜,几镑钱一个,看着很划算,但买回来以后才发现,要么根本用不上,要么质量比较一般。 单看每一件都没多少钱,但加起来其实就是乱花钱。 Joybuy 现在卖的东西也越来越杂,不只是食品和日用品,连电器都有。 比如今年夏天天气特别热的时候,Joybuy 上连空调都卖,而且有一段时间直接卖断货了。 我今天刷 App 的时候,甚至发现上面已经可以买宇树机器人了,而且居然还能隔天送到。 [caption id="attachment_72893" align="alignnone" width="945"]Joybuy上可以买宇树机器人,价格不便宜啊 Joybuy上可以买宇树机器人,价格不便宜啊[/caption] 这基本也能说明 Joybuy 在英国已经铺了不少本地仓储,否则这种配送速度很难做到。

Joybuy Plus会员服务

Joybuy 现在还推出了类似 Amazon Prime 的会员订阅服务。 月费 £3.99,年费只要 £19.99。算下来一个月还不到 £2。 会员最直接的好处就是免运费,另外还有一些 Member Only Deals。 本来 Joybuy 凑到一定金额也可以免运费,但有会员以后,就不用为了免运费硬凑单了。 比如突然想吃一包零食,直接买一包也可以送上门。 从这个角度看,£19.99 一年的价格确实挺划算。 再对比一下 Amazon Prime:目前英国年费大约 £95,月费 £8.99。 当然 Prime 除了配送,还有 Prime Video 等其他服务,但如果单纯从“买东西”这个角度来说,我现在觉得 Amazon 最大的优势还是 Next Day Delivery,以及商品种类特别全。 问题是,Amazon 上很多中国商品价格其实并没有什么优势。 比如一件普通 T-shirt,在 Amazon 上可能就要 £20 左右,而类似的东西在 TEMU 或 Joybuy 上,几镑钱就可能买到。 当然,质量未必完全一样,但价格差距确实很明显。 目前我对 Joybuy 最大的吐槽,反而不是商品或者配送,而是: 纸箱实在太多了。 每次送货过来,不管买的是什么,都感觉特别喜欢“大箱子套小箱子”。 拆快递的时候挺爽,拆完以后看着家里那一大堆纸箱,就开始头疼。 每次处理纸箱都得拆开、压平,再塞进回收箱。 有时候我都忍不住想: Joybuy 这么豪横的吗? 纸箱不要钱? 要是在国内,这么多纸箱估计早就有人收走卖钱了。 不过从消费者角度来说,目前 Joybuy 在英国的体验整体还是挺不错的:价格有竞争力,中国商品丰富,配送快,退货相对方便,再加上签到积分、优惠券和低价会员这些运营手段,确实很容易让人形成使用习惯。 至少从我媳妇的使用频率来看,Joybuy 的这套打法显然已经成功了。 至于我们家接下来最大的问题,大概不是“还要不要买”,而是: [bctt tweet="这些纸箱到底往哪儿放。"] [show_posts keyword="joybuy"] 京东邀请码:SBJG45 首单10英镑省3英镑。

一封 Google 邮件把我惊醒: 一次 WordPress 漏洞入侵事件复盘

2026-09-07 18:46:28

一次未及时升级的 WordPress 及插件漏洞,导致数据库中的 Cloudflare 凭据疑似泄露。攻击者随后添加恶意 Worker,劫持部分博客页面,将流量导向赌博网站,并把自己添加为 Google Search Console 的已验证所有者。本文完整复盘事件经过、攻击链、调查结论和加固措施,也再次提醒我:安全依赖及时更新、最小权限、日志监控和可恢复的备份,而不是某一项单独的防护。

一封 Google 邮件把我惊醒:一次 WordPress 安全事件复盘

2026 年 8 月 11 日,我收到了一封来自 Google Search Console 的邮件,通知我网站新增了一名“已验证所有者”。 [caption id="attachment_72817" align="alignnone" width="1312"]在床上刷手机的时候收到GOOGLE的邮件,说网站有新的Owner验证,明显不对。 在床上刷手机的时候收到GOOGLE的邮件,说网站有新的Owner验证,明显不对。[/caption] [bctt tweet="我完全不认识这个账号。"] 看到邮件的一瞬间,我就意识到事情不对。如果陌生人能够把自己添加为网站所有者,这很可能不只是垃圾评论、撞库登录或者普通的漏洞扫描,而是对方已经能够控制网站向访问者返回的内容。 我立刻开始检查 WordPress、Cloudflare、MySQL 数据库、Web 服务器和系统日志。 调查结果显示,网站确实遭到了入侵。攻击者在部分博客请求到达源服务器之前进行了拦截,并将正常页面替换成了印尼语的赌博网站推广内容。 [caption id="attachment_72814" align="alignnone" width="1456"]Cloudflare的Audit记录 Cloudflare的Audit记录[/caption] 这次事件最终被及时发现和处理,但也给我敲响了一记警钟。 WordPress 向来是漏洞攻击的重灾区。更准确地说,风险并不只来自 WordPress 核心,而是来自由 WordPress、插件、主题、数据库、API Token、CDN、文件权限和日常运维共同构成的整条信任链。

事情是如何发生的?

我这些年陆续积累了大约八个 WordPress 网站。每个网站又安装了若干主题和插件,其中一个插件需要调用 Cloudflare API,因此将一个 Cloudflare 访问凭据保存在了 WordPress 数据库中。 WordPress 的配置表会保存大量网站和插件设置。部分插件还会把 API Token、Secret 等敏感信息以应用程序可以直接使用的形式存放在数据库里。 受影响的网站当时仍然运行着一个没有及时升级的 WordPress 6.8.x 版本,同时安装了存在安全问题的插件。相关漏洞在上个月刚刚被公开,而我没有在修复版本发布后及时完成升级。 [caption id="attachment_72813" align="alignnone" width="705"]打开cloudflare检查API调用的记录 打开cloudflare检查API调用的记录[/caption] 结合服务器日志、数据库内容和 Cloudflare 配置,我认为最可能的攻击路径是:
  1. 攻击者利用已经公开的 WordPress 或插件漏洞,访问了本不应该被读取的数据。
  2. 插件保存在 WordPress 数据库中的 Cloudflare 凭据因此暴露。
  3. 攻击者利用该凭据修改 Cloudflare 配置,并部署了未经授权的 Worker。
  4. 恶意 Worker 在请求到达我的服务器之前拦截部分博客页面。
  5. 部分正常页面被替换成印尼语的赌博推广内容。
  6. 攻击者利用其控制网站响应的能力,完成 Google Search Console 的所有权验证。
  7. Google 发出的“新增所有者”邮件最终惊动了我。
这是现有证据支持的最合理解释,但不是对攻击者每一步操作的完整还原。 安全事件分析必须区分“已经确认”“高度可能”和“尚不能排除”。不能因为一条攻击路径符合逻辑,就把所有推测都写成已经证实的事实。

事件时间线

  • 2026 年 7 月:与旧版本 WordPress 或相关插件有关的安全问题被公开,修复版本随后发布。我的网站没有及时升级,因此形成了风险窗口。
  • 2026 年 7 月中下旬:服务器日志开始出现大量针对 WordPress 和常见插件接口的自动化探测。公开服务器每天都会收到此类扫描,因此“有人扫描”本身不能证明入侵成功。
  • 2026 年 7 月下旬至 8 月上旬:日志中出现针对已知漏洞路径、上传目录和可疑脚本名称的探测。多数请求返回文件不存在,但说明网站一直处于自动化攻击系统的扫描范围内。
  • 2026 年 8 月上旬:攻击者疑似通过未修复漏洞接触到了插件保存的敏感配置。现有证据更支持数据库中插件凭据泄露,而不是攻击者先登录 WordPress 后台。
  • 随后:泄露的 Cloudflare 凭据被用于添加或修改边缘执行逻辑,部分博客页面开始在抵达源服务器之前被替换。
  • 同一阶段:遭到劫持的页面开始显示印尼语赌博推广内容,目的看起来主要是 SEO 污染和流量劫持。
  • 2026 年 8 月 11 日:攻击者利用其控制网站响应的能力完成 Google Search Console 验证,并添加了一个陌生的已验证所有者。
  • 2026 年 8 月 11 日:我收到 Google 的所有权变更邮件,立即开始应急处理。
  • 2026 年 8 月 11 日至 12 日:我删除未经授权的 Google 所有者,检查并清理 Cloudflare Worker 和相关配置,同时撤销并轮换可能泄露的凭据。
  • 2026 年 8 月 12 日:我升级受影响的 WordPress,检查管理员用户、数据库权限、Web 日志、文件修改时间、计划任务及常见 WebShell 痕迹。
  • 2026 年 8 月 12 日:我清理数据库中遗留的敏感插件配置,并开始收紧 MySQL 的文件访问能力。
  • 2026 年 8 月 12 日:我为 WordPress 上传目录增加禁止执行 PHP 的保护,同时检查 Apache 配置和服务状态。
  • 后续:继续复查文件权限、备份可恢复性、Cloudflare Token 权限,以及其他 WordPress 网站的核心、主题和插件版本。

攻击者做了什么

目前已经确认或得到较强证据支持的行为包括:
  • 获得了一个可以调用 Cloudflare API 的敏感凭据。
  • 在 Cloudflare 侧添加或修改了边缘执行逻辑。
  • 在请求到达源服务器之前劫持了部分 WordPress 页面。
  • 向访问者或搜索引擎返回了赌博推广内容。
  • 将一个未经授权的身份添加为 Google Search Console 所有者。
  • 试图利用网站原有的域名信誉和搜索排名进行 SEO 污染及流量导向。
Google Search Console 的所有者权限不应该被低估。 它不等于服务器 root 权限,也不能直接读取服务器文件,但未经授权的所有者可能提交站点地图、申请页面索引、查看搜索数据,并帮助恶意页面更快进入 Google 搜索结果。 幸运的是,Google 发出的所有权变更邮件成为了发现这次事件的关键信号。 如果没有这封邮件,只针对特定 URL、地区、User-Agent 或搜索引擎爬虫返回恶意内容的攻击,站长自己平时访问首页时未必能够马上发现。

攻击者有没有登录 WordPress 后台

目前没有证据表明攻击者成功登录过 WordPress Dashboard。 WordPress 数据库中仍然只有我自己的管理员账号,没有发现新增的管理员。现有日志同样不足以证明攻击者成功登录过后台。 但没有发现登录证据,并不等于绝对没有发生过登录。 日志可能已经轮换,代理层可能隐藏部分请求,某些应用行为也未必会留下完整的审计记录。 因此,更准确的结论是: 目前没有证据证明攻击者登录过 WordPress 后台,但相关凭据仍然应该按照可能已经暴露的标准处理。 我更换了 WordPress 管理员密码,并轮换 WordPress 的认证密钥和 Salt,使原有登录 Cookie 和会话全部失效。 需要注意的是,wp-config.php 中的认证 Key 和 Salt 主要用于保护 Cookie、会话和 Nonce。更换它们会让所有用户退出登录,但不会改变用户的密码。 WordPress 数据库中的密码使用带 Salt 的密码哈希保存。即使密码哈希泄露,攻击者通常也无法直接看到明文密码,但仍然可以离线猜测。 Salt 可以防止预计算彩虹表攻击,也能让相同密码产生不同哈希,但它不能保护弱密码不被字典攻击或暴力破解。 因此,只要数据库可能泄露,正确做法仍然是更换密码,尤其是当密码较短、可预测或者在其他服务中重复使用时。

攻击者有没有获得服务器文件权限

这是我最担心的问题。 Cloudflare Worker 运行在 Cloudflare 的边缘网络。它能够拦截、重写或代理网站请求,但不会因为拥有 Worker 权限就自动获得源服务器的文件系统权限。 数据库漏洞同样不必然等于操作系统命令执行。MySQL 能读取或写入哪些文件,还取决于数据库账号权限、MySQL 配置和操作系统权限。 检查结果显示,WordPress 使用的数据库账号没有全局文件权限。只有本地维护账号和数据库管理员账号具备相关权限。 MySQL 的本地文件导入功能已经关闭,服务器端文件访问能力也被进一步禁用或限制。 日志中确实出现了大量针对 WebShell 和上传脚本的探测,但相关请求多数返回文件不存在。 我没有找到攻击者成功上传并执行 WebShell 的直接证据,也没有发现其取得服务器 Shell 或 root 权限的明确证据。 但是,这并不能证明服务器文件系统绝对没有被接触。 我后来发现,部分网站目录长期由 Web 服务账号拥有,而且可写范围过大。如果攻击者真的取得 PHP 代码执行能力,理论上就有可能修改 Web 服务账号可写的文件。 因此,目前最严谨的结论是: 已确认的是 Cloudflare 凭据泄露和边缘页面劫持。尚未发现 PHP 代码执行、成功部署 WebShell 或服务器文件被篡改的直接证据,但由于历史文件权限偏宽,不能仅凭现有日志完全排除文件系统风险。

WebShell 探测是否与这次漏洞有关

日志中出现了一些访问 WordPress 上传目录下可疑 PHP 文件名的请求。这些请求看起来更像通用的 WebShell 探测。 相关请求返回了 HTTP 404,说明被请求的文件在当时并不存在。 请求一个类似 WebShell 的文件名,并不能证明扫描者曾经成功上传过这个文件。互联网上的自动化攻击程序经常尝试访问已知 WebShell 文件名,希望找到其他攻击者之前留下的后门。 这次 WordPress 漏洞可能允许攻击者接触数据库信息,但这并不会自动获得 PHP 执行或文件写入能力。 真正部署 WebShell 通常还需要额外的能力,例如:
  • 任意文件上传。
  • 任意文件写入。
  • 远程代码执行。
  • 已经被攻破的 WordPress 后台账号。
  • 安装恶意插件的权限。
  • 其他存在代码执行能力的漏洞。
因此,目前没有证据能够把日志中的 WebShell 探测与本次 Cloudflare 凭据泄露事件直接关联起来。 在上传目录禁止执行 PHP 是预防性加固措施,而不是本次攻击已经使用 WebShell 的证明。 见:WordPress安全加固: 禁止在 wp-content/uploads 目录中执行PHP

MySQL 用户名和密码有没有泄露

如果漏洞只允许读取 WordPress 的配置表,那么它可能暴露插件保存在数据库中的 Token 和 Secret,但不一定能够读取 WordPress 的 MySQL 密码。 WordPress 的数据库用户名和密码通常保存在 wp-config.php 中,而不是保存在 WordPress 配置表里。 只有当攻击者获得任意文件读取、PHP 代码执行或其他能够读取 wp-config.php 的能力时,WordPress 使用的 MySQL 用户名和密码才更可能泄露。 MySQL 自己通常也不会把数据库用户密码以可直接恢复的明文形式保存在系统表中,而是保存认证信息。不过,如果这些认证数据泄露,弱密码仍可能遭到离线攻击。 结合目前的调查结果,我没有发现 WordPress 数据库凭据或所有 MySQL 用户密码已经泄露的直接证据。 但作为事件响应的一部分,轮换 WordPress 专用数据库账号的密码仍然是一项低成本的预防措施。修改 MySQL 密码后,还必须同步更新 wp-config.php 中的数据库密码,否则 WordPress 将无法连接数据库。

为什么 Cloudflare 没有挡住攻击?

Cloudflare 不是一个能够自动解决所有安全问题的盒子。 它可以提供 DDoS 防护、WAF、Bot 管理、速率限制和源站隐藏,但这些保护取决于正确配置,同时也要求攻击行为符合它能够识别的流量模式。 更关键的是,这次攻击者疑似获得了一个有效的 Cloudflare API Token。 从 Cloudflare 的角度看,使用有效凭据发起的管理操作可能就是一次经过授权的操作。WAF 主要检查网站访问流量,并不会自动把所有使用合法 Token 发出的 API 请求判定为攻击。 换句话说,Cloudflare 在这次事件中不仅是防线的一部分,也因为泄露凭据的权限过大而成为了攻击链的放大器。 这让我重新认识到一个重要原则: API Token 必须遵循最小权限原则。普通 WordPress 插件不应该持有足以控制整个网站请求链路的凭据,除非这项权限确实不可避免。

WordPress 为什么会在数据库中保存密钥?

许多 WordPress 插件会把外部 API 凭据存放在配置表里,并以应用程序可以直接使用的形式保存。 这并不一定意味着插件开发者完全不懂安全。应用程序需要在无人操作的情况下调用外部 API,因此必须能够在运行时获得对应的凭据。 即使数据库中的值经过加密,只要解密密钥和应用程序位于同一台服务器或同一个执行环境中,当攻击者已经取得足够高的应用权限时,通常仍有可能完成解密。 所以,加密有价值,但不能代替访问控制。 更有效的措施包括:
  • 尽量不要让 WordPress 插件持有高权限的基础设施凭据。
  • 为每个网站和每种用途创建独立的 Token。
  • 把 Token 权限限制到必要的资源和操作。
  • 为凭据设置有效期并定期轮换。
  • 不再使用的插件应该彻底删除,而不只是停用。
  • 数据库备份也应该按照敏感数据处理。
  • 监控 Token 调用、Worker 变更和网站所有权变化。
  • 插件删除或停用后,立即撤销它曾经使用的凭据。
Key Vault 一类的秘密管理系统能够改善凭据的存储、轮换、权限控制和审计,但它不能让一个已经完全失陷的应用自动恢复安全。 真正关键的是限制凭据能够做什么,以及限制它能够使用多长时间。

我采取了哪些处理措施?

发现问题后,我首先处理正在发生的风险,而不是急着构造一个听起来完整的攻击故事。 已经完成或正在进行的工作包括:
  1. 删除 Google Search Console 中未经授权的所有者。
  2. 删除 Cloudflare 中未经授权的 Worker 和相关配置。
  3. 撤销并重新生成可能已经泄露的 API Token。
  4. 升级受影响的 WordPress 网站。
  5. 更新插件和主题,并删除不再使用的组件。
  6. 检查 WordPress 管理员账号、应用密码和异常会话。
  7. 清理数据库中遗留的敏感插件配置。
  8. 限制 WordPress 数据库账号的权限。
  9. 关闭不需要的 MySQL 本地文件导入功能。
  10. 禁用或严格限制 MySQL 的服务器端文件访问能力。
  11. 检查 Web 日志、系统日志、计划任务和异常文件。
  12. 禁止在 WordPress 上传目录中执行 PHP。
  13. 重新检查网站文件和目录的 owner、group 及读写权限。
  14. 检查现有备份是否完整并且能够恢复,而不只是确认备份文件存在。
  15. 轮换管理员密码、数据库密码及 WordPress 认证 Key 和 Salt。

为什么要禁止上传目录执行 PHP?

WordPress 上传目录主要用于保存图片、视频和 PDF 等静态文件。正常情况下,这个目录没有执行 PHP 的必要。 如果某个漏洞允许攻击者绕过文件类型检查,上传一个伪装后的 PHP 脚本,而 Web 服务器又允许在上传目录中执行 PHP,那么这个文件就可能成为 WebShell。 攻击者随后可能通过浏览器执行命令、读取配置文件、修改网站代码,甚至继续向服务器的其他部分扩展。 禁止上传目录执行 PHP,可以切断这条常见的攻击升级路径。 即使恶意 PHP 文件被上传成功,Web 服务器也不会把它当作程序执行。 这项保护通常只有很低的兼容性风险,却能明显降低多种文件上传漏洞造成的影响,因此值得默认启用。 不过,它不是万能的。如果主题目录、插件目录或其他允许执行 PHP 的目录仍然可以被 Web 服务账号写入,攻击者仍可能寻找其他落点。

重新整理文件权限

这次检查让我发现,为了方便安装插件、自动升级和解决写入错误,我曾经给部分 WordPress 目录留下了过于宽松的权限。 这样做很方便,但方便通常意味着更大的攻击面。 还有,就是在MySQL数据库设置里禁止本地文件的访问:使用 local_infile=0 和 secure_file_priv=NULL 加固 MySQL 文件访问安全 接下来我会按照最小权限原则重新整理:
  • 程序代码默认由部署账号或管理账号拥有。
  • Web 服务账号可以读取代码,但不应该默认拥有整个网站。
  • 只有确实需要写入的上传、缓存和临时目录才授予写权限。
  • 配置文件使用更严格的权限。
  • 不再为了方便而让整个网站都可以被 Web 服务账号写入。
  • 临时排错时增加的权限必须及时恢复。
  • 在可行的情况下,可写目录不应该同时允许执行服务器端脚本。
权限设计的目标不是找到一个适用于所有文件的统一数字,而是明确回答一个问题:

如果 PHP 进程被攻击者控制,它到底能够修改哪些文件?

理想答案应该是“只能写入少数业务必需目录”,而不是“可以修改整个网站”。

以后如何更新 WordPress

这次事件之后,我不会再把 WordPress 更新当作“有空再做”的维护工作。 我的计划包括:
  • WordPress 核心安全更新发布后,尽快检查并手动升级。
  • 同时更新插件和主题。
  • 定期删除已经停用、无人维护或没有必要的插件。
  • 不盲目为所有网站开启重大版本的全自动升级。
  • 更新前检查备份,更新后验证网站关键功能。
  • 为所有 WordPress 网站维护统一的版本清单。
  • 定期检查公开漏洞,而不是只依赖后台升级提示。
由于服务器上存在多个历史网站和不同的插件组合,我仍然倾向于手动执行重要升级。完全无人值守的重大版本升级可能带来兼容性问题。 但是,“手动升级”不能成为“长期不升级”的借口。 备份不能只看有没有 以前看到定时任务正常运行,备份目录中也存在文件,就容易产生一种已经安全备份的错觉。 真正可靠的备份至少应该满足:
  • 备份文件完整且没有损坏。
  • 数据库和上传文件都包含在备份中。
  • 至少有一个副本位于生产服务器之外。
  • 攻击者不能使用同一组凭据同时删除生产数据和全部备份。
  • 有明确的备份保留周期。
  • 定期执行实际恢复测试。
  • 清楚恢复过程需要多长时间。
从未验证过恢复流程的备份,只能算是一份可能有用的数据副本。

是否迁移到静态博客?

和朋友讨论这次事件时,有人建议我迁移到 Hexo 一类的静态博客。文章可以直接写成 Markdown,保存在 GitHub 中,再通过自动化流程生成静态页面。 这个建议确实有道理。 我的博客主要用于个人记录,并不依赖复杂的会员系统、动态插件或后台业务逻辑。对于这种使用场景,静态网站能够大幅减少 PHP、数据库、插件和后台登录带来的攻击面。 不过,我现在大约有八个 WordPress 网站,这是多年折腾积累下来的历史包袱。 一次性迁移全部文章、URL、图片、评论和 SEO 数据,并不是一个小项目。 更现实的方案可能是:
  • 新内容逐渐使用 Markdown 编写。
  • 优先迁移结构最简单的博客。
  • 对仍然需要保留的 WordPress 网站做减法。
  • 删除不必要的插件和主题。
  • 尽量保留旧 URL,避免大量外部链接失效。
  • 只在真正需要的地方保留动态功能。
现在有了 AI Agent,批量转换文章、整理元数据、修复图片路径、生成静态网站配置以及调试部署流程,都比过去容易得多。 这也让迁移多年历史内容真正变得可行。

这次事件给我的教训

这次攻击并没有从最显眼的 WordPress 管理员密码开始,而是沿着一条容易被忽略的信任链发生: 未及时更新的应用或插件 → 数据库中的敏感配置 → 权限过大的外部 Token → 边缘侧请求劫持 → 搜索引擎所有权被冒领 每一个环节单独看似乎都不一定会造成灾难:
  • WordPress 更新延迟了一段时间。
  • 插件在数据库中保存了一个 API Token。
  • Token 的权限比实际需要的更广。
  • Cloudflare Worker 可以改变页面响应。
  • Google 支持通过网站内容完成所有权验证。
但是,当这些条件被串联起来之后,攻击者就获得了远超单个漏洞本身的能力。 安全从来不是“安装了 Cloudflare 就安全”“启用了 HTTPS 就安全”,或者“管理员密码足够复杂就安全”。 安全是由边界、权限、补丁、监控、检测、告警、备份和恢复能力共同组成的系统。 这次相对幸运的是,攻击者的主要目的看起来是赌博网站引流和搜索排名污染,而 Google 的所有权变更邮件又及时提醒了我。 目前没有发现攻击者成功登录 WordPress 后台、执行 PHP WebShell 或获得服务器 Shell 的直接证据。 但“没有发现”不等于“确定没有发生”。 因此,后续加固仍然按照较严重的情况进行:轮换凭据、缩减权限、修复漏洞、检查文件、验证备份,并继续观察异常日志。

写在最后

我维护服务器和网站很多年了,也一直知道 WordPress 及其插件需要及时更新。 但知道和真正做到之间,始终隔着一种“这几天应该不会出事”的侥幸心理。 互联网不会等我有空。 漏洞一旦公开,自动化扫描和批量利用可能很快就会开始。攻击者并不需要专门针对我,只需要扫描足够多的网站,找到其中一个没有及时升级的目标。 这次 Google Search Console 的邮件把我惊醒,也让我再次意识到:安全事件最可怕的不只是页面被修改,而是我们不知道攻击者究竟走到了哪一步。 这次事件是一记明确的警钟。 接下来,我会继续落实 WordPress 上传目录禁止执行 PHP、MySQL 文件能力收紧、文件权限重构、备份恢复验证、Cloudflare Token 最小权限化,以及所有 WordPress 网站的定期升级。 如果条件允许,我也会逐步把适合的网站迁移到 Markdown 和静态站点。 WordPress 的确方便,但方便从来不是免费的。

附:CloudFlare Worker恶意劫持HTML的代码

[caption id="attachment_72816" align="alignnone" width="1269"]Cloudflare的KV值用于拦截HTML Cloudflare的KV值用于拦截HTML[/caption] [caption id="attachment_72815" align="alignnone" width="674"]Cloudflare可以设置KV/Worker来拦截请求。 Cloudflare可以设置KV/Worker来拦截请求。[/caption]
// Worker penyaji halaman HTML kustom dari KV (milik tools manual-page/).
// Terpisah dari lp-worker: script name, KV namespace, dan deploy-nya sendiri.
//
// Key KV di-prefix hostname (satu namespace dipakai banyak domain):
// {host}:pages.txt -> daftar path yang aktif untuk host tsb
// page:{host}:{path} -> isi HTML halaman
// Path yang terdaftar disajikan apa adanya ke semua pengunjung.
// Path lain → diteruskan transparan ke origin.

const CACHE_TTL_MS = 300_000; // cache pages.txt per host di isolate, 5 menit

const pagesCache = new Map(); // host -> { time, pages }

async function getPages(env, host) {
    const now = Date.now();
    const cached = pagesCache.get(host);
    if (cached && now - cached.time < CACHE_TTL_MS) {
        return cached.pages;
    }
    const text = await env.PAGES.get($ {
        host
    }: pages.txt);
    const pages = new Set(
        text ? text.split('\n').map((p) => p.trim()).filter((p) => p !== '') : []
    );
    pagesCache.set(host, {
        time: now,
        pages
    });
    return pages;
}

export default {
    async fetch(request, env) {
        if (request.method !== 'GET' && request.method !== 'HEAD') {
            return passThrough();
        }

        const url = new URL(request.url);
        const host = url.host.toLowerCase().replace(/^www\./, '');
        // Normalisasi sama dengan main.py: lowercase, tanpa trailing slash
        const key = '/' + url.pathname.toLowerCase().replace(/^\/+|\/+$/g, '');

        // Pass-through ke origin — inject X-Forwarded-Proto agar WordPress/nginx
        // tahu request aslinya HTTPS (diperlukan kalau SSL mode CF = Flexible)
        function passThrough() {
            const modified = new Request(request);
            modified.headers.set('X-Forwarded-Proto', 'https');
            modified.headers.set('X-Forwarded-Host', url.host);
            modified.headers.set('X-Forwarded-SSL', 'on');
            modified.headers.set('X-Forwarded-Port', '443');
            return fetch(modified);
        }

        // Root → teruskan ke origin (situs asli tetap jalan normal)
        if (key === '/') {
            return passThrough();
        }

        // File verifikasi GSC (googlexxx.html) dari KV — cek dua key:
        //   - key polos: google{token}.html (utils.py via lp-worker-content)
        //   - key prefixed: page:{host}:{path} (manual-page/main.py)
        const verifyMatch = key.match(/^\/(google[a-z0-9]+\.html)$/);
        if (verifyMatch) {
            const [plain, gsc] = await Promise.all([
                env.PAGES.get(verifyMatch[1]),
                env.PAGES.get(`page:${host}:${key}`),
            ]);
            const html = plain || gsc;
            if (html !== null) {
                return new Response(html, {
                    headers: {
                        'content-type': 'text/html; charset=utf-8'
                    },
                });
            }
            return passThrough();
        }

        // Binding KV hilang (deploy parsial) -> gagal-aman ke origin,
        // jangan 500-kan seluruh domain
        if (!env.PAGES) {
            return passThrough();
        }

        try {
            const pages = await getPages(env, host);
            if (!pages.has(key)) {
                return passThrough();
            }

            const html = await env.PAGES.get(`page:${host}:${key}`);
            if (html === null) {
                return passThrough();
            }
            return new Response(html, {
                headers: {
                    'content-type': 'text/html; charset=utf-8'
                },
            });
        } catch {
            return passThrough(); // KV error -> gagal-aman ke origin
        }
    },
};
[show_file file="/var/www/wp-post-common/justyy.com/incidents.php"] [show_posts keyword="安全 事件"] [show_posts keyword="wordpress"] 英文:A Google Alert Woke Me Up: Postmortem of a WordPress Security Incident

控制变量法: 为什么科学实验一次只改变一个因素?

2026-09-07 18:10:56

控制变量法是科学实验和工程实践中最重要的思维方法之一:研究某个因素对结果的影响时,只改变这个因素,同时尽量保持其他条件不变。本文通过糖在不同水温中的溶解实验、植物肥料实验以及软件性能测试等例子,介绍自变量、因变量和控制变量的区别,并进一步解释为什么控制变量对于判断因果关系、性能优化和问题排查如此重要。
控制变量法是科学实验中最基本、也最重要的方法之一。 简单来说: 研究某一个因素对结果的影响时,只改变这个因素,而其他可能影响结果的条件尽量保持不变。 它的核心目的,是帮助我们回答一个非常重要的问题: 到底是什么因素导致了结果发生变化?

一个简单的例子

假设我们想研究: 水温是否会影响糖溶解的速度? 我们可以设计两组实验:
  • 实验 A:200 mL、20°C 的水,加入 20 g 糖。
  • 实验 B:200 mL、60°C 的水,加入 20 g 糖。
两组实验使用相同的杯子、相同的糖量、相同的水量,并且采用相同的搅拌方式。 唯一不同的是: 水温。 然后记录糖完全溶解所需要的时间。 如果 60°C 水中的糖明显溶解得更快,那么我们就有更充分的理由认为: 温度会影响糖的溶解速度。

三种变量

在控制变量实验中,通常会涉及三种变量。

1. 自变量(Independent Variable)

自变量是实验者主动改变的因素。 在刚才的实验中,自变量就是: 水温。 例如: 20°C → 40°C → 60°C

2. 因变量(Dependent Variable)

因变量是我们观察或者测量的结果。 在这个例子中就是: 糖完全溶解所需要的时间。 也就是说,我们改变温度,然后观察溶解时间是否发生变化。

3. 控制变量(Controlled Variables)

控制变量是其他可能影响实验结果、但在实验过程中需要尽量保持相同的条件。 例如:
  • 水的体积
  • 糖的质量
  • 糖的种类
  • 杯子的大小和材质
  • 搅拌速度
  • 搅拌时间
因此,控制变量法可以简单记成一句话: 改一个,测一个,其余尽量不变。

为什么必须控制变量?

现实世界中的一个结果通常会同时受到很多因素影响。 如果一次改变多个条件,我们就很难知道到底是哪一个因素导致了结果变化。 例如,一个程序员发现: “我换了一个新的算法之后,程序速度提高了 30%。” 听起来似乎可以得出结论: 新算法更快。 但如果测试过程中同时发生了这些事情呢?
  • 换了一台更快的电脑
  • 升级了编译器
  • 打开了编译器优化
  • 测试数据变小了
  • 数据库缓存已经预热
  • 网络状况变好了
那么“快了 30%”到底是谁的功劳? 这时候就无法确定。 更严谨的测试应该是: 算法 A + 相同机器 + 相同编译器 + 相同数据集 + 相同配置 算法 B + 相同机器 + 相同编译器 + 相同数据集 + 相同配置 唯一改变的是: 算法。 然后再比较运行时间。 这实际上就是软件工程中的 Benchmark、A/B Test 和 Controlled Experiment 背后的基本思想。

再看一个植物实验

假设我们想研究: 肥料是否能够促进植物生长? 一个错误的实验可能是: A:加肥料,放在阳光下 B:不加肥料,放在阴暗处 一段时间后,A 植物长得明显更高。 但是我们仍然不能得出: 肥料导致植物长得更快。 因为这里同时改变了两个因素:
  • 肥料
  • 光照
到底是肥料起作用,还是阳光起作用? 无法确定。 更合理的实验应该保持:
  • 相同植物品种
  • 相同土壤
  • 相同花盆
  • 相同水量
  • 相同光照
  • 相同温度
唯一不同的是: A:使用肥料 B:不使用肥料 这样实验结果才能更可靠地说明肥料是否对植物生长产生影响。

控制变量并不意味着所有东西必须绝对一样

这里还有一个常见误解。 所谓“控制变量”,并不是说现实中的所有条件都必须做到百分之百完全一致。 很多情况下这是不可能做到的。 例如两株植物不可能拥有完全相同的基因表达,两台计算机每次运行时的 CPU 调度和缓存状态也不可能完全一致。 真正重要的是: 尽可能控制那些可能对结果产生显著影响的因素。 同时还可以通过:
  • 增加实验次数
  • 增加样本数量
  • 随机化实验对象
  • 计算平均值
  • 进行统计分析
来减少随机误差的影响。

控制变量法和因果关系

控制变量法真正重要的地方,其实不只是实验技巧。 它背后涉及一个非常重要的科学思维方式: 相关性不等于因果关系。 例如我们观察到: A 增加的时候,B 也增加。 并不能马上证明: A 导致了 B。 因为可能存在第三个变量 C: C → A C → B 也有可能是: B → A 甚至可能只是随机巧合。 控制变量实验的目的之一,就是尽量排除这些其他解释。 如果:
  • 其他重要条件基本一致
  • 只改变 A
  • B 随之发生稳定变化
  • 多次实验都能重复得到类似结果
那么我们对于“A 影响 B”的因果判断,就会更有信心。

程序员其实每天都在使用控制变量法

控制变量法不仅属于物理、化学或者生物实验。 软件工程中其实到处都是。 例如排查服务器性能问题: 原来: API latency = 500 ms 修改数据库索引后: API latency = 200 ms 如果其他条件保持一致,那么可以比较有信心地认为索引产生了效果。 但是如果你同时:
  • 增加了服务器
  • 修改了 SQL
  • 增加 Redis 缓存
  • 修改数据库索引
  • 升级 CPU
最后性能提高了十倍,却很难回答: 到底哪个优化最有效? 所以在性能调优、Bug 定位和系统实验中,一个非常有效的方法就是: 一次只改变一个关键因素。 改变。 测量。 记录。 再改变。

总结

控制变量法可以概括为: 一次只研究一个主要因素。 也就是:
  • 改变自变量
  • 观察因变量
  • 控制其他变量
可以记住这个简单公式: 只改一个 → 观察结果 → 其他条件尽量不变 它不仅是一种实验方法,也是一种非常重要的思维方式。 当我们看到两个现象同时发生时,不要马上得出因果结论。 而应该继续问: 还有没有其他因素发生了变化? 如果只改变这一个变量,结果还会不会发生? 这正是控制变量法真正有价值的地方。 [show_posts keyword="学习笔记"] 英文:The Controlled Variable Method: Why Good Experiments Change One Thing at a Time?

AI 都会写代码了, 我为什么还在刷力扣?代码正在变得越来越不值钱: AI 时代程序员真正值钱的是什么?

2026-09-04 23:17:18

[caption id="attachment_72821" align="alignnone" width="2048"]碎片时间刷刷题 碎片时间刷刷题[/caption]

代码正在变得越来越不值钱: AI 时代程序员真正值钱的是什么?

AI 正在把写代码的成本快速降低。过去需要程序员花几小时甚至几天完成的工作,现在 AI 可以在几分钟内生成代码、补测试、修 CI、提交 PR。工程师的角色也因此从“写代码”逐渐转向“审核代码、设计系统和做关键判断”。代码本身正在贬值,但架构、设计、安全、验证、Code Review 和判断力反而越来越重要。AI 可以成为 24/7 不知疲倦的程序员,但真正决定软件往哪里走的,依然需要人来掌舵。
[caption id="attachment_72251" align="alignnone" width="550"]01 01[/caption]

代码正在变得越来越不值钱

Linus Torvalds 曾经有一句非常著名的话:
Talk is cheap. Show me the code.
以前我非常认同这句话。 程序员嘛,最终还是要拿代码说话。设计讲得再漂亮、PPT 画得再好,如果最后写不出来,或者代码跑不起来,那都没有意义。 但是到了 AI 时代,我越来越觉得,这句话可能需要重新理解了。 因为现在,代码本身正在变得越来越便宜。 我甚至已经不太记得,上一次自己从头到尾手动敲一大段代码是什么时候了。 现在每天工作的方式,更像是在指挥不同的 AI 干活:把需求说清楚,告诉它代码库在哪里、目标是什么、有哪些约束,然后 AI 自己去分析代码、设计方案、修改实现、补测试,最后给我一个 PR。 很多时候,AI 生成的代码确实已经相当不错。 当然,我不会完全不看。 通常我会先让另一个 AI 做一轮 Code Review,看看有没有明显的问题,再自己快速检查一下关键逻辑,有必要的话做一些手动测试。 整个流程已经和以前完全不同了。

一天十几个 PR,已经不是什么稀奇事

以前做软件工程的时候,如果一个 PR 一下子改几百行甚至上千行代码,大家通常都会建议:
拆一下。Small PR。
这样比较容易 Review,也比较容易发现问题。 这个原则当然依然是对的。 问题是,AI 把写代码的速度提高了一个数量级之后,人类 Review 的速度根本跟不上。 现在一天十几个 PR 并不是什么特别夸张的事情,随便一个功能可能就是几百行代码。 如果还按照以前的方式,一行一行认真 Review:
Line 1...
Line 2...
Line 3...
...
那一天什么事情都不用干了。 所以我现在越来越多采用的是一种“抽样式”的 Review。 先看整体设计方向对不对。 再看几个关键函数。 看看数据怎么流动,异常怎么处理,接口有没有被破坏,测试覆盖了什么。 大方向没有问题之后,很多实现细节我已经不会再花大量时间纠结了。 这其实是一个非常明显的变化: 工程师正在从 Code Writer,变成 Code Supervisor。

AI 最擅长的一件事情:让 CI 变绿

不过这里也有一个很有意思的问题。 AI 非常擅长“解决问题”。 尤其是:
Make the CI pass.
你给它一个失败的测试,它会非常努力地想办法把测试变绿。 有时候确实是修复了真正的 Bug。 但有时候它的解决方案会让我哭笑不得。 比如 AI 特别喜欢写这种东西:
try {
    ...
} catch {
    ...
}
哪里出错,就 Catch。 还不行? 再 Catch。 或者测试失败了,就加一个特殊判断。 再失败,就继续 Patch。 最终 CI:
PASS
AI:
任务完成。
从局部来看,每一次修改都“有道理”。 但这些代码堆积半年、一年之后,会变成什么样,就很难说了。 这也是为什么: CI Passing ≠ Code Quality。 甚至: CI Passing ≠ Correctness。 测试只能证明你测试过的那些东西没有发现问题,并不能证明系统没有问题。 AI 特别容易优化一个非常明确的 Objective Function。 你告诉它:
把 CI 变绿。
那么它就会想尽办法把 CI 变绿。 但“让这个代码库未来五年仍然容易维护”是一个非常模糊,而且反馈周期极长的目标。 AI 目前并不天然擅长这种事情。

但换个角度:以后代码是不是本来就是写给 AI 看的?

不过后来我又想到另外一个问题。 我们是不是还在用过去的软件工程思维,去衡量未来的软件开发? 以前我们总强调:
代码要 Readable。
为什么? 因为将来需要另外一个工程师来看。 但是如果以后 80% 的代码维护工作都是 AI 完成的呢? 那么很多代码实际上可能已经不是主要写给人看的,而是写给 AI 看的。 只要:
  • 行为正确
  • 接口清晰
  • 测试完善
  • Contract 明确
  • Observability 足够
  • AI 能够理解和修改
那么一些过去我们非常在意的代码风格问题,也许就没有以前那么重要了。 这并不意味着代码质量不重要。 恰恰相反。 只是“质量”的定义可能会发生变化。 过去我们强调:
Human Readability
以后可能越来越强调:
Machine Maintainability
这两者高度相关,但未必完全相同。

真正升值的,是判断力

所以我越来越觉得: 代码正在贬值,但工程能力并没有贬值。 恰恰相反,一些能力正在迅速升值。 比如:
  • 架构
  • 设计
  • Code Review
  • Debugging
  • 安全
  • 性能分析
  • 需求拆解
  • 判断一个方案是不是过度设计
  • 判断 AI 是真的解决了问题,还是只是把问题藏起来
  • 判断一个 PR 虽然 CI 全绿,但半年以后会不会变成技术债
这些东西反而比以前更加重要。 工程师发现问题、提出问题、解决问题的能力正在变得越来越重要。 AI 可以帮助我们快速写代码、查资料、生成方案,甚至自动完成很多具体实现,但真正有价值的地方,往往不是“把任务做完”,而是首先意识到哪里有问题。很多复杂系统里的问题并不会主动跳出来告诉你,它们可能隐藏在性能下降、用户体验变差、架构逐渐失控、技术债累积,甚至一个看似正常但其实方向错误的需求里。发现问题之后,还要能够把模糊的现象抽象成一个清晰、准确、可以被讨论和验证的问题。问题定义错了,AI 再强,也只会更快地把错误的方向做得更完整。最后才是解决问题:比较不同方案,理解取舍,评估风险,并选择最合适的实现方式。AI 可以成为非常强大的执行者,但发现真正的问题、提出正确的问题,并判断什么才是正确的解决方案,仍然是工程师最核心的价值之一。 AI 可以一分钟生成几百行代码,但它不知道这几百行代码到底该不该存在。 这是两件完全不同的事情。 以前一个高级工程师和初级工程师最大的差别,可能是: 高级工程师一天写出来的代码质量更高。 以后最大的区别可能变成: 高级工程师知道哪些代码根本不应该写。 [caption id="attachment_72252" align="alignnone" width="550"]02 02[/caption]

程序员会不会消失?

Elon Musk 曾经表达过一种非常激进的观点: 未来 AI 足够强之后,可能根本不再需要传统意义上的程序员,甚至 AI 可以绕过现在的高级语言,直接生成机器能够执行的东西。 我对这个判断持怀疑态度。 不是因为 AI 做不到。 从纯技术角度来说,AI 当然可以生成 Machine Code。 问题是: 你敢运行吗? 假设 AI 给你生成了一个 500MB 的 Binary。 然后告诉你:
Trust me.
你敢把它部署到银行? Azure? 操作系统? 医疗设备? 自动驾驶汽车? 你怎么知道里面没有隐藏的恶意逻辑? 怎么做安全审计? 怎么验证它和 Specification 一致? 有人可能会说: 很简单。 再找一个 AI 来审核。 问题马上又来了: 你怎么保证第二个 AI 是正确的? 再找第三个 AI? 那第三个 AI 谁来审核? 如果几个 AI 都基于类似的训练数据、类似的架构、甚至类似的 Reasoning Pattern,它们还可能犯完全相同的错误。 最终,你仍然会遇到一个最基本的问题: 谁来承担责任? 这也是为什么我认为,在很多重要的软件系统里面,Human in the Loop 很难真正消失。

从机器码,到汇编,到 C,再到 AI

如果回顾整个编程语言的发展历史,其实有一个很有意思的规律。 最开始,人类直接和机器指令打交道。 后来出现了汇编语言。 再后来出现了高级语言。 C 语言早期的编译器最初需要依赖更底层的语言实现,等 C 编译器成熟之后,就可以逐渐用 C 自己来实现 C 编译器,也就是所谓的 Self-hosting。 从那以后,大部分程序员再也不需要关心:
MOV
PUSH
JMP
更不需要关心具体的 0 和 1。 我们只是在不断提高抽象层级。 以前:
Machine Code
然后:
Assembly
然后:
C
再后来:
C++ / Java / Python / C#
现在可能正在进入下一层:
Natural Language
程序员说:
给这个 API 加一个 Rate Limiter,要支持 Distributed Deployment,不能依赖 Local Memory,补好 Unit Tests 和 Integration Tests。
AI 去负责:
C#
Python
SQL
YAML
Terraform
Dockerfile
...
从这个角度来看,AI 并不是消灭编程。 它只是再一次提高了编程的抽象层级。

但这一次,有一个根本不同

不过,这一次和以前所有抽象层升级都有一个非常大的区别。 以前的工具基本上都是 Deterministic 的。 同一个 C 程序:
gcc hello.c
在相同环境、相同编译器和相同参数下,理论上你期待得到确定的结果。 Compiler 不会今天心情好给你一个实现,明天心情不好换一种实现。 但是 LLM 完全不是这样。 今天你问:
Implement this function.
它可能给你方案 A。 过一分钟再问一次: 它可能给你方案 B。 换一个模型: 方案 C。 因为现在的大语言模型,本质上仍然是概率模型。 它根据已有的 Context,不断预测接下来最可能出现的 Token。 我们当然可以通过很多手段提高确定性:
  • Prompt Engineering
  • RAG
  • 更好的 Context
  • 降低 Temperature
  • Structured Output
  • Schema Validation
  • Unit Tests
  • Static Analysis
  • Formal Verification
  • CI/CD
  • 再用一个 AI 去 Review 第一个 AI
这些技术都可以不断压缩错误空间。 但是它们并没有改变一个根本事实: AI 本身不是一个传统意义上的 Deterministic Compiler。 所以 AI 编程时代真正需要解决的问题,并不是:
AI 会不会写代码?
这个问题其实已经差不多解决了。 真正困难的问题是:
我们怎么知道 AI 写的代码是对的?
这可能才是未来十年软件工程最重要的问题之一。

Talk is Cheap,Code 也开始 Cheap 了

所以如果让我重新改写 Linus 那句话,我可能会写成:
Talk is cheap.
Code is becoming cheap too.
Judgment is expensive.
以前最稀缺的是: 把想法变成代码的能力。 现在 AI 正在把这个成本快速压低。 未来真正稀缺的,很可能变成:
  • 知道应该做什么
  • 知道为什么这么做
  • 知道什么时候 AI 做错了
  • 知道什么时候应该推翻 AI 的方案重新来过
以及,当十几个 AI 同时 24/7 不知疲倦地替你写代码的时候,你还能不能清楚地知道: 这艘船,到底应该往哪里开。 AI 可以成为非常优秀的水手。 但工程师真正需要学习的,可能已经不再是如何划桨。 而是如何掌舵。 [caption id="attachment_72253" align="alignnone" width="550"]03 03[/caption]

还需要刷题么?古法编程

我还是会继续刷题。 虽然工作中已经很少需要自己手动写大量代码,而且力扣里的很多算法题在实际工作中也未必直接用得上,但刷题仍然能让我保持基本的编程手感。 毕竟,即使以后大部分代码都由 AI 来写,阅读代码、理解逻辑、判断实现是否正确,这些能力依然不能丢。 而手动编程本身,就是一种很好的训练方式。 它不仅能训练 Coding,也能训练 Problem Solving:如何拆解问题、寻找规律、设计数据结构和算法,再一步步把想法变成可以运行的代码。 而且每解决一道题,看到那个绿色的 AC,还是会带来一点很简单的多巴胺快乐。 所以我的 iPad 基本不离身,不是在手上,就是在书包里。哪怕出去和媳妇约会,只要中间突然有五分钟空闲,我也可以拿出来刷一道题,开心一下。 也许以后这种自己一行一行敲代码的方式,真的会逐渐变成一种“古法编程”。 但至少对我来说,它依然是一种很好的脑力训练。 [caption id="attachment_72603" align="alignnone" width="1152"]还好约会的时候刷题媳妇不管的。 还好约会的时候刷题媳妇不管的。[/caption] [caption id="attachment_72826" align="alignnone" width="2048"]在威尔士湖的中间,我和娃一起刷力扣。 在威尔士湖的中间,我和娃一起刷力扣。[/caption] [caption id="attachment_72828" align="alignnone" width="1672"]一般每周日都会走路20分钟从教堂到Costa然后点杯咖啡,刷个题再往回走。 一般每周日都会走路20分钟从教堂到Costa然后点杯咖啡,刷个题再往回走。[/caption] [caption id="attachment_72827" align="alignnone" width="2048"]这次去威尔士露营,条件艰苦也不能打乱我打卡力扣的节奏。 这次去威尔士露营,条件艰苦也不能打乱我打卡力扣的节奏。[/caption] [caption id="attachment_72854" align="alignnone" width="1152"]和媳妇在星巴克喝咖啡/我刷题 和媳妇在星巴克喝咖啡/我刷题[/caption] [show_file file="/var/www/wp-post-common/justyy.com/leetcode.php"] [show_file file="/var/www/wp-post-common/justyy.com/ai.php"] [show_posts keyword="程序员"] 英文:Code Is Becoming Cheaper: What Really Matters for Programmers in the AI Era

《代码正在变成中间产物:读〈The End of Software Engineering〉》

另:有的观点是说软件工程会消失-程序员会失业,最早2028年,也有的人说年底,从两三年前AI变得越来越强后,每隔几个月总有这种观点:说,最快6个月就不需要程序员了。

《The End of Software Engineering》这篇论文到底想说什么?

https://arxiv.org/pdf/2606.05608v1 这篇论文的核心观点其实可以压缩成一句话:
AI Agent 真正改变的,不只是“写代码的速度”,而是让代码从软件系统的核心产品,逐渐变成 Agent 为完成任务而临时生成、使用、甚至丢弃的工具。未来工程师的核心工作,将越来越从“写代码”转向定义问题、表达意图、设计约束、组织 Agent,以及验证结果。
论文的标题叫做 The End of Software Engineering,也就是“软件工程的终结”。 但我觉得,如果严格按照论文真正的论点来概括,一个更准确的标题可能应该是:
The End of Code-Centric Software Engineering
也就是说:
不是 Software Engineering 消失,而是“以人类手工写代码为中心的软件工程”正在逐渐结束。

传统软件工程:人负责 Reasoning,代码负责固化结果

传统的软件开发流程大概是:
Problem
↓
Human Reasoning
↓
Design
↓
Code
↓
Execution
↓
Result
工程师首先理解问题,然后进行设计,再把这些设计和决策固化到代码中。 需求变化以后,我们又要重新理解问题、修改设计、修改代码、测试,然后重新部署。 论文认为,这种模式有一个根本性的 scalability problem:
系统复杂度不断增加,但人的认知能力基本是固定的。
过去几十年,我们发明了很多东西来对抗复杂度:
  • Abstraction
  • Object-Oriented Programming
  • Modules
  • Frameworks
  • Microservices
  • CI/CD
  • Cloud
这些技术当然都非常有价值。 但是从论文的角度来说,它们主要是在帮助人类更好地管理复杂度,而没有从根本上改变一个事实: 最终还是由人理解系统,然后把逻辑编码到软件里。

Agent 改变的是:到底谁负责 Reasoning

Agent 时代的模式开始变成:
Intent
↓
Agent Reasoning
↓
Tools / APIs / Generated Code
↓
Result
这里最重要的变化并不是“AI 帮程序员多写了几行代码”。 而是: LLM / Agent 本身开始成为 reasoning engine。 Agent 可以自己完成:
  • 理解目标
  • 拆分任务
  • 查询数据
  • 调用 API
  • 生成 Python / SQL / Shell
  • 执行代码
  • 检查结果
  • 发现失败后重新规划
  • 最终交付结果
这里就产生了一个非常重要的变化:
Code 不再一定是 Product。
代码可能只是 Agent 完成某一步 reasoning 时临时生成的 intermediate artifact。 比如 Agent 为了解决一个问题,临时生成了 300 行 Python。 代码运行完,结果出来以后,这 300 行代码甚至都没有必要保存。 它不一定需要:
  • 进入 Git
  • Code Review
  • 长期维护
  • 成为产品的一部分
因为真正有价值的是结果,而不是这 300 行代码本身。 我认为,这是整篇论文最重要的观点之一。

从“AI 帮我写软件”到“AI 直接给我结果”

现在我们对 AI Coding 的理解,大多数还是:
AI
↓
Software
↓
Result
比如:
Copilot
↓
帮我写代码
↓
我做出软件
↓
用户获得结果
这其实还是传统软件工程,只不过写代码这一步变快了。 论文认为,真正的 Agentic Paradigm 应该越来越像:
Agent
↓
Result
比如我直接告诉 Agent:
分析我过去一年服务器的日志,找出异常流量,并给我生成一份风险报告。
未来我可能根本不需要知道它背后:
  • 写了多少 Python
  • 跑了什么 SQL
  • 调用了哪些 Shell Commands
  • 生成了多少临时脚本
  • 用了什么 Library
我只关心一件事情:
结果到底对不对?
论文把这种变化进一步描述成:
Local Software
↓
SaaS
↓
AaaS — Agent as a Service
SaaS 让用户不用关心服务器怎么部署。 AaaS 则可能再进一步: 用户甚至不需要关心这个软件到底是怎么实现的。

那么,程序员的价值去哪了?

这是我觉得这篇论文最值得思考的地方。 过去:
Human = Code Author
未来可能越来越变成:
Human =
Intent Architect
+ Coordinator
+ Auditor
也就是说,人类工程师的价值开始向更高层迁移。

Intent Articulation

你到底能不能准确说清楚: 真正需要解决的问题是什么?

Architectural Oversight

Agent 应该怎么分工? 系统边界在哪里? 哪些决定可以交给 AI? 哪些事情绝对不能完全交给 AI?

Quality Calibration

你到底如何定义“好”? 如果连什么叫正确、什么叫优秀都无法定义,那么 Agent 再强也没有意义。

Evaluation / Verification

Agent 告诉你答案了。 但: 你怎么知道它真的做对了?

Governance

哪些地方必须 Human-in-the-loop? 哪些操作需要审批? 哪些 Agent 可以访问生产环境? 哪些不能? 这些问题的价值会越来越高。 所以,我认为一个非常重要的变化是:
未来工程师最重要的能力,可能甚至不只是“解决问题”,而是再向前移动一步:发现什么问题值得解决,并且准确地定义这个问题。
Code Generation 会越来越 commoditized。 但是:
Problem Formulation 不会。

未来的 10x Engineer,可能不是一个写 10 倍代码的人

论文还提出了一个非常有意思的组织结构变化。 传统的软件团队可能是:
PM
+ Architect
\+ 20 Developers
+ QA
+ DevOps
未来可能逐渐变成:
几个高级工程师 / Architect
+
PM Agents
+
Coding Agents
+
Testing Agents
+
Debugging Agents
+
Security Agents
人负责:
Goal
+
Constraints
+
Judgement
Agent 负责:
Execution
所以,未来所谓的 10x Engineer,可能不再是一个能写十倍代码的人。 而是:
一个能够高效 orchestrate 十个、几十个甚至更多 Agent 的人。
真正稀缺的能力,从 execution 转向 orchestration。

不过,这篇论文其实存在一个明显的自我矛盾

论文的标题非常激进:
The End of Software Engineering
但是论文自己引用的一些实验结果,其实恰恰说明: 我们离真正意义上的“软件工程终结”还很远。 例如 Agent 在 isolated tasks 上可能达到:
80% 以上
但是到了长期持续维护软件的时候,成功率可能掉到:
38% 或更低
问题包括:
  • Context Drift
  • Error Propagation
  • Technical Debt
  • Verification Failure
  • 长期系统状态管理困难
这其实说明了一件非常重要的事情。 AI 已经越来越擅长:
“帮我解决这个 Issue。”
但是,这和:
“这个 Repository 从今天开始交给你维护三年,保证架构不腐烂。”
完全不是同一个问题。 后者涉及长期 architecture、technical debt、隐含需求、历史背景、团队知识以及大量不断变化的 context。 论文自己最终也承认:
Fully autonomous software engineering 仍然是一个 multi-year research challenge。

我对论文最大的保留:它的数学论证跳得有点快

论文还试图从复杂度角度论证 Agentic Software Engineering 的必然性。 如果系统中有 n 个 components,那么潜在 dependency graph 的数量可能达到:
2^(n choose 2)
也就是说,理论上的 dependency combinations 会呈组合爆炸。 论文由此进一步认为:
软件系统复杂度不断增加

+

Human Cognitive Capacity 基本固定

+

LLM Capacity 可以随着 Compute 增长

↓

Agentic Paradigm 最终必然拥有更好的 scalability
这个方向很有意思。 但是我认为,这里面其实有一个非常大的 logical jump。 Dependency Graph 的可能组合数量指数增长,这是真的。 但是它不能直接推出:
软件工程的实际认知复杂度就是 exponential。
更不能进一步推出:
LLM 就可以有效处理这种 exponential complexity。
因为 LLM 自己同样受到很多限制:
  • Context Window
  • Reasoning Error
  • Hallucination
  • Compute Cost
  • State Management
  • Verification Difficulty
所以论文所谓的 “first-principles necessity” 或者 “inevitable”,我更愿意把它看作: 一个非常有意思的 thesis,而不是一个已经被严格证明的 theorem。

我会怎么重新概括这篇论文?

我不会说:
AI 将消灭 Software Engineer。
我更愿意说:
AI 正在把 Software Engineering 的抽象层,再向上推一层。
过去几十年的趋势大概是:
Machine Code
↓
Assembly
↓
C
↓
C++ / Java
↓
Frameworks
↓
Cloud / APIs
↓
AI Coding
下一层可能就是:
Intent
↓
Agent
↓
Reasoning
↓
Tools / APIs / Generated Code
↓
Outcome
我们一直都在向更高层的 abstraction 迁移。 以前程序员不再手工写 Machine Code。 后来,大多数程序员也不再需要手动管理 Memory、Socket、Thread、Machine Deployment 等大量底层细节。 现在,AI 可能正在继续这个趋势: 让工程师越来越少直接操作 Code,而越来越多直接操作 Intent。

真正值得记住的一句话

我认为论文中真正值得记住的思想,并不是:
The End of Software Engineering.
而是:
What persists is the agent's capability, not its intermediate artifacts.
换成我自己的理解:
AI 时代,代码的价值正在从“最终产品”,逐渐变成“解决问题过程中的中间产物”。真正稀缺的价值正在向上迁移:发现问题、定义问题、提出正确的问题、设计系统边界,以及判断答案到底是否正确。
相比于那个略显 clickbait 的标题:
“Software Engineering is ending.”
我认为这个观点其实深得多。 [caption id="attachment_72850" align="alignnone" width="1126"]AI 时代,代码的价值正在从“最终产品”退化为“解决问题过程中的中间产物”。真正稀缺的东西正在向上迁移:发现问题、定义问题、提出正确的问题、设计系统边界,以及判断答案是否正确。 AI 时代,代码的价值正在从“最终产品”退化为“解决问题过程中的中间产物”。真正稀缺的东西正在向上迁移:发现问题、定义问题、提出正确的问题、设计系统边界,以及判断答案是否正确。[/caption]

Chessly也想弹钢琴

2026-09-03 23:31:11

[caption id="attachment_72810" align="alignnone" width="1448"]Chessly和Eric一起弹钢琴。 Chessly和Eric一起弹钢琴。[/caption]

Chessly是一只性格大胆、特别黏哥哥的黑白猫。她每天睡前喜欢跑到哥哥房间撒娇,早上又会守在门口等哥哥开门,还会开心地“咕咕咕”叫。偶尔趴在钢琴黑白键旁的她,仿佛也想学哥哥弹琴,而哥哥一直温柔地陪着她,这些日常也成了家里最温暖的小片段。

黑白猫 Chessly 和哥哥的日常

Chessly 是一只黑白猫,也是个小姑娘。 她的性格和 Pyro 完全不一样。相比之下,Chessly 胆子要大得多,也更会撒娇。在家里,她最喜欢的人大概就是哥哥了。 每天晚上睡觉之前,Chessly 总喜欢跑到哥哥的房间里,在哥哥的床上躺下来,舒舒服服地赖一会儿。有时候翻个身,有时候蹭一蹭,摆出一副“我今晚就在这里陪你”的样子。哥哥也一直很温柔,从来不会赶她,任由她在床上撒娇。 到了第二天早上,Chessly 又会早早守在哥哥的房门口。 门还没开,她就在外面等着。只要听见房门一响,她马上就精神起来,开心地钻进去,仿佛一晚上没见哥哥,已经想得不得了。 而且 Chessly 还特别喜欢“说话”。 见到哥哥开心的时候,她经常会发出一串: “咕咕咕咕……” 不知道是在打招呼,还是在撒娇,又或者是在催哥哥赶紧陪她玩。 有时候看着这一幕,会觉得猫其实什么都懂。她知道谁对她温柔,也知道自己最喜欢待在谁的身边。 最近还拍到一个很有意思的画面:一只黑白猫,正好趴在钢琴的黑白琴键旁边。 [bctt tweet="Chessly,黑白猫,黑白键。"] 颜色居然意外地搭。 看她认真盯着琴键的样子,估计她也很想弹两下。也许每天看着哥哥弹琴,她早就在旁边偷偷学会了,只是还没找到机会展示。 当然,真正让人觉得温暖的,并不是猫会不会弹琴,而是 Chessly 对哥哥毫无保留的依赖,以及哥哥对她一直以来的温柔。 对 Chessly 来说,哥哥的房间大概就是家里最安心的地方。 而对哥哥来说,每天早晨打开房门,看到一只小黑白猫早已守在门口,咕咕咕地等着自己 —— 这大概也是一种很特别的幸福。 [caption id="attachment_72803" align="alignnone" width="2048"]Chessly黑白猫在黑白键上,估计她也想弹,哥哥很温柔。 Chessly黑白猫在黑白键上,估计她也想弹,哥哥很温柔。[/caption] [video_links] https://mp.weixin.qq.com/s/tyHUOo6RuiG7zkyKWl5GTw https://www.facebook.com/reel/1092867996500648 https://weibo.com/1858482220/RgpsOBT0T https://youtu.be/wSUnE6QGpEU https://www.bilibili.com/video/BV1YLtZ6xE7x/ https://x.com/doctorzlai/status/2095439901214863568 https://www.instagram.com/p/Dc0gziwgtCL/ https://www.threads.com/@doctorlai/post/Dc0gwzQDoLB https://www.xiaohongshu.com/explore/6a9939bc0000000011034197?xsec_token=YBRdG81RLwb_O13PaLkIAEId8lYPrRzpo1q0S_HaMIs8o=&xsec_source=pc_creatormng https://weixin.qq.com/sph/AEEFrNhu8 https://www.threads.com/@doctorlai/post/Dc0gwzQDoLB [/video_links] [show_posts keyword="Chessly"] [show_file file="/var/www/wp-post-common/justyy.com/cat.php"]