Refactoring English: Month 12

Michael Lynch

《重构英语》第 12 个月

一句话总结

行吧,那我就自己做一个分享宝宝照片的应用。

亮点

  • 我在开发一款游戏,用来预测哪些帖子能登上 Hacker News 首页。
  • 我正在赌气开发一个家庭照片分享应用。
  • 我切换到了以键盘为主的窗口管理器。

目标评分

每月月初,我都会宣布想要完成的目标。以下是我对照这些目标的成绩:

发布两个新的书籍章节

  • 结果:发布了一个新章节
  • 评分:C

我在“设计文档”这一章卡住了。这一章有很多我想讲的内容,但其中一些我很难表达清楚,也难以决定哪些内容应该写进书里。

问题的一部分在于这一章太长了,想一口气完成会让人望而生畏。我的新计划是把这一章拆成更小的部分,逐个攻克。我觉得这是我最后一个“难啃”的章节了,因为对剩下章节想写什么,我已经更有把握。

联系 10 位读者

  • 结果:我只联系了两位读者(有一位回复了)。
  • 评分:D

这件事我一直在拖延,尽管我很享受做这件事,也能得到有用的反馈。我不断把更多事务性工作自动化,希望减少起步阻力能促使我更常去做。

制作一个能把人带到《重构英语》网站的工具或博客文章

  • 结果:发布了《What Makes the Intro to Crafting Interpreters so Good?》一文
  • 评分:B

有 3,508 人阅读了这篇文章,所以在吸引新读者方面还算成功。我写的对象——Crafting Interpreters(《手写解释器》)的作者 Bob Nystrom(鲍勃·尼斯特罗姆),喜欢上了我的文章,这让我很欣慰。我想就算这篇文章扑街了,至少也能让 Bob Nystrom 知道我有多感激他的作品。

《重构英语》各项数据

指标2025 年 10 月2025 年 11 月变化
独立访客22,3987,608-14,790(-66%)
预购收入$570.75$1,018.48+$447.73(+78%)
赞助收入$48.25$48.25$0.00(0%)
总收入$619.00$1,066.73+$447.73(+72%)

11 月在访问量和销售方面是不错的一个月。访问量比 10 月略有下降,但仍是今年表现最强的月份之一。

我搞了一次黑色星期五 30% 折扣活动。我只向邮件列表上的读者宣传了这次折扣,因为我总觉得到处群发促销信息很奇怪。不过这次公告很成功,有 18 位顾客购买,总额达 $359.41。

Peter Spiess-Knaflzeitkapsl 的联合创始人,在一篇博客文章中引用了《重构英语》,这篇文章还登上了 Lobsters 第一名。我很高兴看到 Peter 的文章,因为我写这本书的一贯计划就是让它帮助读者写出成功的博客文章,并让他们对这本书满意到愿意推荐它。

《能不能上首页?》游戏

我刷 Hacker News 刷得太频繁了,以至于我觉得自己很擅长预测哪些帖子能登上首页,但我从来没有严格验证过这个想法。于是我做了一款游戏来测试我的准确率。

游戏会向我展示 Hacker News 上最新的提交,玩家要预测它们能否登上首页:

这款游戏最大的问题在于,一个帖子可能需要长达 24 小时才能登上首页。等 24 小时才能知道结果,游戏的乐趣就被消磨光了。

我试过改规则,改成预测文章能否在提交后的前 30 分钟内登上首页,但 30 分钟还是让人等得心焦。

我的新想法是:在帖子提交 10 分钟后做一个初步判定。根据帖子的发布时长、点赞数和评论数,我可以大致计算它有没有机会登上首页的概率。所以,如果你预测某个帖子会登上首页,但 10 分钟后它仍然没有点赞或评论,游戏会初步判定你猜错了,不过如果这个帖子在接下来的 24 小时里奇迹般地逆袭,你仍然可以拿回分数。

我想过做一个让玩家猜测历史帖子结果的游戏版本。这样我就能给出即时反馈,因为答案已经存在,但那样感觉没那么有趣,因为别人已经做过类似的游戏。而且,对于我希望这款游戏吸引的 HN 老玩家来说,历史数据会毁了游戏,因为你多少记得什么上过首页、什么没上过。

出于赌气开发一个免费的 TinyBeans 替代品

我和妻子去年有了第一个孩子,所以我们想要一种私下与家人分享宝宝照片的方式。一些朋友用过这类应用,但全都靠广告支撑。我讨厌公司在我孩子的照片上贴广告的想法,于是我去找其他选择。

当我发现 TinyBeans 时,我以为找到了赢家。他们有付费版可以关闭广告,而且隐私是他们宣传的主要卖点:完美!

然后,我开始使用 TinyBeans,结果到处都是广告。“购买我们的照片书!”“给我们更多个人信息!”

