Paternity Leave: Month 3

Michael Lynch

陪产假:第三个月

原文由 Michael Lynch 发布,订阅该博客

一句话总结

逐渐回归工作。

亮点

  • 作为新手爸爸,我越来越能平衡好自己的时间了。
  • 我曾为两篇表现不佳的博文而郁闷,结果它们后来都火了。
  • 我尝试了堆叠式 diff 的软件开发工作流,除了 git 本身的短板外,整体体验不错。

目标评分

每月初我都会定下当月想完成的目标,以下是本月的完成情况:

享受家庭时光

  • 结果:和妻子、儿子共度了愉快的时光。
  • 评分:A

我发现时常提醒自己很有帮助:即便看起来有很长一段时间没工作,那也是我自己的选择,而且我的时间在很大程度上仍由我掌控。

我仍在寻找工作与家庭之间的平衡,但感觉正越来越好。

发布 Nix 模糊测试教程

逐渐回归工作

当我坐下来写这篇回顾时,之前那种没时间工作的焦虑仿佛已是很久以前的事了。我还以为那是两个月前的事,没想到翻开一看,竟然就是上一篇回顾里的内容。

好在现在我对家庭时间的分配感到放松多了。在享受大量家庭时光的同时,我也发表了比以往更多的文章

几个影响因素:

儿子夜里睡得更好了

之前他每晚要醒三四次,每次吃奶要 60 到 90 分钟,现在每晚只醒两三次,而且 15 到 60 分钟内就能重新入睡。

昨晚他更是睡了整觉(7 小时 45 分钟),让人很兴奋。

家人的帮助更多了

随着儿子慢慢长大,我们也更放心让家人过来单独照顾他。现在每周大约有五个小时的帮忙时间,而且这个时长很可能会继续增加,因为家人们其实愿意帮更多。

儿子能在我工作时小睡

有人抱着或放在胸前背带里时,儿子能睡得更久,所以我通常每天会把他抱在胸前工作一到三小时。这也能让妻子得到休息,因为这连续的几小时里她可以完全属于自己。

有了固定的工作时间

我发现在不固定的时间表下很难专心工作。即便有很多时间是妻子在照顾儿子,或者儿子在我胸前睡着,但一想到他们可能随时需要我,就很难集中注意力。

妻子主动提出每天给我 90 分钟雷打不动的专注时间,这对提升专注度很有帮助。知道每天都有这段时间,我也可以把那些需要高度专注的任务留到这个时段来做。

我是否在博文上投入过度了?

我以前有个不好的习惯:每学会一个难的东西,就觉得一定要写篇博文把它讲清楚。

我会把每篇文章都打磨到极致,哪怕它的受众很小,或者我根本没有渠道触达读者。之前的例子包括《Hiring Content Writers: A Guide for Small Businesses》(有受众,但我触达不到)和《Retrofitting Apps for Cloud Storage with Zero Code Changes》(非常小众,除了我那个奇怪的用例外几乎没人关心)。

也有读者表示很喜欢这些文章,但我也不得不考虑机会成本。花在它们上面的时间,如果换成写另一篇文章,会不会触达更多读者、创造更大的总体价值?

后来我写文章变得更有策略性了。如果觉得一篇文章无法达到一定的读者规模,我要么不写,要么就在“Notes”栏目里写个快速粗糙的版本。

《Using Nix to Fuzz Test a PDF Parser》

对于在这篇文章上投入的时间,我心情很矛盾。

写这篇文章让我学到了很多关于 Nix 和模糊测试的知识,但耗时远超预期。起初我想:“几个小时就能快速写完”,结果最后花了 20 多个小时。

在大语言模型的时代写软件教程也让人沮丧。几年前,教程还有长期回报,人们会通过搜索陆续发现它们。如今,如果我写一篇小众教程,大模型会直接拿走我的内容,而读者根本不知道来源是我。

《Lessons from my First Exit》

从一开始我就知道这是一篇有风险的文章,有几个不利因素:

  • 它讲的是卖掉一家公司的细枝末节,而 99% 的读者根本没打算卖公司。
    • 我上一篇关于出售的文章获得了关注,但那是一个故事,即便读者自己不想卖公司,也能享受其中的过程。
  • 文章非常长。
    • 我一般希望每篇博文的阅读时间在 10 分钟左右,而那篇估计要读 33 分钟。
  • 唯一一个可能有机会的社交媒体渠道就是 Hacker News。

我把它提交到了 Hacker News,但完全没有上首页。

我觉得它在 Hacker News 上仍有机会获得关注,但就算彻底没人看,我也依然为写了它而高兴。它帮我自己理清了这次收购的思路,以后如果再卖一家公司,也会是有用的参考。我也从一些经历过收购或正在考虑收购的创始人那里收到了积极的反馈。

峰回路转,两篇文章都火了

