《Refactoring English》:第一個月
原文由 Michael Lynch 于 發布,訂閱此部落格
一句話總結
我發表了新書的第一章。
重點回顧
- 我發表了新書的第一章,對迴響感到滿意。
- 嘗試聘請封面設計師以失敗告終。
- 我可能找到了讓 PicoShare 支援大檔案的方法。
目標評分
每個月月初,我都會訂下當月想完成的目標。以下是這個月的達成狀況:
完成《Refactoring English》兩章
- 結果:完成一章,下一章完成了 75%。
- 評分:B
第一章花的時間比預期久,因為我一直發現想重寫的地方。不過我發現先休息一週去寫第二章,再回頭看會有幫助,能以全新的眼光重新審視。
與設計師合作完成《Refactoring English》的封面設計
- 結果:決定自己做封面設計。
- 評分:C
和設計師合作到一半,但因為不喜歡設計方向,我就喊停了。決定先自己做封面。
關於完成《Refactoring English》第一章的一些想法
我發表了新書《Refactoring English》的第一章,標題是〈Rules for Writing Software Tutorials〉,內容是基於多年來閱讀各種教學、觀察它們做得好與不好的地方所累積的心得。
第一章獲得不錯的迴響
這一章的迴響落在我預期的高標。以教學規則清單來說,我本來沒指望會爆紅,但在幾個我認為合適的網站上都得到了不錯的回應:
- Hacker News:375 分,曾衝上第 10 名
- /r/programming:159 分,當天衝上第 1 名(應該是吧?)
- Lobste.rs:27 分,衝上第 2 名
我主要追蹤的指標是電子報訂閱人數。文章發表後一週內新增了 245 位訂閱者,讓這本書的總訂閱數成長了 31%。

第一章讓本書電子報的訂閱人數大幅成長。
發表後,該怎麼迭代修改文章?
幾年前,Redis 的創造者Salvatore Sanfilippo暫停了程式開發工作,轉而寫了一本科幻小說。在寫小說的過程中,他觀察到:
我認為寫作和程式設計最鮮明的差異在於,小說一旦寫完、編輯、定稿,大致上就定版不變了。
Salvatore 接著說,程式設計師應該向小說家學習,克制在應用程式完成後重寫核心邏輯的衝動。但我反而得到相反的啟示:作者應該像程式設計師那樣,用更迭代的方式來寫書。
對於《Refactoring English》,我試著以接近完稿的狀態發表各章節,但也希望讀者的回饋能影響我的寫作。
讓章節內容保持浮動帶來了一個我從未遇過的問題:我把留言串搞亂了。在 Hacker News、Lobste.rs 和 Reddit 上,留言者對我關於「讓電腦來判斷條件邏輯」的觀點提出異議。而我覺得他們說得對。那是我最薄弱的論點,所以我已經把它刪掉了。
問題在於,之後再去看那些討論的人,會納悶為什麼大家在反對一個文章裡根本沒出現的觀點。
目前我想得到最好的解決辦法,是在文末加上一則說明,表示本書仍在修訂中,並附上原始版本的連結與重要修改清單。
如何持續找到願意提供回饋的讀者?
到目前為止,我覺得根據讀者回饋來迭代的計畫是可行的。
我對第一章發表的內容感到滿意,同時也收到了許多讀者深思熟慮的批評,這些都將有助於我修訂內容。
我本來想:「好,那我可以繼續把預覽章節分享到同樣的管道。」
但接著我檢視了目錄,才發現其他章節都不適合發在當初分享第一章的那些管道。那些網站大多有明文或不成文的規定:「文章裡沒有程式碼,就不該發在這裡。」舉例來說,/r/programming 大概不會對我那篇痛陳為何討厭被動語態的章節感到興奮。
我想到一個點子:為其他作者做自由接案的編輯,並把經驗回饋到《Refactoring English》中。
不過我覺得「編輯」並不完全是我擅長的事。大家聽到「編輯」,會以為我要幫他們潤飾文字。但我真正想做的是找出他們寫作中的問題,並說明相關的原則與技巧,幫助他們自己改進。我不知道該怎麼稱呼這種角色。寫作指導?教練?
無論如何,如果你對此感興趣,歡迎與我聯繫。我可以協助部落格文章、文件,或任何與軟體相關的寫作。我能教你如何吸引更多讀者、讓文章更引人入勝。基本上,如果你喜歡我在這個部落格的寫作風格,我可以把我在這裡使用的技巧教給你。
- 兩輪審閱收費 100 美元。
- 費用包含我審閱你的初稿,以及根據我的回饋修改後的再審閱。
- 文章長度最多 2,500 字。
- 收費主要是讓你更有投入感,如果 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.0 分。
自己動手做的封面
Gary 退出後,我決定自己試著做封面。我在 Unsplash 上找到一張免費授權的圖片,很能呈現寧靜、細緻工作的氛圍,再加上文字就完成了。

