軟體設計很難。第一個冒出來的點子,幾乎不可能是最佳設計

對每個重要設計決策,考慮多個選項——這就是「設計兩次」。

範例:GUI 編輯器的文字類別#

設計類別介面時,別停在第一個點子,至少考慮幾個替代方案:

選項介面風格
行導向整行的插入、修改、刪除
字元導向個別字元的插入、刪除
字串導向(範圍)任意範圍的字元(可跨行)

不需要把每個方案的所有細節釘死——只需草擬幾個最重要的方法。

替代方案要「差異夠大」#

盡量挑差異很大的方案,學到的東西最多。

即使你確信只有一條合理路線,也至少考慮第二個設計——再爛都好。

思考爛設計的弱點、再對比好設計的優點,本身就極具教育意義。

列出每個方案的優劣#

設計介面最重要的考量:對上層程式碼是否易用

例如文字類別案例:

  • 行導向 → 上層需要為跨行 / 部分行操作做拆行 / 合行
  • 字元導向 → 多字元操作得用迴圈

其他可考慮的因素:

  • 哪個方案的介面更簡單
  • 哪個方案更通用
  • 哪個方案能讓實作更高效
    • 文字案例中,字元導向可能顯著較慢(每個字元都要呼叫一次文字模組)

可能的最佳解:把多個方案的優點合起來#

比較完替代方案後,最佳設計可能是:

  • 其中之一
  • 或一個結合多個方案優點的新設計

如果所有方案都不夠好——

  • 再生出新方案
  • 拿原方案的問題當線索:例如行 / 字元兩個方案都讓上層得做額外文字操作 → 紅旗,提示介面應該與上層的真實操作對齊 → 這個推理過程會把你導向「範圍導向」API

多層次的應用#

「設計兩次」可以套用到系統的許多層級:

  • 模組介面(如上)
  • 模組實作:對文字類別可考慮「行的 linked list」、「固定大小字元 block」、「gap buffer」等
    • 介面與實作的目標不同:實作最看重簡潔與效能
  • 高層次:UI 功能、系統主要模組的拆解

每個層級都同樣的判斷:能比較幾個方案,就比較容易看出最佳路徑。

時間成本#

「設計兩次」並不需要很多額外時間。

  • 小模組(class):考慮替代方案大概一兩個小時
  • 相較於後續實作的好幾天 / 好幾週,這只是一小部分
  • 初步設計實驗多半能換到顯著更好的設計,回收成本綽綽有餘

更大的模組?實作時間更長,好設計帶來的好處也更高

為什麼聰明人特別難接受#

作者觀察:「設計兩次」對非常聰明的人特別難接受

成長過程中,他們發現「第一個直覺」就足以拿好成績;不需要第二、第三個方案。但問題是:

  • 隨著職涯推進,他們進入更困難的問題場域
  • 終究有一天,第一個點子不再夠好
  • 大型軟體系統就是這類問題:沒有人能一次就做對

但作者經常看到聰明人堅持實作第一個點子,從而讓他們的真實潛力被低估(也讓人很難與他們合作)。

也許他們潛意識相信「聰明人應該一次就做對;嘗試多種設計就代表不聰明」——這是錯的。

不是你不夠聰明,而是問題真的很難

這是好事:思考困難的問題比解 trivial 問題有趣得多。

額外好處:磨練設計技藝#

「設計兩次」不只改善這次的設計,還會持續改善你的設計能力

比較多種方案的過程會教你:什麼讓設計變好、什麼讓設計變糟。久而久之,你會更快剔除壞設計、鎖定真正好的設計。