写完上面那段后,我发现Hackaday 报道了我的 Nix 模糊测试教程,这让人很有成就感。

就在我写完《Lessons from my First Exit》反响平平那一节的第二天,一位读者又把它提交到了 Hacker News,结果冲上了第 2 名

不过,我觉得我最初的分析还是对的:我在那篇模糊测试的文章上投入过度了,而在关于出售 TinyPilot 的那篇上投入则恰到好处。

用堆叠式 diff 实现大型功能

过去几周,我的业余编程时间大多花在了ScreenJournal 上——这是我做的一个影视点评网站。它的理念类似 Letterboxd 或 Goodreads,但评论仅对好友可见,而且代码是开源的。

用户在 ScreenJournal 上点评《Weird: The Al Yankovic Story》的动画演示

ScreenJournal,我做的开源影视点评网站

我一直想让 ScreenJournal 同时支持电影和电视剧,但先实现了电影,因为更简单。我有意没有把代码做成通用化以支持电视剧,因为不确定这个功能是否真的会做,所以想先为已有的功能做优化。

10 月,我加入了电视剧点评的支持,因此不得不修正代码库中大量“点评一定是电影”的假设。

整个改动最终达到了 2000 行代码,作为单个 changelist 来理解有点过于庞大了。我在这里用“changelist”这个词,指的就是 GitHub 里的 pull request 或 GitLab 里的 merge request 这类东西。

以前处理这种大型改动时,我的做法是建一个功能分支,在功能完成前它一直处于不可用或未完成的状态。我要么直接在功能分支上改,要么再从它拉一个子分支做子任务,完成后再合并回来。

这种做法的问题在于,功能分支会变成一大坨难以理解的改动。你可以在我把 What Got Done 从 Firestore 迁移到 SQLite的那次改动中看到例子。那次改动里有很多子步骤,但因为全混在一起,根本无法逐一审查。

所以,这次做 ScreenJournal 的改动时,我尝试了不同的方法。我没有保留一个又大又乱的功能分支,而是采用了堆叠式 diff。

什么是堆叠式 diff?

堆叠式 diff 指的是:你有一个 main 分支,想合入一个大型功能,于是把功能拆成改动 ABC。你从 main 拉出 A,再从 A 拉出 B,以此类推。

GitHub 对堆叠式 diff 的支持还算可以:假设你的堆栈是 ABC,你会创建一个从 Amain 的 PR,再创建一个从 BA 的 PR。当你把 A 合并到 main 后,原来 BA 的 PR 会自动更新为 Bmain 的 PR。

我把工作按电视剧点评流程中的每一页拆成了一个个 changelist。

留下点评的第一步是搜索想点评的作品。以前只能搜电影,所以我支持电视剧的第一步就是加一个单选按钮,让用户在电影和电视剧之间选择:

ScreenJournal 标题搜索界面新增的电视剧与电影单选按钮截图

我的第一个任务是修改标题搜索界面以支持电视剧。

接下来我需要让用户能选择电视剧的季,这是只有电影时不需要的功能。所以,这也成了一个独立的改动

来自 ScreenJournal 的电视剧季选择界面截图

我的第二个任务是实现一个用于选择要评价的电视剧季的网页界面。

我就这样持续下去,流程的每个阶段都是一个新的分支和独立的 pull request。

以下是这种开发方式的一些体会。

优点:堆叠式 diff 更能激励我

堆叠式 diff 的好处在于,功能的每个子任务都是独立的 changelist。

把改动拆成更小的块让我更有成就感,也更能感受到进展。完成一个 changelist 并知道它已经 100% 完成,远比在一个又大又乱的分支上把进度从 30% 推到 35% 更有满足感。

缺点:不得不频繁丢弃变更历史

我最不喜欢堆叠式 diff 工作流的一点是,最终会删掉源码历史,这抵消了版本控制的一大好处。

每当我意识到应该在堆栈更早的位置做某个修改时,就得做 git rebase,这会重写历史。这意味着我必须向 GitHub 强制推送,结果在 changelist 里留下大量难看的 force-pushed 记录:

显示大量 force-pushed 记录的 GitHub PR 截图

在 git 中频繁变基会在 GitHub 的 changelist 里留下大量难看的 force-pushed 记录

我知道有些人希望所有改动都原样保留,就好像每次提交都是谋杀案的证据一样。我倒不在乎这个,但我确实想要一个合理的撤销历史,以防出错。我不喜欢强制推送会覆盖远端的撤销历史,而且想从本地恢复还需要复杂的操作。

优点:--update-refs 让堆叠式 diff 的变基更简单

在尝试堆叠式 diff 工作流的过程中,我了解到 git 的 --update-refs 选项,它可以一次性变基多个分支。

这个技巧让堆叠式 diff 变得更轻松,因为我之前是按顺序逐个分支变基,堆到四个分支后就变得极其繁琐。

缺点:用 --update-refs 变基后推送依然麻烦

