普通视图

发现新文章,点击刷新页面。
今天 — 2025年6月29日Limboy

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

2025年6月29日 08:00

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

游戏机制是这样的:

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

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

昨天 — 2025年6月28日Limboy

Vibe Coding 一段时间后的感受

2025年6月30日 08:00

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]。我们的核心竞争力不再是写代码的速度或对语言语法的熟练度,而是产品感、架构能力、任务拆解能力和战略眼光

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

昨天以前Limboy

科萨人和祖鲁人

2025年6月23日 08:00

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

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

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

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

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

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

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

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

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

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

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

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

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

LimTube

2025年6月23日 08:00

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

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

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

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

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

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

Email

2025年6月21日 08:00

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

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

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

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

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

❌
❌