Refactoring English: Month 1

Michael Lynch

重构英语:第一个月

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

一句话总结

我发布了新书的第一章。

亮点

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

目标评分

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

完成《Refactoring English》的两章

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

第一章花的时间比我预期的要长,因为我总能找到想重写的地方。不过我发现,先花一周时间写第二章,再回过头来审视,效果很好,能以更清醒的状态继续修改。

与设计师合作完成《Refactoring English》的封面设计

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

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

关于完成《Refactoring English》第一章的想法

我发布了新书《Refactoring English》的第一章。这一章的标题是“编写软件教程的规则”,基于我多年来阅读各种教程、观察它们优劣所积累的体会。

第一章获得了不错的反响

这一章的反响达到了我预期的上限。它只是一份关于教程的规则清单,我本没指望它会引爆互联网,但在几个我认为比较匹配的平台上,还是获得了相当不错的回应:

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

第一章的发布让本书邮件列表的订阅人数大幅跃升。

发布后该如何迭代文章?

几年前,Redis 的创造者 Salvatore Sanfilippo 暂停了编程工作,去写了一本科幻小说。在写作过程中,他这样写道

我认为写作和编程最根本的区别在于,小说一旦写完、编辑好、定稿,就基本上不会再变了。

Salvatore 接着说,程序员应该向小说家学习,克制住完工后重写应用核心逻辑的冲动。而我得出的结论恰恰相反:作者应该像程序员那样,更迭代地去写书。

对于《Refactoring English》,我尝试以接近完稿的状态发布各章,同时也希望读者的反馈能影响我的写作。

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

问题在于,之后再去看那些讨论的人,会奇怪为什么大家在反驳一个文章里根本不存在的观点。

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

如何持续找到愿意提供反馈的读者?

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

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

我当时想:“好,我可以继续在同样的渠道分享后续章节的预览。”

然后,我回顾了一下目录,才意识到其他章节都不适合我分享第一章的那些渠道。大多数这类网站都有明里或暗里的规则:“帖子里没有代码,就不属于这里。”例如,/r/programming 大概不会对我那篇痛斥被动语态的章节感兴趣。

我有一个想法是为其他作者提供自由职业的写作指导,并用这些经验来完善《Refactoring English》。

不过我觉得“编辑”这个词并不完全准确。人们听到“编辑”,会以为我是帮他们润色文字。而我真正想做的是,找出他们写作中的问题,并讲解能帮助他们自行改进的原则和技巧。我不知道该怎么称呼这个角色。写作导师?教练?

无论如何,如果这听起来对你有吸引力,欢迎联系我。我可以帮你看博客文章、文档或任何与软件相关的写作。我可以教你如何吸引更多读者、让写作更引人入胜。基本上,如果你喜欢我在这个博客上的写作方式,我可以把我在这里使用的技巧教给你。

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

通过 Reedsy 聘请图书封面设计师的不快经历

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

设计师是通过 Reedsy 找的,这是一个在 Write Useful Books 社区里有好几个人推荐的平台。大家普遍的评价是:贵,但值得。

我写了一份设计需求文档,说明了我的要求,并发给了 Reedsy 上的四位设计师。我列出的预算是 350 至 650 美元。一位设计师的报价比我的上限还高出 20%,回复也只是泛泛的“当然,我可以帮你做”,完全看不出他读过我的需求。另一位以预算太低为由拒绝了,还有一位则没有回复。

唯一一份有效的报价来自 Gary,他报价 350 英镑(约 434 美元)来做封面。他发来了很有诚意的回复,提到了我需求中的细节,作品集里有几十个图书封面,在 Reedsy 上还有满分 5.0 的评分。他提出了一个月的工期,费用分三期支付。这听起来不错,于是我就雇了他。

与 Gary 的合作

一周过去了,我没有收到 Gary 的任何消息。在第一笔款项被自动扣费后,我询问了初稿的大致时间。Gary 说第二天就会发来构思,的确也发了。

我在 Reedsy 上聘请的设计师提供的初始封面构思

方案 1 看起来不错,但几乎是对Beautiful Code的直接照搬,而我在需求里就引用过这本书。其余的方案都让人提不起兴趣,不过我把这归咎于自己没有在需求上花更多时间。

在审视这些构思时,我意识到自己真正想传达的是细致、专注的工作感。我觉得方案 6 的禅意庭院和方案 5 的黏土模具方向是对的,于是请他在这个方向上深入。我建议用雕塑家雕刻石头的意象。

又过了一周,Gary 发来了一个对禅意庭院构思的微小改动。他也尝试了雕塑家的概念,配了一张凿子和原石的图片。但照片里的石头完全没有被雕刻过的痕迹,根本没有传达出细致工作的感觉。

接下来的一周是圣诞节,我开始担心项目无法在 12 月 30 日的截止日期前完成。Gary 在圣诞节前的周一给我发邮件说,他 12 月 27 日就回来工作,所以进度依然正常。