假设我有分支 ABC,一次性变基它们后,git 的输出是这样的:

$ git rebase master --update-refs
Successfully rebased and updated refs/heads/C.
Updated the following refs with --update-refs:
        refs/heads/A
        refs/heads/B

虽然 --update-refs 简化了变基本身,却没有一句“好了,现在把刚变基的分支都推送上去”的命令。相反,我得把 git 的输出复制到文本编辑器里,编辑提取出分支名,再拼成类似 git push origin A B C -f 这样的命令。这是个很烦人的过程,总会打断我的思路。

缺点:经常陷入意料之外的 git 状态

明明觉得自己是用正确的方式在变基,却经常陷入令人困惑的状态。比如我变基之后,它又让我去解决那些已经解决过的冲突。

我通过压缩提交再重新变基来绕过这个问题,但这又一次重写历史,让撤销错误变得更难。我也很烦恼自己把大量精力浪费在思考如何“正确地向 git 道歉”上,而不是去写代码。

也许我该试试 jujutsu

我越来越多地看到关于jujutsu 的讨论,这是一个有望在 Google 内部成为标准的新版本控制系统。

几个月前我考虑过试试它,当时想:“算了,git 已经够用了,何必去追新潮流?”但经历了这次 git rebase 的折腾后,我才意识到自己已经把太多令人沮丧的 git 体验当成了常态。

粗略看了 Steve Kalabnik 的教程后,感觉 jujutsu 对堆叠式 diff 和多分支变基的支持比 git 更好

推荐

《Why I still blog after 15 years》,作者 Jonas Hietala

这篇关于博客写作的文章让我很有共鸣。在进一步浏览 Jonas 的网站后,我心想:“这家伙简直就是瑞典版的我。”所以如果你喜欢我的写作,应该也会喜欢他的。

《Notes on Ukraine》,作者 Matt Lakeman

我上周才发现 Matt 的博客,从那以后每天都在想:“这到底是何方神圣?”

Matt 经常去一些不太热门的目的地,通常待上十天左右,然后发表一篇关于那个国家的博文。但这可不是那种给妈妈寄明信片式的游记;这些文章篇幅堪比中篇小说,基于对该国历史数小时的研究以及与当地人的深入交流。

我还发现 Matt 在互联网上以用户名 dormin111 有着长期的发帖历史,比如这篇对电影《The Disaster Artist》的详细分析

他所有作品最不可思议的地方在于,似乎没有任何功利目的。通常看到有人在写作上投入这么多,很容易看出对他有什么好处:他们有一个 Substack 或某个付费课程来赚钱,免费文章只是引流品。但我在 Lakeman 的任何作品里都找不到这样的目的或盈利动机。他似乎只是单纯地热爱深入思考并分享想法

言归正传,回到这篇乌克兰的文章。我本以为他是战前去的,结果发现他是在战争爆发两个月后去的,并在距前线仅数英里的地方采访了士兵和平民。看到一个非职业记者却采访了乌克兰各色真实人物的战争报道,我觉得很有意思。比起传统媒体的任何报道,这都让人感觉更真实、更个人化。

《赛博朋克 2077》(游戏)

我平时不怎么玩游戏,每年只买一款新游戏,玩到腻为止,通常几天内玩 5 到 25 小时。这款游戏我已经玩了大约 25 小时,依然乐在其中。

它的深度令我惊叹。玩了 25 小时,我感觉自己只探索了游戏的 5% 左右,现代游戏能拥有如此庞大的世界让我惊叹不已。

我通常不在乎游戏剧情,甚至觉得被迫看冗长铺垫很烦,但《赛博朋克 2077》是少数让我觉得剧情足够吸引人、值得认真看下去的游戏。看到他们在配音上投入如此之大,甚至让基努·里维斯在游戏中担任重要角色,也很酷。

《Detroiters》(电视剧)

我早就听说过这部剧,但名字总让我不想看。一部以角色住在底特律为最大卖点的剧?听起来很无聊。

直到我看到剧中这个片段,才意识到参演的都是很棒的人,而且它的基调就像情景喜剧版、稍微更接地气一点的《I Think You Should Leave》。我刚看完第一季,觉得非常棒。

《Detroiters》剧照:Tim Robinson 和 Sam Richardson 在昏迷的 Jason Sudeikis 面前吃薯片

《Detroiters》就像是更接地气的情景喜剧版《I Think You Should Leave》。

收尾

做了哪些事?

经验总结

  • 堆叠式 diff 为大型改动提供了不错的工作流,但 git 对它的支持并不好。
  • 让在博文上的投入与预期回报相匹配。
    • 虽然我热爱记录学到的所有东西,但我需要博客在财务上可持续,而这只有在大部分长文都能吸引到可能对我的盈利项目感兴趣的读者时才能实现。

下月目标

本文章由 muse-spark-1.2-contributor 进行翻译

评论