Refactoring English: Month 1

Michael Lynch

Refactoring English(《重构英语》):第 1 个月

一句话总结

我发布了本书的第一章。

亮点

  • 我发布了本书的第一章,对反响感到满意。
  • 我尝试聘请封面设计师,但失败了。
  • 我可能已经找到了让 PicoShare 支持大文件的方法。

目标评分

每个月初,我都会公布当月的目标。以下是完成情况:

完成《重构英语》的两章

  • 结果:完成了一章,第二章完成了 75%。
  • 评分:B

第一章花的时间比预期更长,因为我不断发现想要重写的地方。休息一周去写第二章再回头看,确实很有帮助。

与设计师合作完成《重构英语》的封面设计

  • 结果:决定自己完成封面设计。
  • 评分:C

我与设计师合作到一半就叫停了,因为我不喜欢设计的方向。我决定暂时自己做封面。

完成《重构英语》第一章的感想

我发布了新书《重构英语》的第一章。这一章名为“软件教程写作规则”,基于我多年来学习教程并观察其优劣的经验写成。

第一章获得了不错的反响

这一章的反响超出了我的预期上限。它的内容是一份关于教程的规则清单,所以我本以为不会引起轰动,但在几个我认为比较匹配的平台上还是获得了不错的回应:

我关注的主要指标是邮件列表订阅人数。文章发布后的一周内新增了 245 名订阅者,使本书的总订阅人数增长了 31%。

第一章使本书邮件列表的订阅人数大幅增长。

发布后该如何恰当地迭代文章?

几年前,Redis 的创造者 Salvatore Sanfilippo(萨尔瓦托雷·桑菲利波)暂停了编程工作,去创作科幻小说。在写作期间,他提到

我认为写作和编程之间最鲜明的区别在于,一部小说一旦写完、编辑并定稿,就基本保持不变了。

桑菲利波接着说,程序员应该向小说家学习,克制在完成后重写应用核心逻辑的冲动。而我得出的却是相反的结论:作者应该像程序员那样更迭代地写书。

对于《重构英语》,我尝试以接近完成的状态发布章节,同时也希望读者的反馈能塑造我的写作。

让章节处于持续变动的状态带来了一个我以前从未遇到的问题:我把评论区的讨论搞乱了。在 Hacker News、Lobste.rs 和 reddit 上,评论者对我关于“让计算机去计算条件逻辑”的观点提出了异议。我觉得他们说得对。那是我最薄弱的一个论点,所以我已经把它删掉了。

问题在于,任何阅读那些讨论的人都会疑惑,为什么大家在反驳一篇文章中根本不存在的观点。

我能想到的最好办法是在文末加一条说明,表示本书仍在修订中,并附上原文链接和重要修改列表。

如何持续找到读者来提供反馈?

到目前为止,我觉得基于读者反馈进行迭代的计划是有效的。

我对第一章发布的内容感到满意,同时也收到了许多读者深思熟虑的批评,这将有助于我进行修订。

我曾想:“好吧,我可以继续向同样的渠道分享预览章节。”

然后,我回顾了目录,发现没有其他章节适合我分享第一章的那些渠道。这些网站大多有明文或不成文的规定:“如果帖子里没有代码,就不属于这里。”例如,/r/programming 大概不会对我那篇充满激情地批判被动语态的章节感兴趣。

我有一个想法是为其他作者做自由编辑,并以此为《重构英语》提供素材。

不过我不认为“编辑”恰好是我擅长的。人们听到“编辑”会以为我会帮他们润色文字。而我真正想做的是发现他们写作中的问题,并讲解帮助他们自行改进的原则和技巧。我不知道该怎么称呼这个。写作指导?辅导?

无论如何,如果你对此感兴趣,请联系我。我可以帮助你修改博客文章、文档或任何与软件相关的写作。我可以教你如何吸引更多读者、让写作更具吸引力。基本上,如果你喜欢我在这个博客上的写作方式,我可以向你展示我在这里使用的技巧。

  • 两轮审阅收费 100 美元。
    • 费用包含我对初稿的审阅以及根据我的反馈修改后的再审阅。
  • 文章最多 2500 字。
  • 收费主要是为了让你有所投入,如果 100 美元超出你的预算,也许我们仍可以商量。