我刚才打开这个应用,为了看到自己孩子的照片,不得不关掉三个不同的广告。

我打开 TinyBeans 应用时,它会给我展示三个巨大的广告,尽管我是付费用户,而且之前已经把这些一模一样的广告关掉过几十次了。

而且事实证明,我的家人看到的广告比我还多,包括第三方服务的广告。下面是最近的一条,鼓动我的家人去投资某个骗人的 AI 公司:

TinyBeans 给我的家人发邮件时,会在我儿子的照片之间塞进这种垃圾广告。

付费档“无广告”的承诺只限于我和我妻子;TinyBeans 对我家的其他所有人进行广告和追加销售轰炸。

我很早就想抛弃 TinyBeans,但当时忙于新手父母的各种事情,没空去找新应用并把全家人迁移过去。所以每个月,我都心不甘情不愿地付给 TinyBeans 那 $9。

然后,黑色星期五来了。

TinyBeans 给我发了一封邮件,自夸没有用黑色星期五的促销信息塞满我的收件箱,因为所有促销都会放在应用里。

TinyBeans 给我发了一封毫无意义的邮件,来吹嘘自己不会用毫无意义的邮件塞满我的收件箱。

太棒了,一封祝贺你自己不会给我发多少邮件的邮件。

但这甚至都不是真的!TinyBeans 接着又给我发了四封邮件,让我去应用里查看黑色星期五的优惠:

在承诺不会用黑色星期五促销轰炸我之后,TinyBeans 给我发了五封黑色星期五促销邮件。

这彻底把我逼急了,现在我踏上了一条赌气之旅:自己做一个 TinyBeans 替代品,再也不给 TinyBeans 送钱了。

“那么,你想做一个分享宝宝照片的应用,理由是什么呢?”

我在 TinyBeans 里唯一在乎的功能是:

  • 我的家人可以浏览我上传的宝宝照片和视频。
  • 我的家人可以订阅,通过邮件接收新照片和视频。
  • 我的家人可以对照片发表评论或用表情符号回应。

这能有多难?20 个小时的开发工作?

反正 TinyBeans 的网页版和 Android 应用也很烂,我很乐意摆脱它们。而且由于体验主要以邮件为主,我可以用自己的应用替换 TinyBeans,而我的家人在迁移过程中不需要做任何事。

我不是要开一家公司与 TinyBeans 竞争。我只是想做一个能替代 TinyBeans 功能的 web 应用。

切换到 Awesome Window Manager

作为开发者,我的一个羞耻秘密是我很不擅长管理屏幕上的窗口。我用过度依赖鼠标来弥补,尽管那样又慢又低效。

去年,我从 Windows 换到了 Linux,并配了一台 49 英寸超宽显示器。Windows 是为像我这样鼠标用得飞起的用户设计的,而 Linux 桌面更侧重键盘操作,所以我键盘功底的欠缺开始找上门来。我会不停地开窗口却从不关闭,最后桌面上堆着 10 多个 VS Code 窗口、10 多个 Firefox 窗口,还有为了临时算个数而打开的 5 个计算器实例。它们全都堆在我桌面中央的一大堆里。

到那时,很明显我在浪费大量屏幕空间,还在浪费时间找窗口。我试了几种不同的窗口管理器,但总是遇到问题。比如锁屏功能用不了,或者无法用满显示器 5120x1440 的完整分辨率。

我见过的电脑操作最快的人是我的朋友 okay zed。我向他请教,他向我解释了他的窗口管理方法。他的策略是使用大量虚拟桌面,窗口在桌面内几乎总是全屏。他用的是 xmonad,但建议我试试 Awesome Window Manager。

我很喜欢 okay 的单一用途虚拟桌面理念,于是我围绕它创建了一个 Awesome 窗口管理器配置。这样,我有一个专门用于博客的桌面、一个专门用于书的桌面、一个用于邮件的桌面,等等。我尽量限制每个桌面只放 1-2 个窗口,但有时查资料时会拉出第三个或第四个。

以下是我的博客桌面,相当典型:一个 VS Code 窗口用于编辑,一个 Firefox 窗口用于查看效果,有时还有第二个 Firefox 窗口用来查东西:

默认的桌面布局模式我都不喜欢,所以我不得不自己写一个。它给每个窗口分配屏幕宽度的 25%,如果我打开超过四个窗口,它就把所有窗口压缩到能放下为止。我还可以用 Shift+Win+H 和 Shift+Win+L 手动扩展或收缩窗口。不过有时我会不小心把自己锁在系统外面,因为 Win+L 是我的锁屏快捷键。