到了 27 日下班时,我还没有收到 Gary 的消息,这下有点棘手了。

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

我请求 Reedsy 客服将最后一笔付款推迟一周,因为 Gary 还没有交付成果。Reedsy 却让我去和 Gary 协商。我解释说,如果等到下一个工作日再得到 Gary 的回复,就来不及调整付款了。Reedsy 客服还是坚持让我先去找 Gary 解决。

我在东部时间周五下午 5 点给 Gary 发了邮件,他回复说自己不按“朝九晚五”工作,所以打算周末加班,项目仍能按时完成。他出于礼貌帮我推迟了付款,但似乎对我向 Reedsy 投诉有些不满。

而我恰恰是尽量遵守正常工作时间的人,并不想在周末陪着 Gary 赶工。等到周一再看时,Gary 已经发来了两个方案的更新,但都很平庸。一个明显是用 AI 生成的,看起来很不真实。另一个则完全没有抓住我想要的基调。

我问 Gary 这些图片是否是 AI 生成的,以及是否符合我在需求中明确的授权要求。他这时变得支支吾吾,于是我提出取消项目。我提出已支付的 231 英镑(约 287 美元)归他,希望他能同意取消最后一笔付款并终止项目。他同意了,事情就此结束。

我给 Gary 打了全 3 星的评价。我不觉得他很糟糕,只是比较平庸,而且不擅长沟通时间安排。我的评价是公开的,但 Reedsy 仍然显示 Gary 是满分 5.0,即便我给了 3.0,而他只有另外四条评价。

尽管我给了 Gary 3 星评价,他在拥有 5 条评价的情况下依然显示为满分 5.0。

我自己做的封面

Gary 退出后,我决定自己尝试做一个封面。我在 Unsplash 上找到了一张可免费商用的图片,它传达出那种安静、专注的工作氛围,然后加上了文字。

我知道它看起来有点业余,但满意度大概达到了我对 Gary 成品预期的 80%。而且这是免费的,只花了我一个小时。我把它当作临时占位,以后随时可以再请人做或自己多花些时间完善。

业余项目

让 PicoShare 支持大文件

PicoShare 是我几年前做的一款极简、易于自托管的文件分享 Web 应用。我每周都会使用它。

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

我已经排查过几次,很确定性能问题是因为 PicoShare 把所有文件数据都存在了 SQLite 里。这是个不寻常的选择,但好处是 SQLite 数据就包含了应用的完整状态,包括文件本身。所以我猜测是 PicoShare 试图向 SQLite 写入大量数据时耗尽了内存而崩溃。

我一直对使用 SQLite 的流式 I/O API 很感兴趣,因为它们似乎能让我更高效地写入数据库。但 PicoShare 是用 Go 写的,而我用的 Go SQLite 驱动并不支持这些流式接口。

好在 Nuno Cruces 发布了一款支持流式 I/O 的全新 Go SQLite 驱动,并主动提出帮我把 PicoShare 迁移到他的库上。我在 9 月和他合作了一段时间,取得了一些进展,但我们发现即使用了流式 I/O,PicoShare 在处理大文件时依然会耗尽内存。

Nuno 建议我如果把文件分块写入 SQLite,可能会降低内存占用。我现在的实现其实已经是这么做的,但流式 I/O 的语义不同,意味着我得重写大量精细的代码。所以当时我就没了动力,把这事搁置了。

12 月,我换了个角度重新审视流式 I/O 的问题。我意识到分块问题比我想的要简单。PicoShare 在写入大文件时会耗尽内存,但在读取时不会。所以我只需要用更高效的流式 API 来重写写入部分。

用流式 I/O 分块写入文件,结果比用 SQLite 默认 API 的实现更简单。我最初以为最省事的办法是用一个 io.Writer 对象来抽象 SQLite 数据库,然后让 io.Copy 去倾倒数据。但这一次我发现,直接完成所有写入、不用 io.Copy 反而更简单。

流式 I/O 版本在有限的测试中表现稳定,但还需要更充分的测试。眼下的障碍是我家里的上传带宽实在太差,所以我一直在想办法在 fly.io 上跑一个可以通过 VNC 远程访问的桌面系统。

收尾

完成了什么?

经验教训

  • 聘请平面设计师的经验
    • 在聘请专业人士之前,先自己做一个临时占位版本。
    • 将付款与项目里程碑挂钩,而不是按日期。
    • 明确说明是否接受设计师使用 AI 生成的图像或 AI 辅助的图像合成。
    • 明确要求查看第三方素材(如照片、字体)的授权信息。
      • 我在需求中就说过所有素材都必须有合规的授权。
      • 更好的做法是,要求对方必须交付授权信息,而不是仅仅口头保证素材合规。
    • 不要把项目的截止时间安排在圣诞节刚结束的时候。
    • Reedsy 的体验明显偏向保护接单方,而非客户。

下月目标

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

求助

  • 如果你有兴趣请我帮你打磨写作,欢迎联系我

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

评论