我在 Reedsy 上聘请图书封面设计师的不愉快经历

11 月让我分心的一件事就是说服自己需要专业设计的封面。我在 11 月启动了这个流程,但实际工作发生在 12 月。

我是通过 Reedsy 找到设计师的,这是一个在Write Useful Books community 中被多人推荐的平台。普遍的评价是价格贵但值得。

我写了一份设计简报来说明我的需求,并发给了 Reedsy 上的四位设计师。我的预算标为 350 至 650 美元。一位设计师的报价比我的上限高出 20%,回复只是泛泛地说“当然,我可以为你做”,没有任何迹象表明他读过我的简报。另一位设计师以预算太低为由拒绝了,还有一位则没有回复。

唯一有效的报价来自 Gary(加里),他报价 350 英镑(434 美元)来做封面。他发来了周到的回复,提到了我简报中的具体细节,他的作品集里有数十个图书封面,而且他在 Reedsy 上拥有完美的 5.0 评分。他提出了一个月的时间表,费用分三期支付。这听起来不错,于是我聘用了他。

与加里的合作

一周过去了,我没有收到加里的任何消息。在第一笔款项被自动扣费后,我询问了初稿的预计时间。加里说第二天会发送构思,第二天他也确实发了。

我通过 Reedsy 聘请的设计师提供的初始图书封面构思

样稿 1 看起来不错,但它几乎是直接抄袭了我曾在简报中提到的Beautiful Code(《代码之美》)。其余的则平淡无奇,但我归咎于自己没有在简报上花更多时间。

在审视这些构思时,我意识到我想传达的是细致、审慎工作的理念。我觉得第 6 个禅意花园的样稿和第 5 个黏土模具的样稿方向是对的,于是我要求围绕这些方向深入,并建议用雕塑家雕刻石头的意象。

又过了一周,加里发来了禅意花园构思的一个微小变体。他也尝试了雕塑家的概念,用了一张凿子与原石的照片。但照片中的石头完全没有被雕刻过,所以没有体现出细致工作的理念。

接下来的一周是圣诞节,我开始担心项目无法在 12 月 30 日的截止日期前完成。加里在圣诞节前的周一给我发邮件说他 12 月 27 日恢复工作,所以仍然能按时完成。

到 27 日下班时,我仍未收到加里的消息,我意识到自己陷入了困境。

对我而言,那是美国东部时间周五下午 4 点,但加里在英国,他的工作日早已结束。Reedsy 将在周一东部时间中午自动扣费。而 Reedsy 允许我对账单提出异议的最后期限是扣费前 24 小时,所以我已经没有工作日可以拿到完成的工作了。

我请求 Reedsy 客服将我的最后一笔付款推迟一周,因为加里还没有交付工作。Reedsy 告诉我必须与加里协商解决。我解释说如果等到下一个工作日再得到加里的回复,就来不及调整付款了。Reedsy 客服仍坚持让我先尝试与加里解决。

我在周五东部时间下午 5 点给加里发了邮件,他回复说自己不按“朝九晚五”工作,所以周末加班仍能按时完成项目。出于好意他推迟了我的付款,但似乎对我向 Reedsy 投诉感到不高兴。

而我则尽量坚持正常的工作时间,并不想在周末与加里一起匆忙完成这个项目。周一再查看时,加里已经对两个构思发来了更新,但两者都很平庸。一个明显是 AI 生成的,看起来不真实。另一个则完全没有抓住我要求的基调。

我询问加里这些图片是否为 AI 生成,以及是否符合我在简报中规定的许可要求。他当时变得含糊其辞,于是我要求取消项目。我提出如果他允许我取消最后一笔付款并终止项目,我愿意支付已付的 231 英镑(287 美元)。他同意了,事情就此结束。

我给加里打了全 3 星的评价。我不认为他很糟糕,只是平庸且不善于沟通时间安排。我的评价是公开的,但尽管我给了 3.0 分,Reedsy 仍显示加里拥有完美的 5.0 评分,而且他只有另外四条评价。

