阅读视图

发现新文章,点击刷新页面。

我的第一款 iOS App:PingMind

一直觉得有一套合适的反思系统很重要,相关的思考可以参见上一篇文章。于是开始寻找合适的解决方案,但都没有太满意的。既然这套系统具有重要性,而市面上又没有合适的解决方案,那就很有必要自己实现一个,于是就有了 PingMind 这个 app。

Gallery image 1
Gallery image 2
Gallery image 3
Gallery image 4
Gallery image 5

具体的 features 可以参见官网,简单来说就是可以创建每日/周/月的自省问题,并进行记录,设计上尽量保障输入和回顾的便捷性。创建的内容保存在本地,使用 iCloud 同步,支持导出,不需要创建账号,开箱即用。价格上采用 IAP(In App Purchase),可以免费使用大部分功能,购买后解锁全部功能,不需要订阅。

如果你对自省感兴趣,或者也在寻找合适的自省 App,或许可以试试 PingMind。使用过程中有任何的建议和反馈,欢迎留言,或邮件与我联系。

记一次与 Coding Agent 合作实现 Feature 的过程

背景

在实现一个用 SwiftUI 构建的 iOS App 的过程中,我想让 Agent 帮我加一个 Feature:让 Calendar 可以滑动查看上一月/下一月。本以为是个简单的一个需求,过程的艰辛却远超我的预期。这也体现了纯 Vibe Coding 的一个局限:当 AI 撞墙时,即使指令给得再小、再清晰,它都很难独立完成任务。

Gallery image 1

第一次尝试

用的 Claude Code w/Sonnet-4.5,以为是个简单的需求,就给了一个最直接的 prompt:

Make the Boolean Type Calendar Scrollable. Scroll left/right to view previous/next month.

经过几次迭代后,这个 Calendar 可以滚动了,但很卡,于是我把这个信息告诉它,让它进行优化。

there's a scroll glith on boolean type calender view, when I scroll the calender past half, and release, it will lag twice, then slide to the end. think carefully to fix this bug.

又经过了几次迭代,它还是没能 fix 这个卡顿的问题,于是我重置了代码,进行了第二次尝试。

第二次尝试

对于同样的 Feature 不同的 Agent 可能会有不同的解法,所以这次切换到了 Codex w/gpt-5-codex,给了同样的 prompt,除了耗时更长外,结果并没有什么不同。此时我知道,这件事它可能不简单。

第三次尝试

这次只能亲自动手了,卡顿一般跟 re-render 有关,于是我查看代码,将 Calendar 对应的代码,简化成了 Color.random()(Color 本身并没有这个方法,所以加了一个 extension),发现在滑动时,Color 变了好几次,说明这些 View 被 SwiftUI 认为是不同的 View,所以重新创建了。得到这个信息后,让 Calude Code 再次进行优化:

the boolean calendar view is a bit lag while scrolling, it seems to be the view don't have a consistent id, so they re-render while page change. reduce the re-render by giving them appropreate ids.

有了这个信息后,Claude 再次进行优化,几次迭代后,优化完成,它非常自信的告诉我 re-render 的问题解决了,这次应该会非常丝滑。我结合 Self._printChanges(),发现确实重复生成/渲染的问题解决了,但,这个卡顿还在!

第四次尝试

这就很奇怪了,难道是这个用 SwiftUI 实现的 Calendar 有性能问题?为了验证这个想法,我让 CC 简化代码,用最简单的色块代替 Calendar,看看滚动起来是否顺畅。

now it works, but the lag persistent. can we first identify what's causing the lag, by simplify the scenario like use a random color, etc?

CC 听取了建议,把 Calendar 变成了纯色块,滑动是顺畅了,但有个问题,滑动过一半后,色块的颜色就变成了下一个 Calendar 的色块,我分析了下,应该是滑动过半后,page 自动变成了 next page,而这个色块会监听这个值的变化,于是也就变了。把这个信息给 CC 后,它很快就 fix 了。

- the prev/next button works perfect.
- but the scroll still has a problem, it seems to be caused by the page variable, once it pass half, the page change, and current scrolling item will be replace to that page.

给出的结果非常好,没有丝毫卡顿,极其丝滑。

第五次尝试

这么看来确实是 SwiftUI 实现的这个 Calendar 模块有问题,于是我想用 UIKit 重新实现一个,再嵌到 SwiftUI 里,看看是否能解决性能问题。

it seems the SwiftUI's Calendar is the root cause of glitch, maybe we can use UIKit to represent this calendar?

这个改动其实挺大的,所以 CC 也是尝试很多轮后,结合我的反馈,才终于基本可用了,中间还因为用满了 5 小时的 Token 限制,休息了一会。

yeah, its smooth, but after scroll end, the calendar doesn't refresh, all blank day, the title updated though.

---

the behavior is after scroll ended, it first display blank date, then immediately updated with some data, but it's not the final data, it will refresh quickly again to reveal the final data, so visually, like it blinks.

---

yes, it's better now, but the colored background only appear when scroll end, visually its not too good, can we pre fill the calendar?

---

the previous month's colored circles appear immediately, but the month before still blank and fulfilled after scroll end.

---

better, but ${currentMonth}-3 is still blank first when scrolled.

看起来确实丝滑了,实现方案是预加载 3 个 Calendar 的数据,当这 3 个 Calendar 滑动起来,这些蓝色块、红色块会被预先填上,但滑动到第 4 个 Calendar 时会出现先显示空 Calendar,然后再渲染色块的现象。

第六次尝试

CC 的这个策略看起来有点 rigid,能不能先预加载 3 Calendar,当滑动到倒数第二个预加载的 Calendar 时,再往前加载 3 Calendar?