我知道看起來有點業餘,但滿意度大概有我原本期待 Gary 成品的八成。而且這是免費的,只花了我一小時。我把它當作暫時的替代方案,之後隨時可以再請人設計或投入更多時間。
支線專案
讓 PicoShare 支援大檔案
PicoShare 是我幾年前開發的一款極簡、易於自行架設的檔案分享網頁應用程式,我每週都會使用它。
讓我對 PicoShare 有點慚愧的是,它在大檔案的處理上擴展性很差。在一台共享 CPU、256 MB 記憶體的虛擬機器上,PicoShare 處理 1 GB 以內的檔案表現很好。但如果嘗試上傳超過 1 GB 的檔案,PicoShare 通常會耗盡記憶體而當掉。你可以靠堆硬體來解決,但如果 PicoShare 能支援任意大小的檔案上傳當然更好。
我已經深入研究這個問題好幾次,強烈懷疑效能問題是因為 PicoShare 把所有檔案資料都存在 SQLite 裡。這是個不常見的選擇,但好處是 SQLite 的資料就能完整保存應用程式的狀態,包括檔案本身。所以我推測實際發生的情況是,PicoShare 試圖寫入大量資料到 SQLite,耗盡記憶體而當掉。
我一直很好奇是否能使用SQLite 的串流 I/O API,因為它們看起來能讓我更有效率地寫入資料庫。但 PicoShare 是用 Go 寫的,而我當時使用的 Go SQLite 驅動程式並不支援串流 I/O API。
幸好,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 遠端存取。
總結
完成了哪些事?
- 發表了〈Rules for Writing Software Tutorials〉
- 發表了〈if got, want: A Simple Way to Write Better Go Tests〉
- 設定好新的 NixOS 系統,過去一個月完全沒用 Windows。
- 設定 offlineimap 來保留電子郵件的本地備份,並以每日快照備份。
- 為我喜歡的開源 RSS 閱讀器 fusion(以 Go 和 SQLite 打造)貢獻了幾個改進。
學到的教訓
- 聘請平面設計師的心得
- 在聘請專業人士之前,先考慮自己做個暫時的版本。
- 讓付款與專案里程碑掛鉤,而不是日期。
- 明確說明是否接受設計師使用 AI 生成圖片或 AI 輔助合成。
- 明確要求查看第三方素材(如照片或字型)的授權資訊。
- 我在需求說明中有提到所有素材都必須具備相容的授權。
- 更好的做法是要求承包商必須交付授權資訊,而不只是口頭保證素材符合授權規範。
- 不要安排在聖誕節剛結束就截止的專案。
- Reedsy 的機制明顯偏向承包商而非客戶。
下個月的目標
- 發表 2024 年的年度回顧部落格文章。
- 完成書中的另一個章節。
- 根據讀者回饋修訂教學章節。
需要協助的事
- 如果你有興趣聘請我協助寫作,歡迎與我聯繫。
隨機一篇部落格
留言
登入後參與討論