尽管我给了加里 3 星评价,他在拥有五条评价的情况下仍显示为完美的 5.0 分。

我自制的图书封面

加里退出后,我决定尝试自己制作封面。我在 Unsplash 上找到了一张免版税图片,它体现了安静、细致工作的精神,然后加上了文字。

我知道它看起来很业余,但满意度大约达到了我对加里作品预期的 80%。而且这是免费的,只花了我一个小时。我把它当作一个占位符。以后我随时可以再请人或投入更多时间。

业余项目

让 PicoShare 支持大文件

PicoShare 是我开发的一款极简、易于托管的网络文件分享应用。我几年前创建了它,每周都会使用。

让我有点不好意思的是,PicoShare 在处理大文件时扩展性很差。在一台共享 CPU、256 MB 内存的虚拟机上,PicoShare 处理约 1 GB 以内的文件表现很好。如果尝试上传超过 1 GB 的文件,PicoShare 通常会耗尽内存并崩溃。你可以通过增加硬件来解决这个问题,但如果 PicoShare 能支持任意大小的文件上传就更好了。

我已经几次深入研究过这个问题,我强烈怀疑这个性能问题是因为 PicoShare 将所有文件数据都存储在 SQLite 中。这是一个不寻常的选择,但它意味着 SQLite 数据包含了应用的完整状态,包括文件数据。所以,我认为发生的情况是 PicoShare 试图向 SQLite 写入大量数据,耗尽了内存,然后崩溃。

我一直很好奇使用 SQLite 的 streaming I/O APIs(流式 I/O API),因为它们似乎能让我更高效地写入数据库。但我用 Go 编写了 PicoShare,而我使用的 Go SQLite 驱动并不支持 streaming I/O APIs。

幸运的是,Nuno Cruces(努诺·克鲁塞斯)发布了一个支持 streaming I/O 的 Go 用 SQLite 新驱动,并主动提出帮我将 PicoShare 移植到他的库上。我在 9 月与他合作了一段时间,取得了一些进展,但我们发现即使使用 streaming I/O,PicoShare 在处理大文件时仍会耗尽内存。

努诺建议,如果我将文件拆分并分块写入 SQLite,可能会降低内存消耗。实际上,我在当前的实现中已经这样做了,但不同的 streaming I/O 语义意味着我必须重写大量精细的代码。所以,当时我就泄气了,把这项工作搁置了。

12 月,我以全新的视角重新审视了 streaming I/O 的问题。我意识到分块问题比我想象的要简单。PicoShare 在写入大文件时会耗尽内存,但在读取时不会。因此,我只需要用更高效的 streaming APIs 重新实现写入部分。

使用 streaming I/O 分块写入文件结果比我用 SQLite 默认 API 实现的要简单。我最初以为最简单的方法是用一个io.Writer 对象抽象 SQLite 数据库,然后让 io.Copy 转储数据。但这一次,我意识到如果直接完成所有写入而不使用 io.Copy 会更简单。

streaming I/O 版本在我的有限测试中一直很稳定,但我仍需要更广泛地测试。障碍在于我家里的上传速度非常慢,所以我一直在想办法在 fly.io 上运行一个可以通过 VNC 远程访问的桌面操作系统。

总结

完成了什么?

经验教训

  • 聘请平面设计师的经验教训
    • 在聘请专业人士之前,考虑先做一个自制的占位版本。
    • 将付款与项目里程碑挂钩,而非日期。
    • 明确说明你是否接受设计师使用 AI 生成的图像或 AI 辅助的图像合成。
    • 明确要求查看第三方素材(如照片或字体)的许可信息。
      • 我在简报中说过所有素材都必须具有兼容的许可。
      • 更好的做法是要求承包商必须交付许可信息,而不仅仅是口头保证其提供的素材符合许可。
    • 不要计划在圣诞节刚结束就截止的项目。
    • Reedsy 的体验严重偏向承包商而非客户。

下个月的目标

  • 发布我 2024 年的年度回顾博文。
  • 再完成本书的一章。
  • 根据读者反馈修订教程章节。

求助

  • 如果你有兴趣聘请我帮助你改进写作,请联系我

原文由 Michael Lynch 发布

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