can we make it simpler? because the scroll always from large month to small month (if scroll back to large month, it's already loaded), so why not just prefetch previous 3 months, if scroll to the prefetched month - 1, then start prefetch next 3 months?

很不幸,CC 在 Operate 的过程中触发了 Weekly Limit,好在还有 Codex,于是切换到 Codex,继续这个 CC 未完成的任务。

I'm in the middle of optimizing boolean type calendar scroll performance, I want the strategy be: first preload previous 3 months data, when user scroll to the second to last preloaded data's month, preload next 3 month. help me implement this strategy.

半小多时后,结果出来了,符合需求,但 Token 也用了近 20%(PS:这也是我打算退订 Codex 的一个原因:慢,有时 Token 消耗地还快)。

小结

这个看似简单的需求,如果过程中缺少人的协作,很难达到满意的效果。尽管 AI 在代码生成和辅助开发方面能力强大,但在面对复杂、深层或性能敏感的需求时,它仍然是一个强大的工具,而非完全独立的解决方案。它需要有人能够帮忙诊断问题、制定策略,并在必要时进行干预和引导。纯粹的 Vibe Coding 适用于简单、明确的需求,但对于有挑战的任务,人与 AI 的高效协作,即 “人机协作编程”,才是提升效率和解决问题的关键。

构建自己的反思系统

未经审视的人生是不值得过的。

我们都听过这句话,可能还会有小小的触动,但之后该刷手机还是刷手机,该工作还是工作。

但如果你真的把它当回事,这可能会是你为自己做的,回报率(ROI)最高的投资之一。

开会

把自己的人生旅程想象成一个项目,这个项目的合伙人,是你自己——-过去的你、现在的你,以及未来的你。

而反思,就是你们每周一次的董事会议。你们坐下来,诚实地对话,为了一个共同的目标:让这个项目变得更好。

这是你与未来自己的合作。你现在的每一个决定,都是在为未来的自己铺路,或者挖坑。

遗忘和混乱

如果不主动管理自己的生活会怎样?

帕金森定律说:工作会自动膨胀,直至填满所有可用时间。生命也是如此。琐事、噪音、他人的议程……如果你不主动捍卫自己的时间和精力,就会被它们吞噬殆尽。

遗忘和混乱是人生的默认设置。一个反思系统,就是对抗这种熵增的工具。

不要等到撞上南墙(比如经历人生重大变故),或者在泥潭里动弹不得时,才想起需要一张地图。这张地图,现在就可以开始画。

一个强迫你诚实的系统

一个好的反思系统,会强迫你梳理清楚,自己最关注的是什么。

当你必须写下来,那些模糊的想法就无处遁形,你无法再欺骗自己。

把它当作一个产品来对待。量化关键指标,将进度可视化,记录关键决策。不是为了给别人看,而是为了让你对自己一目了然。

系统会帮你找到自己行为中的 Bug,发现那些让你在错误道路上越走越远的模式。

它让你清晰地回答这两个问题:

  • 我是谁?
  • 我正在变成谁?

让它运转起来

最关键的不是某一次彻夜长谈式的深度反思,而是持续。

让反思成为生活的一部分。像刷牙一样自然,像吃饭一样必须。

不需要完美。只需要开始,然后坚持。

这套反思系统,不会给你人生的标准答案。

但它会确保,那个最重要的问题,始终被提出。


附录

以下是一些可以参考的每日/每周/每月反思问题。

每日反思

类别 问题
习惯 冥想
习惯 运动 (例如:30分钟,具体类型)
习惯 阅读 (例如:15分钟)
习惯 写日记/反思
习惯 饮水 (例如:8杯水)
习惯 屏幕时间 (例如:低于X小时)
习惯 没有吃垃圾食品
习惯 高质量睡眠 (例如:7-9小时)
效率与专注 我是否按照计划的日程行事?
效率与专注 我完成了多少个番茄工作法会话?
效率与专注 我今天是否容易分心?
成果和进步 今天我完成了哪些重要的任务或目标?
成果和进步 我今天有哪些小小的胜利?
学习与成长 我今天学到了什么新东西?
幸福感与情绪 今天我的整体情绪如何 (1-10分)?
幸福感与情绪 今天有哪些事情让我感到感恩?
幸福感与情绪 今天有哪些事情挑战了我的耐心或造成了压力?
反思与改进 今天我有哪些地方可以做得更好?
反思与改进 明天我将做一件什么不同的事情?
关键指标 睡眠时长 (小时)
关键指标 饮水量 (杯/升)
关键指标 深度工作时长 (小时)

每周反思

类别 问题
成果与进步 本周我最主要的3项成就是什么?
成果与进步 我是否在关键项目/目标上取得了进展?
成果与进步 我获得了哪些新技能或知识?
挑战与反思 本周我遇到了哪些主要的困难或挑战?
挑战与反思 什么事情让我感到最大的压力或沮丧?
挑战与反思 我从这些挑战中学到了什么教训?
习惯与日常 我坚持了哪些日常习惯?
习惯与日常 我哪些日常习惯做得不好?为什么?
习惯与日常 我目前的日常安排是否支持我的目标?
幸福感与平衡 本周我的精力水平如何 (1-10分)?
幸福感与平衡 我是否为休息、爱好和社交留出了时间?
幸福感与平衡 本周有哪些事情给我带来了快乐或让我感到充满活力?
计划与优先级 我是否有效地安排了任务和时间优先级?
计划与优先级 有哪些任务延续到下周了?为什么?
展望未来 下周我最重要的3项优先事项是什么?
展望未来 我将对我的计划或习惯做出哪些调整?
关键指标 平均每日睡眠时长 (小时)
关键指标 总运动时长 (小时)
关键指标 总深度工作时长 (小时)
关键指标 社交互动次数

每月反思

类别 问题
主要目标与进展 本月我的主要目标是什么?
主要目标与进展 我是否实现了它们?如果没有,为什么?
主要目标与进展 我在长期目标上取得了哪些重大进展?
学习与成长 本月我获得了哪些新技能、知识或见解?
学习与成长 我完成了哪些书籍、文章或课程?
挑战与挫折 我面临的最大障碍或失败是什么?
挑战与挫折 我是如何应对它们的?我学到了什么?
习惯与系统 哪些习惯变得更强或更稳定了?
习惯与系统 哪些习惯仍然需要更多关注或调整?
习惯与系统 我目前的系统 (例如:计划、组织) 有效吗?
人际关系与联系 本月我如何培养了重要的人际关系?
人际关系与联系 我是否结识了新朋友或加强了现有联系?
财务 (可选) 本月我的支出与预算相比如何?
财务 (可选) 我在财务目标上取得了进展吗?
幸福感与自我关怀 本月我的整体身心健康状况如何?
幸福感与自我关怀 我是否优先考虑了自我关怀和休息?
反思与感恩 本月我最引以为豪的事情是什么?
反思与感恩 本月我最感恩的事情是什么?
展望未来 下个月我最重要的3个目标是什么?
展望未来 我将实施哪些新习惯或系统?
展望未来 下个月我希望重点改进的一个领域是什么?
关键指标 平均生产力得分 (例如:1-10)
关键指标 总学习时长 (小时)
关键指标 新建立的联系数量

避风塘 V2

关于避风塘这个网站的由来,可以见我之前的一篇文章,主要是方便有发布日常/想法的诉求,又缺少合适载体的同学。这次升级让它变得更丰富了些。

添加了音乐模块

Gallery image 1
Gallery image 2

这些音乐列表跟这个博客用的是同一套,也是这么多年自己积累下来的歌单,所以非常个人。「钢琴」和「爵士」比较适合作为工作时的背景音乐。

添加了 YouTube 模块

Gallery image 1
Gallery image 2

这些 YouTube 的 Channels 和 Playlists 也是自己平时收集的,时不时会看看,也一并放出来了。

添加了通知模块

Gallery image 1

这样当别人对帖子点赞或评论时就不会错过了。

支持导出自己的帖子

登入账号后,浏览自己的页面,会看到一个「导出帖子」的按钮,点击之后,所有的帖子会被整理到一个 markdown 文件里,

# limboy 的帖子导出

导出时间:2025-09-24T13:35:46.696Z

共 114 条

## 2025-09-24 12:47

看了黑灯的脱口秀专场(录像),确实很不错。

---

## 2025-09-17 04:53

终于把 Shogun[1] 看完了,之前看过小说,非常精彩。剧版刚出来时,看过两集,品质过硬,但因为没出完,加上忙别的事,就耽搁了。

演员几乎完全符合我看完小说后觉得的每个人应有的样子,尤其是虎永和鞠子,无论是形象还是表演,都堪称完美。

就不剧透了,imdb 上的一位用户的评论我觉得很合适:

> No spoilers from me because to watch it unfold is such a delight, it would be rude to steal that pleasure.

[1]: https://www.imdb.com/title/tt2788316/

---

## 2025-09-13 15:08

摸索出了一个「睡不着觉,是否该起床」的判断方法:完成 100 个呼吸。也就是数自己的呼吸,从 1 数到 100。如果数完了,就起床;没数完,要么睡着了,要么就是走神了,从头再来。

...

天生有罪

看到有不少人推荐这本书,就把它放到了待看列表里,最后是哭着看完的。

这本书的书名并没有夸大其词,作者 特雷弗·诺亚 的出身在当时就是一种罪:在种族隔离时期的南非,他的白人父亲(瑞士-德国裔)和黑人母亲(科萨族)之间的结合是违法的。特雷弗因此被归类为“有色人种”,在一个严格实行种族隔离的社会中,他不属于任何一个阵营。

这本书的核心是诺亚与他母亲帕特里夏的深厚关系(看的过程中我总是会想到史铁生的《我与地坛》)。她是一位极具韧性、虔诚且思想独立的女性,用智慧、幽默和坚定的爱武装特雷弗,教他如何利用语言和思想去打破种族和社会的壁垒。因为他的特殊身份,加上淘气的天性,结合南非当时的社会环境,让他的童年和青少年总是在滑稽可笑和惊心动魄之间切换:被母亲从行驶的汽车中扔出以躲避危险;在不同社区间利用语言优势游刃有余;从经营盗版CD生意,到与家暴的继父斗争等等。

他能够相对平和地度过童年和青少年,并以健康的身心进入成年,在事业上取得成功,他的妈妈功不可没。她在一个传统的黑人家庭长大,却从小就展现出非凡的独立和反叛精神。她拒绝被传统的性别角色和社会期望所束缚,坚持学习打字,成为了一名秘书——这在当时对于黑人女性而言是极不寻常的。正是这种精神,让她敢于与一个白人男子建立关系并生下孩子。她也深知,要让儿子在这样一个扭曲的社会中生存下去,必须赋予他最强大的武器——知识和语言。她坚持让特雷弗学习英语作为母语,因为她认为英语是通向更广阔世界、获取知识和财富的钥匙。同时,她也确保他学习南非的多种语言,如科萨语、祖鲁语和南非荷兰语。她用一种独特的方式教育特雷弗。她带他去白人社区、黑人社区和有色人种社区,让他亲身体验不同世界的规则。她用幽默化解生活的苦难,用坚定的信仰作为精神支柱。

母亲的远见很快得到了验证。在一个由种族决定一切的国度里,语言成为了特雷弗的“变色龙”皮肤。他发现,只要他能说对方的语言,就能在瞬间打破隔阂,获得认同。当一群祖鲁族男孩准备抢劫他时,他用流利的祖鲁语与他们交谈,对方立刻将他视为“自己人”,从而化解了危机。这个经历让他深刻理解到:“语言,比肤色更能定义你的归属。” 他凭借这项技能,在不同种族群体之间游走,既不完全属于任何一方,又能与各方建立联系。

身为局外人,你可以缩进壳里,默默无闻,让别人看不到你,或者你可以走上另一条路。你通过敞开自己的方式,从而保护自己。你不用因为自己是谁而希望被某个小团体接纳,你只要愿意分享自己的一小部分就可以了。对我来说,那部分就是幽默。我了解到,即使我不属于任何一个小群体,但我可以融入所有正在开怀大笑的小团体里面。我会突然出现,分发零食,讲几个笑话。我可以取悦他们,参与他们的一小部分对话,了解一点儿他们的圈子,然后转身离开。我从来不会在哪个圈子里停留过久。我并不受欢迎,但我也不会被排斥。我可以在任何地方,和任何人打交道,与此同时,我又完全是孤单一人。

但随着继父亚伯的到来,特雷弗的家庭生活开始笼罩在恐惧的阴影之下。亚伯不仅对帕特里夏进行身体和情感上的虐待,也与日渐成长的特雷弗关系紧张。亚伯代表了南非社会中大男子主义和父权文化的毒瘤。他无法容忍帕特里夏的独立和坚强,试图用暴力来维护自己的“权威”。特雷弗亲眼目睹了母亲所承受的痛苦,这让他对暴力和家庭关系有了早熟而深刻的认识。他与亚伯之间的冲突不断升级,最终导致他决定搬出去独立生活。

看到这里时,我其实也有跟特雷弗一样的疑惑,为什么不离开?答案其实很简单:离开之后,去哪儿?

从外人的角度指责这个女人,说“你走不就行了”,实在太容易。我的家庭并不是唯—一个发生过家暴的家庭。在我的成长过程中,周围经常有这样的事。在索韦托的街道上,在电视里,电影里,我看到过无数次家暴。如果这是社会范例,那一个女人能去哪儿?当警察都不肯帮她的时候,当她自己的家人都不肯帮她的时候,她能去哪儿?离开那个打他的男人,找到第二个男人很可能还是会打她,而且比第一个更凶的时候,她能去哪儿呢?当一个女人带着三个孩子,而周围的社会会给没有丈夫的女人打上贱民的标签时,她能去哪儿呢?当所有人都会觉得她是个荡妇,她能去哪儿呢?她能怎么做呢?

特雷弗离家后,亚伯的暴力变本加厉。他无法接受帕特里夏的离开,最终在她回家的路上开枪射中了她。一颗子弹穿过她的腿,另一颗子弹奇迹般地擦过她的头骨后部,从鼻孔穿出,没有伤及大脑和重要血管。

当特雷弗赶到医院,看到幸存下来的母亲时,帕特里夏依然不改其幽默本色,她对儿子开玩笑说:“你看,特雷弗,现在你才是家里长得最好看的人了。” 甚至还说:“至少你现在可以说你妈妈被人‘爆头’了,这在街头很酷。”

这一事件是全书的高潮,也是让我哭着看完的部分,当他接到弟弟打来的电话时,我就感觉到不太妙,他妈应该是出事了,但没想到这么严重,更没想到这种情况下居然还能活下来,而且没什么大碍,可能冥冥之中,上帝也进行了干预吧。

直到今天,也没人能够解释发生的一切。就连警察都不明白。因为那把枪不是不能用。它开过一枪,然后开不了了,然后又开了最后一枪。任何懂一点儿枪支的人都会告诉你,一支9毫米口径的手枪绝对不会像那把枪那样哑火。但是在犯罪现场,警察在车道上用粉笔画了很多小圈,都是亚伯开枪后散落的弹壳,而在他在我妈身旁站立的那个位置上,掉着的是四颗完好无损子弹—没人知道这是为什么。

但好像又干预地不太彻底:

亚伯就这么出来了。案件在法律程序上缓缓推进,但所有事情都开始倒向不利于我们的一边。由于我妈妈奇迹般地躲过了一劫,所以对亚伯的指控只能是谋杀未遂,加上此前亚伯的那些家暴,在我妈报警后并没有留下任何记录,所以亚伯没有犯罪案底。而且,他还请了个好律师,一直在法庭上强调,他家里还有孩子在等着他抚养。结果,这个案子根本没有进入正式的审判环节。亚伯认了谋杀未遂的罪,然后被判了三年缓刑。他一天都没有在监狱里蹲过,并且还继续拥有两个儿子的共同监护权。直到今天,他还在约翰内斯堡的大街上,行动完全自由。我上次听到有关他的消息是,他还住在高地北附近的某个地方,离我母亲的住所不太远。

作者特雷弗从一个在夹缝中求生的孩子,成长为一个懂得利用自己“局外人”身份,观察并解构世界的喜剧演员。他的经历让他能够以一种独特的视角看待种族、权力和社会不公。这本书不仅是他个人的回忆录,更是写给他母亲的一封情书,致敬那位教会他如何思考、如何欢笑、如何在一个试图将他定义为“罪恶”的世界里,骄傲地活出自己的女人。

35mm Coffee - 一个创意工作者的线上社区

家附近有一个叫 35mm 的咖啡馆,以前经常去,某天心血来潮就想,会不会 35mm.coffee 正好是个可以注册的名呢?就上 Cloudflare 上看了下,果然可以,于是就注册了。即然注册了,就想着拿来做点什么,一开始把使用地限制在了 35MM 咖啡馆,也就是只有在那里才能使用,后来又将它改造成了只有晚上才能访问的网站,之后去掉了时间限制,改成可以随时访问的小 Twitter,还是不满意,总觉得少了一个明确的主题。

我是一个创作者,平时喜欢做点小东西,也会接触很多创作相关的内容,但总有种孤独感。回想起一开始入行的时候,学的是 ActionScript,那时经常逛一个论坛,氛围挺好的,自己写了一个什么小程序,或者学到了什么都会在那里分享,也从那里学到了不少,在交流过程中也结识了一些志同道合的朋友。

现在论坛已经成了过去式,创作者能逛的地方更多了,小红书、微博、推特、V2EX、知乎等等,但好像都没有特定主题的社区那种特有的氛围,也少了那种相对深入的、持续的、互相启发式的交流。Discord 其实蛮适合的,但它的封闭性和糟糕的桌面端是很大的问题。我开始思考,35mm.coffee 这个域名,是不是可以成为一个契机,重新找回那种失落的连接感,让它成为一个能让创作者们找到共鸣、答疑解惑、分享经验、甚至共同创作的地方?

35mm 代表着胶片时代经典的视角,一种记录真实、捕捉瞬间的工具。对于创作者而言,我们其实也正是在用自己的方式,记录着、捕捉着这个世界。

在这里,你可以:

  • 分享你的「胶片」: 无论是你刚完成的一个小项目,一段在创作中遇到的瓶颈,还是一闪而过的奇思妙想,都可以分享出来。也许你的一个困惑,正是别人曾经走过的路;你的一个灵感,也能点亮别人的火花。
  • 品味「咖啡」的醇厚: 针对某个特定主题,可以发起深入的讨论,比如「如何平衡商业与艺术创作」、「AI 工具对创作流程的影响」、「寻找个人风格的路径」等等。
  • 寻找你的「曝光」: 晒出你的作品,无论是草稿、半成品还是最终成果。
  • 建立「暗房」般的连接: 也许你会在这里找到志同道合的伙伴,一起发起一个协作项目,或者只是单纯地分享彼此的创作日常,互相打气。

最后,希望这个小站能重新找回那种失落的连接感,让创作之路不再孤单。

避风塘

大概 4 年前,我注册了一个域名 before.town,因为脑海中忽然闪过「避风塘」,好像正好可以对应英文的 before town,而 town 又可以作为域名的后缀,就搜了一下,果然可以注册,就毫不犹豫地下手了,这一放就是 4 年。

生活中,总是会有一些瞬间,让我们忍不住拿起手机记录下来,但其实也没有太 Special,这些照片你想与别人分享,但好像又不够精致到值得发个朋友圈或 Instagram,于是就只能默默地住在相册里。我有时会想,这些照片它们会不会也想有一个出口呢?

「避风塘」的概念和这些照片好像挺契合的,带着这个想法,我决定让 before.town 成为这些「不够精致」但充满生活气息的照片的避风港。

它不是一个追求完美构图和滤镜的平台,更像是一个数字化的「避风塘」,让那些在主流社交媒体中找不到位置的照片,能够在这里找到一个安静的角落。你可以在这里分享你随手拍下的街角风景、一杯咖啡的特写、或者只是一个不经意的瞬间。它们可能没有华丽的辞藻来描述,也不需要精心的排版,但它们都带着你生活的温度和独特的视角。

最后,欢迎来避风塘分享你的日常 🙃。

做了一个小游戏:笔画猜成语

前几天在看跑男,有一个游戏环节是这样的:嘉宾通过努力得到一个笔画,目标文字中如果包含该笔画就会出现。感觉挺有意思的,对它稍加改造,于是就有了这个小游戏:笔画猜成语

游戏机制是这样的:

  • 初始显示 20% 的笔画作为提示
  • 每隔一分钟会多 10% 的笔画,最多显示 50% 的笔画
  • 总共有 5 次猜测机会
  • 新题每日更新

和周围的人玩了下,还是挺有乐趣的。如果你也感兴趣的话,可以在这里体验哦。

Vibe Coding 一段时间后的感受

TL;DR

  • 工欲善其事,必先利其器:选对工具至关重要,目前 Claude Code (CC) 在代码理解和生成质量上相比 Cursor 表现更优。
  • 人机协同新范式:Vibe Coding 能极大提升开发效率,但需要掌握新的协作技巧,否则可能事倍功半。
  • 能力圈的重塑:AI Agent 的崛起正在改变传统的编程模式,迫使程序员更新自己的核心能力圈,将重心从具体实现转移到更高层次的架构设计和战略规划上。

最近,我通过 Vibe Coding 的方式完成了三个个人项目:

  • 五子棋:一个功能完善的网页五子棋游戏。
  • 笔画猜成语:一个根据汉字笔画顺序猜成语的互动游戏。
  • 歌曲转视频脚本:一个能自动为日文歌曲的歌词和单词注音并翻译,最终生成视频的学习工具。

在开发「五子棋」时,由于初次尝试 Vibe Coding,经验不足,踩了不少坑,但最终坚持了下来,算是摸到了一些门路。有了此前的经验,做「笔画猜成语」时更加得心应手,效率也大幅提升,大约只花了 3 天时间,就将一个模糊的想法变成了一个功能完整的 Web App。而「歌曲转视频」项目,更是在 2 个多小时内就产出了可运行的核心脚本。

Vibe Coding 工具的选择

我最初使用 Cursor,但在看到越来越多的人推荐 Claude Code(以下简称 CC)后,决定一试,结果确实令人惊喜。我的习惯是在 Cursor 的终端里打开 CC,这样 CC 可以直接访问当前项目的文件上下文(当然,在独立的终端里使用也完全可行)。

通过两个简单的例子就能看出 CC 与 Cursor 的能力差异:

  1. 重构组件属性:我让 Cursor 移除一个 React 组件中未使用的属性。它的做法是给这个属性一个别名,在前面加上下划线 _,以此「欺骗」编译器,绕过检查。当我追问该属性是否无用时,它才承认并将其删除,但却忽略了检查调用该组件的其他地方,工作只完成了一半。我撤销修改后,将同样的指令交给 CC,它一次性就完美地完成了任务,干净利落。

  2. 代码结构优化:在开发五子棋的禁手功能(黑棋不能走出三三、四四或长连)时,我有一个核心的协调文件 gomoku-ai.ts。Cursor 的做法是直接将禁手判断的复杂逻辑堆砌到这个协调文件中。而 CC 则展现了更优秀的设计能力,它创建了一个独立的 forbidden-move.ts 文件,专门用于封装所有禁手检测的逻辑,再由 gomoku-ai.ts 进行统一调度,使得代码结构更清晰,职责更分明。

类似的例子还有很多,这让我越来越依赖 CC。Cursor 更像一个初级程序员,优先考虑完成当前任务,对代码质量、复杂度和可维护性的考量不足,倾向于「能加代码就不改代码」。而 CC 在理解意图、分析代码结构以及构建更优代码方面表现更强。当然,它也并非完美,有时也会在「奋战」十分钟后报告任务完成,但却没有解决问题。

Vibe Coding 实用技巧

我喜欢将 Coding Agent 比作一匹马,这能强化我们对其「驾驭」和「驯服」的过程。不同的马有不同的脾性与能力(所以摸清每个 Agent 的能力圈很重要),选择一匹既强大又易于驾驭的马,才能事半功倍。以下是我总结的一些通用技巧:

1. 精准的目标分解

在开发五子棋 Web App 时,我犯了一个错误。在 v0.dev 上设计好页面后,就把整个实现任务直接丢给了 Agent,以为五子棋算法早已成熟,AI 肯定了然于胸,加上最终的目标界面,应该很快就能做完,结果却不尽人意。

我耐着性子,以产品经理和 QA 的身份不断提出修改意见。噩梦从此开始:AI 修复一个 Bug 的同时,往往会引入新的 Bug,或是让之前修复过的问题重现,陷入「按下葫芦起了瓢」的循环。

检查代码后我发现,AI(当时使用的还是 Cursor) 写的算法冗长复杂、职责不清,上百个测试用例中充斥着大量敷衍了事的断言(比如只检查返回值是不是布尔类型,而不关心是 true 还是 false)。基于这样的代码迭代无异于在沙地上盖楼。

最终,我决定放弃原有算法,从一个成熟的开源项目中剥离出经过验证的五子棋算法,然后让 CC 将其整合进现有项目——相当于给汽车换了个引擎,问题迎刃而解。

吸取教训后,在做「笔画猜成语」时,我首先对目标进行了细致的拆解。

如图所示,页面的核心是成语笔画展示区。这意味着我需要一个组件,它能接受一个汉字和对应的笔画序号,并使用 SVG 数据将其绘制出来。我的第一个子任务就是寻找一个合适的汉字笔画库,并让 Agent 基于这个库构建出核心组件。

任务分解还能带来意想不到的好处:掌控感、大局观和节奏感

  • 掌控感:每个任务都足够小,Review 起来更轻松,可以始终保持对代码的掌控。
  • 大局观:你清楚每个子任务在整个项目中的位置,对整体进度了如指掌。
  • 节奏感:一个接一个完成任务会带来持续的正反馈,推动项目稳步前进。

2. 提供关键输入(Input)和认真审查(Review)

Agent 并不总能选择最佳实现路径,如果不加干预,可能会在错误的方向上浪费大量时间和 Token。例如,在生成带注音和翻译的歌词图片时,我希望实现这样的效果:

CC 最初的方案是使用 sharp 配合 canvas 绘制,这不仅实现复杂,效果也未必理想。此时就需要人为干预,我给出的策略是:利用无头浏览器渲染一个包含 ruby 标签(HTML 原生支持注音)的页面,然后对该页面进行截图,这个方案更简单、效果也更好。

Review 同样至关重要,尤其是在商业项目中。在做「笔画猜成语」时,我要求每天提供一个固定的新成语。Agent 实现时用了一个简单的哈希算法,导致每天的成语都非常相近(如昨天是「坐享其成」,今天是「坐井观天」)。如果没 Review,这个问题可能只有上线后才能发现。我让它改进,它又手动实现了一个伪随机算法。我再次给出 Input,让它使用 seedrandom 这个成熟的库来确保高质量的伪随机性。

3. 及时干预

如果 CC 尝试了 5 次左右仍未完成任务,或者在执行一个明确的任务时消耗了大量时间却最终失败,就需要立即干预。这通常意味着任务粒度过粗、描述不清、AI 的策略有问题或者当前项目复杂度太高。 如果任务分解地很好,这种情况发生的概率不高,但一旦发生,很有可能会把之前节省下来的时间都还回去···。

4. 善用计划模式(Plan Mode)

CC 支持一个非常实用的「计划模式」。在执行一个有难度的任务前,可以让它先拟定一份行动计划。只有在你确认计划可行后,它才会开始实施,这极大地提高了复杂任务的成功率。

5. 拥抱软件开发的最佳实践

过去,我们常因耗时费力而忽略一些重要的开发实践,如编写测试或使用 Storybook。但现在,Agent 以其不知疲倦的特性,让这些「最佳实践」的落地变得轻而易举。测试驱动开发(TDD)等过去只存在于书本中的理念,现在完全可以在 Agent 的协助下融入日常开发流程。

6. Agent 的一些通病

  • 需求理解偏差:不太会主动确认需求,往往按自己的理解埋头就做。
  • 有「偷懒」倾向:为了完成任务可能会走捷径,例如引入 Magic Number、硬编码等。
  • 代码审美有限:对复杂度和代码整洁度的认知不足,尽管 CC 已比多数同类工具要好。

Vibe Coding 带来了什么

Someday -> Today

「日文歌曲转成带翻译的视频」这个 Project 我其实酝酿了蛮久的,如何实现也有大概的思路,但一想到要手动去实现里面的代码,要去熟悉 ffmpeg 的调用,还是会下意识地去拖延。但 CC 大大降低了我创建这个项目的阻力,虽然还是需要花一点时间描述清楚这个项目,对其进行分解,但相比自己去实现已经方便了很多。

我还记得当时是 10 点左右,我想测试下「笔画猜成语」在 0 点时能否正常切换到新一天的成语,既然还有两个小时,不如就来做这个项目吧,结果真的在 12 点多,就把它做出来了。

这便是 AI Agent 的魅力,它将那些看似遥不可及的「Someday」,变成了触手可及的「Today」。 那些曾经因为技术门槛、因为预想中的繁琐而搁置的想法,如今有了一个快速验证的通道。从一个模糊的概念到看得见、摸得着、能分享给朋友的作品。

程序员能力圈的重塑

这个访谈视频中,极限编程(XP)之父、《测试驱动开发》作者 Kent Beck,一位拥有 52 年编程经验的传奇程序员,分享了他对 AI 时代程序员能力转变的看法。他将 AI 编程工具比作一个「难以预测的精灵」 [06:44],它能实现你的愿望,但结果未必如你所想。

他的一段话精辟地总结了 Vibe Coding 「迫使」程序员做出的改变[01:12:42]:

I had this tweet two years ago where I said “90% of my skills just went to zero dollars and 10% of my skills just went up 1000x”. And this is exactly what I’m talking about - having a vision, being able to set milestones towards that vision, keeping track of a design to maintain or control the levels of complexity as you go forward. Those are hugely leveraged skills now compared to knowing where to put the ampersands and the stars and the brackets in Rust.

我两年前的一条推里说「我的 90% 的技能价值归零,而 10% 的技能价值增长了 1000 倍」。这正是我所说的——拥有一个愿景,能够为这个愿景设定里程碑,并在前进过程中跟踪设计以控制复杂性。与知道在 Rust 中如何放置符号和括号相比,这些才是现在被极度放大的核心技能。

这里的「迫使」是积极的。Agent 的出现,将程序员从繁琐的具体代码实现中解放出来,让我们能像 Kent Beck 所说的那样,去思考「真正宏大的想法」  [01:13:36]。我们的核心竞争力不再是写代码的速度或对语言语法的熟练度,而是产品感、架构能力、任务拆解能力和战略眼光

编程的本质正在回归——将复杂的问题,分解成计算机可以理解并执行的简单步骤。只不过这一次,我们操作的「计算机」拥有了更强的理解力和执行力。这要求我们站得更高,看得更远,专注于创造真正的价值。

科萨人和祖鲁人

昨晚在看特雷弗·诺亚的《天生有罪》,开篇的一段话是这样的:

其中最明显的裂隙存在于南非两大主要的部落之间,祖鲁和科萨。祖鲁人是公认的战士。他们很骄傲,会拼尽全力去战斗。殖民者的军队入侵时,祖鲁人拿着长矛与盾牌就冲上了战场,和对面拿着枪支弹药的敌人血拼。上千名祖鲁人死在了战场上,但是他们从未停止过战斗。和祖鲁人截然不同的是,科萨人一直以头脑灵活而自豪。我的母亲是科萨人。纳尔逊·曼德拉也是科萨人。科萨人也与白人进行了漫长的战争,但是在对手武器装备遥遥领先的情况下,科萨人感受到了武力战争的徒劳,于是一些科萨首领采取了一种更机智的手段。‘不论我们喜不喜欢,这些白人都已经在这儿了,’他们说,‘我们来看看他们都有什么长处是我们可以用得上的。与其抵抗他们的语言,不如我们来学学英语。这样我们就能明白他们在说什么,然后迫使他们与我们谈判。’

我忽然想到,这段历史的镜像,还挺像我们与「智能手机」的关系。智能手机,就像当年那些无法阻挡的「白人」一样,携带着压倒性的技术优势,闯入了我们的生活。它强大、迷人,以「便利」和「连接」为名,迅速重塑了世界的样貌。

起初,我们都曾为之兴奋和着迷。它打破了信息壁垒,延展了我们的感官,赋予了我们前所未有的可能性。但慢慢的,我们也感受到了「被殖民」的代价:注意力被无情收割,时间被碎片化,深度思考的能力逐渐退化,真实的人际关系被虚拟互动所稀释。 我们开始焦虑、疲惫,发现自己非但没有成为生活的主人,反而沦为了算法的奴隶。

面对这种困境,我不自觉地成为了「祖鲁人」:感受到了威胁,于是选择了直接对抗。这种对抗体现在行为上,是尝试各种「数字极简主义」,卸载App,甚至想换回功能机;体现在心态上,则是对智能手机持一种否定和批判的态度,视其为洪水猛兽,认为它是一切问题的根源。这种「战斗」的姿态虽然悲壮,但收效甚微,因为它违背了我们生活于世的现实。更重要的是,这种全然的抵抗,也让我关闭了探索其正面潜能的大门,比如,我因此失去了在它上面开发App、创造价值的兴趣。

科萨人的智慧给了我新的启示。当物理上的抗争显得徒劳,他们没有选择玉石俱焚,而是转向了一种更高级的策略:理解、学习、为我所用,最终与之「谈判」。

现在,我想成为一名数字时代的「科萨人」。这意味着我需要从根本上转变我的 Mindset:

  1. 接受现实,放弃幻想: 首先,坦然承认智能手机已经成为我们社会和生活的基础设施,它不会消失,只会在形态和功能上不断进化。指望通过彻底的「断舍离」来一劳永逸地解决问题,是一种不切实际的幻想。

  2. 「学习它的语言」: 「科萨人」选择学习英语,我们则需要去理解智能手机背后的运行逻辑。这不只是学习如何操作App,更是要去了解推荐算法如何工作,通知系统如何设计来吸引你的注意力,商业模式如何依赖你的使用时长。只有理解了它的「语法」,才能识破那些让你无意识沉迷的「圈套」,从被动的接受者,转变为清醒的观察者。

  3. 利用它的长处: 智能手机并非纯粹的「恶」。它是极其强大的工具,关键在于为谁所用。我们可以用它来学习新知识、管理健康、高效工作、进行深度创作、维系远方的亲情。关键在于,你要主动定义你使用它的目的,而不是被它预设的功能所定义。 这需要我们从「消费内容」的心态,转向「运用工具」的心态。

  4. 划定边界,与之「谈判」: 接受不等于放任。「科萨策略」是用对方的规则来与之周旋,为自己争取最大的利益。我们可以主动设计自己的数字环境:关闭非必要通知,设定App的使用时限,规划固定的「无手机时间」,策划能带来真实满足感的线下活动等等。这不是在「抵抗」手机,而是在与它「谈判」,重新夺回生活的主导权。

这里最重要的转变在于责任归属。如果一个人因为饮食过量而损害了健康,我们会认为是这个人的自制力出了问题,而不是食物的错。同样,如果一个人因为过度使用手机而让自己偏离了理想的人生轨道,这终究是Ta需要面对和解决的个人课题,而非手机的原罪。

成为数字时代的「科萨人」,意味着不再将自己置于科技的对立面,进行一场注定失败的消耗战。相反,选择直面这个强大的「新物种」,理解它、驯化它,最终让它服务于我们真正渴望成为的那个「更好的自己」。这,或许才是我们在这个时代,与科技共存的最佳路径。

LimTube

萌生出做这个 App 的念头源于一个非常朴素的需求:我想在干活时,放一些舒服的背景音乐。这个需求有很多现成的解决方案,但没有太满意的。我希望它是

  • 一个 Mac App。
  • 有丰富的曲库可选(因为很容易听腻)。
  • 界面简洁,功能够用,审美在线。

论曲库的话,YouTube 是最全的,Lofi、钢琴曲、Jazz 等等,只要愿意花点时间,总能找到满意的,听腻了的话,也很容易找到新的。但我不想打开 YouTube,一个是不够方便,另外就是干扰因素太多,还容易被推荐视频吸引而掉进兔子洞。

于是我就想,不如做一个可以播放 YouTube Playlist 的 Mac App 吧,这就是 LimTube 这个 Mac App 的创作初衷。

既然能添加 Playlist 了,我也会顺手把 YouTube 上感兴趣的 List 加进来,省的每次都要打开 YouTube。那既然 Playlist 可以添加,Channels 不加好像也说不过去,于是就变成了这样。

自己用了一段时间,感觉还是挺方便的,如果你也有类似的需求,欢迎使用和反馈。

Email

前几天浏览Sivers博客Now 页面时,发现这位我长期关注的博主因为被上海吸引而开始学习中文。作为读者,我试着发了封邮件:先是表达欣赏,继而提议成为他的中文学习伙伴。没想到很快就收到回信——他详细说明了学习进度,还分享了自己的中文名字。随后的邮件往来中,我们交换了更多个人信息。

这个简单的举动,让我与千里之外的人建立了真实连接。在社交网络触手可及的时代,这看似平常,但电子邮件带来的体验还是不太一样:没有信息洪流,没有算法干预,没有无止境的推送诱惑。就像在数字丛林中意外发现的一条幽静小径,这条由最原始通信协议铺就的道路上,文字在发件箱与收件箱间静静流淌,每个字节都承载着明确意图。

当光标在邮件正文框规律闪烁时,你能清晰听见自己的思考节奏——宛如钢笔在信纸上沙沙作响的往昔。这种交流自带庄严的仪式感:点击发送后,你不会焦虑地刷新收件箱,而是像投递老式邮筒般,任由时间在对话间自然发酵。

电子邮件则像 一壶需要静待滴滤的手冲咖啡,虽然节奏迥异,却各自诠释着数字时代的沟通美学。。当世界将人际关系简化为「点赞」,「转发」的标准化货币时,一封邮件的抵达,依然如同中世纪商船运来的香料,让收件人嗅到遥远大陆的真实气息。

如果你也向往这种纯粹的文字交流,欢迎来信。每封邮件我都会认真阅读和回复。我的邮箱地址是: hi@limboy.me

冷水澡

断断续续从不同渠道听说过洗冷水澡,以及带来的好处,并没太在意:热水澡那么舒服,为什么要折磨自己呢。直到有一次心血来潮试了一下:打开冷水,不给自己思考时间,迎上去。头 1 分钟会有点挑战,3 分钟后,基本就适应了。后来又发现一个小技巧,可以帮助克服最开始的不适应:洗头。一方面可以避免冷水全部浇在身上,另一方面也可以分散注意力,等头洗完后,身体也差不多适应了。

我自己洗完冷水澡的感受是头脑更清醒了,身体会微微发热还蛮舒服的(更具体的洗冷水澡的好处,可以问下大语言模型)。如果把冷水澡比做「难而正确的事情」,热水澡比做「容易但无长期收益的事情」,生活中的很多选择都如同在冷热水之间徘徊。热水澡是即刻的温柔乡,让人沉溺于熟悉的舒适区;而冷水澡则是清醒剂,用短暂的刺痛换来长久的活力。

  • 想画画?拿起笔,先画个 5 分钟,画什么不重要,重要的是这 5 分钟你在画画。
  • 工作内容让你焦虑?啥都别想,先做个 5 分钟,可能会发现,好像也就那样。
  • 打开手机想看收藏的文章,但又怕忍不住去刷社交媒体、短视频 App?强迫自己先看个 5 分钟,可能看着看着就看进去了。

很多时候,我们知道哪些事情应该多做,哪些事情应该少做,如果能借助「啥也不想,先来个 5 分钟」的劲儿,或许能多做一些正确的事,成为更好的自己。

PS:相比热水澡,冷水澡的搓灰体验差了一大截···

关于 AI 辅助编程的一些实践和思考

前些日子尝试借助 Cursor(主要是 claude-sonnet-4) 写一个五子棋 Web App,想着这是一个挺成熟的项目,应该不太需要干预,直接 Vibe Coding(依靠 LLM 生成代码) 应该就能搞定。一开始挺顺利的,界面经过几轮 Prompt 后,基本符合需求,也可以下棋,但在优化五子棋智能时遇到了严重的问题。我扮演 QA 的角色,不断地下棋,然后反馈五子棋算法的错误落子,AI Code Assistant(以下简称 ACA) 收到反馈后,总是会回复:我找到问题了!我解决问题了!完美!诸如此类,我还真就信了。在尝试了大约 50 次后,我发现事情不对,它好像没有真正地解决问题,只是解决了我那次报给它的问题,而且代码也变得异常臃肿,根本没法维护。

后来我就换了一个思路,先实现一个最最基础的五子棋策略,然后询问多个 AI,把代码发给它们,让它们提供优化思路,再把这些 AI 提到的共通点收集起来,让 ACA 每次只针对其中的一点进行优化,并且让它写对应的测试。如此经过几轮迭代下来,才终于慢慢地提升了五子棋的智能,代码也有了可维护性。

本以为一天可以搞定的需求,结果花了近四天,才基本完工,这其中走了不少弯路,正好总结下自己对于 AI-Assisted Coding(AI 辅助编程,以下简称 AAC) 的思考。

先说结论,我认为:

  • 只靠 AAC 是无法做出有竞争力的产品的。
  • AAC 是一个 multiplier,要么事半功倍,要么事倍功半。
  • 「将 AAC 的价值最大化」,是开发者的必选项。

AAC 的本质是:提供了一个以完成当前任务为最高优先级的初级程序员。这里的 trick 就在于「当前任务」,假设你有一个机器人,然后跟它说:房间太乱了,打扫干净。它可能会:

  • 发现桌上的东西很多,如果全部收拾掉,并按它们的属性放到合适的位置会涉及到很大的工作量,且不一定做得好,那么它的解决方案可能是在桌上盖一层毯子,这样看着不乱了,符合「干净」的需求。
  • 发现角落里有一双鞋,看起来有点旧,又不知道放哪里,那就索性扔掉,虽然这可能是你最喜欢的一双鞋。
  • 一些散落的衣服本来应该挂起来,但它可能会叠起来放进抽屉里。

ACA 也一样,它没有长期目标,也没有「代码质量」、「可维护性」等内在驱动力,它只关心如何最直接地满足当前 Prompt。针对一个任务它可能会:

  • 走捷径。如加 if 判断,或引入 Magic Number,看起来好像解决了问题,但其实是在堆积技术债。这个倾向在写测试时体现的淋漓尽致。如果你的 prompt 是:为本次代码改动编写测试。那么它很可能会写好几个测试,结果也都通过了,但测试本身非常敷衍。
  • 新增非必要的复杂度。它会尝试在现有结构上打补丁,而不是从根本上优化或简化。这可能是因为「增加代码」是解决问题最直接的方式,而「重构」需要更深层次的理解和抽象能力。这也意味着 AI 可能引入冗余代码、重复逻辑,甚至不必要的依赖。
  • 进入死胡同。就好像你给一个 prompt:让这辆车飞起来。那么它会想各种办法,对车进行改造,但每次都失败。它不知道这件事几乎不可能,也不会揣测你背后的意图,跟你讨论其他的可能性。

正是因为这些特性,ACA 的表现看起来像是初级程序员。它们缺少创造性思考和大局观,能生成「看起来合理」的代码,但逻辑正确性、架构合理性、长期可维护性需要人工把关。所以ACA 不是一个完全独立的开发者,它是一个高级工具。如果你只是提需求和报 Bug,会发现它可能会为了解决 Bug 而引入新的 Bug,或者为了实现某个功能而增加不必要的复杂度。AI 并不真正理解代码,它只是模拟理解,如果你告诉它错了,它会立刻道歉并尝试给出另一个答案,但这不代表它真的理解了错误。

但我们可以利用它「以完成当前任务为最高优先级」的这个特点,来发挥它的价值。这就需要我们的 prompt 指令清晰,目标明确,且足够小。比如「实现登录功能」,这个 prompt 太大,太模糊。把它分解成:

  • 设计AuthService协议
  • 实现MockAuthService
  • 实现RealAuthService的网络请求
  • 编写LoginViewModel处理逻辑
  • 编写LoginView UI
  • 编写登录成功/失败的集成测试

然后按顺序提交给 ACA,效果会好得多。这个是 Cloudflare 的工程师通过 Claude 写的代码,可以看下他们给 Claude 的 prompt:

prompt: Please write tests for this library using vitest. The tests should use a mock or fake KV namespace for storage. Be sure to study README.md and storage-schema.md in addition to oauth-provider.ts to fully understand the functionality. Try to cover all the important logic.

Claude initially wrote a separate mock library.

prompt: Let's just put the whole test including mocks in one file.

Claude spent several minutes thinking and produced the test. It failed immediately due to `cloudflare:workers` not being available.

prompt: Looks like for this test to run under node, we need to mock out the `cloudflare:workers` module. We just need to define the `WorkerEntrypoint` class. Can you do that?

Claude did this. Yay.

Several tests are still failing, but they do run. Will debug in separate commits.

由此可见,prompt 要明确:

  • 需要达成的目的
  • 能够使用的工具
  • 应该遵循的规范
  • 需要考虑的要素

必要的话,再提供一些示例。通常需要几轮迭代才能完成一个小 feature 或修复一个 bug。每一轮 prompt,ACA 都会输出它的思考和对应的代码,不要在这个期间切换到社交媒体上刷新闻,这样不仅不容易进入 Flow 状态,也容易忽略 AI 犯的错。如果发现 ACA 无法正确地执行任务,要找到其中的原因或提供自己的思考,反馈给它,这样才能打开思路,避免进入死胡同。一个好的实践是,在把 Prompt 给 ACA 之前,自己先思考下:如果是我来做,大概会怎么实现,然后跟 ACA 的输出做对比。

有了 Prompt 的最佳实践后,接下来要做的就是如何生成这些 Prompt,这个就需要用到高阶程序员的技能了:架构设计、良好的编程习惯、定位问题和目标分解。一个好的架构是基础,它让每个模块职责清晰、数据可以顺畅流转、便于新增 Feature、便于定位 Bug。好的编程习惯可以让代码更容易维护。好的目标分解能力和定位问题能力,可以将产品经理的 Feature、QA 发现的 Bug、技术需求等转化为高质量的 Prompt,借助 ACA 的能力,得到最终想要的结果。

有了高质量的 Prompt 还不够,因为 ACA 依旧可能犯错,因此代码 Review 必不可少。值得考虑的点有:

  • 是否需要写单元测试,如果是,需要覆盖哪些场景。
  • 是否考虑了边界条件、错误处理、性能、可读性、可维护性。
  • 是否符合代码规范。
  • 是否有「代码异味」,如魔数、深层嵌套、大量 if、重复代码、命名含糊等。

所以,有了 ACA 并不意味着学习编程基础知识变得不那么重要,程序员的经验变得无足轻重,或者程序员的技能会被 AI 完全取代,恰恰相反,它需要你掌握高阶的编程技能,善于与 ACA 沟通,才能让开发效率事半功倍。

采用 AAC 后,开发范式会发生转变,开发者的角色从以「写代码」为主,慢慢转向「设计架构、分解任务、优化 Prompt、Review 代码」。越早适应这种转变,强迫自己提升对应的能力,越能取得优势。

One More Thing:精通市面上最强的 ACA(如 Cursor),结合最强的 AI 模型,可以大幅提升开发效率。

杀死一只知更鸟

这本书相信大家都有听说过,我也是拖拖拉拉,直到最近才读完。书的主题是种族歧视,但又不止于此,也会涉及到家庭、教育、社会等方面的问题。书中的故事发生在美国南方的一个小镇,主人公是一个律师,他接手了一个案子,为一位黑人辩护。现在看来不觉得有什么,但当时的美国社会(尤其是南方)是很敏感的,黑人和白人之间的界限非常明确,几乎不可逾越。就像拿锤子去砸一面墙,一锤子下去,墙可能没什么变化,但你知道这一砸一定松动了墙的某些结构。

经典的书就是有能力把沉重的话题用想对轻松的方式呈现出来。这本书就是这样,虽然讲的是理我们较远的种族歧视,但是书中的人物形象、情节安排都很有趣。尤其是通过孩子们的视角来观察和讲述这个故事,更增添了一份天真和纯粹。书中的一些情节非常有画面感,比如斯库特躺在轮胎里,滚到了怪人布·拉德利家的院子;从树洞接受到了布拉德留下的种种礼物;用钓鱼竿给布·拉德利写信;自编、自导、自演跟拉德利有关的角色扮演游戏等等。

小女孩的父亲,阿提克斯·芬奇,是一位正直、善良、有原则的律师,他不仅在法庭上为黑人辩护,也在日常生活中身体力行地教导孩子们什么是正义和公平。他没有用空洞的说教,而是用自己的行动给孩子们树立了榜样,让他们在潜移默化中理解了人性的复杂和社会的残酷。

书中另一个令人印象深刻的角色是「怪人」拉德利。他被小镇居民视为异类,被孩子们当成鬼怪,但随着故事的推进,你能了解到他内心的善良和孤独。他就像一只被误解的知更鸟。而「杀死一只知更鸟」的隐喻,也正是指代了这种对无辜者的伤害,以及社会对弱势群体的偏见和歧视。

自深深处

想象你与一个渣男/女坠入爱河,对方不仅掏空了你的金库,极大地败坏了你的名声(虽然是间接地),还害你坐了两年牢,现在你在牢里要给 Ta 写封信,你会怎么写,基调是怎样的?

这本《自深深处》(from the depth) 就是王尔德在狱中给波西写的信,你能完全感受到他对文字那炉火纯青的驾驭能力(虽然中间隔了一层翻译)以及其中流淌着的真切情感。大概有剖析、反思和哲思这几部分。

剖析:你(波西)是一个怎样的人(虚荣、浮浅、心怀怨恨、贪图享乐,但与我又有不可抗拒的吸引力);我是一个怎样的人(视艺术为至高存在,享受与志同道合者的交谈以及由此催生的友谊)。

反思:为什么自己会从神坛跌落到身败名裂的境地(对自己掌控力的过度自信,对你的过度溺爱);为什么明知你的存在会切断自己与艺术的连接又无法舍你而去(你身上有一种不可抗拒的魅力,自己的软弱导致无法割舍)。

哲思:关于爱(恨就像杂草很容易就长出来了,而爱则像蝴蝶兰,需要精心打理才能存活长大,要学会爱);关于痛苦(所有的痛苦都有意义,提供了新的思考点,是更完整的体验);关于做自己(一个人必须完全是、绝对是他自己,才会过基督那样的生活)。

这本书可以让你对王尔德有更全面的了解,同时书中的一些思考也能带来触动和碰撞,值得一读。

足利女童连续失踪事件

作者清水洁绝非凡人:正义感、专业素养(重视现场和采访)、很强的换位思考(政治嗅觉)和共情能力、杰出的刑侦和推理能力、做事非常有条理、擅长写作,最后也是最重要的:一根筋死磕的精神。

这样的人的存在,既是幸运,也是不幸。说是幸运,因为他确实一定程度上撼动了日本,这除了自身极强的素养外,离不开支持他的上层和可以发声的媒体。说是不幸,因为这样的人太少了,能带来的影响毕竟有限。

但只要媒体还没有彻底腐化,就还有希望。

桶川跟踪狂杀人事件

上一次酣畅淋漓地看完一本第一人称纪实文学,还是杨柳松的 北方的空地,现在想想这两本书的主人公还有那么点相似:

  • 都在挑战一个极其困难的任务
  • 有很大的勇气
  • 有大智慧又非常细心
  • 有很强的韧性

不同的是,杨柳松是一个人在战斗,面对的是极端的自然环境,清水洁是孤勇者,面对的是绝望的社会环境,但得到了被他这股劲儿感染的人的帮助,让真相一步步浮出水面,让恶行得以被昭示。

跟 GPT 聊了下这本书(主要是它在输出),分析地挺全面的。 https://chatgpt.com/share/670d35fe-e694-800f-9be9-65ecd63316ce

最后,这本书的出版本身就说明了一些问题。

我与地坛

第一次接触到史铁生的名字,是在中学的语文课本上,于是「史铁生」就与背诵、考试产生了联系,这一耽误就是几十年,好在最终没有错过。

史铁生跟我们一样,也有七情六欲,也有悲欢离合,跟我们不一样的是他在21岁那年就双腿瘫痪,30岁肾衰竭,靠两天一次的透析续命。没有人生来就准备好了迎接苦难,尤其是在最年轻气盛之时。

好在有懂他又爱他的母亲,有在他低落时带来欢声笑语、鼓励他坚持下去的朋友,有拂动心弦却又被拦阻的爱情。当然还有地坛。

自从那个下午我无意中进了这个园子,就再没长久地离开过它。我一下子就理解了它的意图。正如我在一篇小说中所说的:“在人口密集的城市里,有这样一个宁静的去处,像是上帝的苦心安排。”

一直担心,一个被苦难「眷顾」的人,他写的文字也会很苦,以至于除了那份苦,品不出其他的滋味。但史铁生的文字不一样,平实又细腻,可以放在枕边,在夜深人静之时翻看。他会描写当时的挣扎,但不「卖苦」。

一个人可以很细腻,但能把这份细腻表述出来,则又是另一回事,史铁生同时具备了这两个特质。书中有很多描写他母亲的片段,每每读来,都感觉心里一颤。

上帝焊死了史铁生的一扇门,但也打开了他的精神世界,看他的文字,就像进入了他精心构建的花园,你会忘了作者是一个双腿瘫痪、靠着透析维生的人,只会惊叹于花园的鬼斧神工。

借着他的文字,也能一窥特殊年代下普通人的生活状态,我没有经历过,但能共情。觉得生活艰难时,想想那个年代,还能获得些慰藉。

感谢史铁生,感谢史铁生的作品,愿你在天堂与家人团聚。如果有来生,愿你的屋前有一片空地,种两棵树,一棵合欢,一棵海棠。

❌