基于使用 Awesome 的这几周,我的感受如下:

  • 我喜欢的
    • 促使我为每个桌面保持单一用途,以便更专注。
    • 促使我用键盘快捷键而不是鼠标点击来导航。
    • 不会像 Gnome 那样有 2% 的概率在挂起时崩溃。
  • 我不喜欢的
    • 一切都用 Lua 实现和配置,而我不懂这门语言。我全靠 LLM 帮我写配置。
    • 配置相当底层,所以你得自己编写逻辑来实现诸如填满视口又不溢出之类的事情。
    • 默认的桌面布局模式我都不喜欢,所以不得不自己写。
    • 文档全是纯文本,对于一个专门围绕图形设计的软件来说,这感觉很不寻常。
    • 如果你不小心定义了冲突的快捷键,Awesome 不会警告你。
    • 如果我在 Firefox 之外点击一个链接,有时它会在不在我当前桌面上的浏览器里加载。我猜它加载到了我最近碰过的那个 Firefox 窗口上。
  • 我还需要弄清楚的
    • 如何实现“scratchpad”功能。比如我想把密码管理器以浮动窗口形式拉出来,或者召唤计算器快速算个数,然后再关掉。
    • 如何在状态栏里加入更多小组件,比如网络连接状态和资源占用。

有趣的链接

在你的博客中缓存外部内容

我在 Mastodon 上和 LGUG2Z 聊过在博客里嵌入推文有多烦人。如果用户删掉了推文,我的文章里就会出现死内容。即使一切正常,我的读者也得从 Twitter 加载追踪器。我一直在用截图推文的方式绕过这个问题,但那是个很丑的解决方案。

我想在 Hugo(我用来搭建这个博客的静态站点生成器)里用类似 {<tweet id="12345">} 的 shortcode 来嵌入推文,然后 Hugo 可以抓取推文数据并存入版本控制,这样我就不用一直依赖 Twitter 了。

LGUG2Z 探索了这个想法并在他的 Zola 博客上实现了支持。他运行一个脚本,预先从外部来源(比如推文)一次性下载数据,之后就能在博客中嵌入内容,而不需要在博客构建时或读者访问时重新获取。

我尝试把 LGUG2Z 的方案移植到 Hugo,但它变得太复杂了。我写了一个独立脚本,从 Twitter 下载数据,然后用类似推文的界面来渲染它。普通文本推文还行,但一旦遇到带嵌入媒体或转发的推文,我就感觉自己在过于脆弱的地基上盖楼了。

Michael Stapelberg 使用 Immich 的经历

我以前把所有照片都存在 Google Photos 上。尽管有隐私方面的顾虑,Google Photos 还是比其他任何产品都好用太多,所以我捏着鼻子把所有照片都交给了他们。后来我对隐私变得更敏感,也更不信任 Google,于是不再向 Google Photos 上传新照片,但我一直没找到替代品。

我听说过不少关于 Immich 和 Ente 的好评,所以很高兴看到 Michael Stapelberg 这篇详细介绍他用 NixOS 搭建 Immich 服务器经历的文章。

Firefox 增强跟踪保护

Firefox 最近改进了它的增强跟踪保护,我之前都不知道有这个功能。我把它打开后,它拦截了 uBlock 放行的追踪器,而且没有出现误杀。

《有钱朋友,没钱朋友》

我刚发现了 2022 年的《Rich Friend, Poor Friend》和几周前的续篇。我非常认同“花钱请专业人士而不是找朋友帮忙”的做法(比如请搬家公司而不是找朋友帮忙搬家)。

我可能正处在曲线中最尴尬的一段:有钱到不好意思请朋友帮忙搬家,但还没富到有一间独立客房,方便留朋友住。

更多证据表明 Deel 雇了企业间谍

Deel 商业间谍事件在我所处的圈子里得到的关注出奇地少。

2025 年 3 月,Rippling 披露,他们发现自己的一名员工其实是竞争对手 Deel 派来的企业间谍。抓到这个间谍时,他冲进洗手间,试图把手机冲进马桶。

Rippling 在 11 月发布了一篇更新,称他们找到银行记录,显示 Deel 通过 Deel 首席运营官的妻子向间谍支付款项。巧的是,这位妻子曾是 Robinhood 的合规负责人,而 Robinhood 是另一家以道德败坏著称的公司。

作为一个不愉快的 Deel 前客户,我很高兴看到他们遭到报应。

收尾

完成了什么?

学到的教训

  • 快速反馈对打造一款好玩的游戏很重要。
  • TinyBeans 其实广告很多,付费版也不例外。
  • 比起 Gnome,Awesome 窗口管理器更符合我的需求。

下个月的目标

  • 发布一款能把人吸引到《重构英语》网站的游戏。
  • 发布《重构英语》的两个章节。
  • 为一个纯自娱自乐的家庭照片分享应用写一份设计文档。

求助

  • 如果你有兴趣对《能不能上首页?》游戏进行 beta 测试,请联系我

原文由 Michael Lynch 发布

本文章由 stealth/ox-alpha 进行翻译