軟體開發中的「無緒」

無緒 (Cluelessness)

由 Martin Rinard 提出。他在演講時指出:
在開發和維護軟體系統時,應該避免讓開發人員深入了解系統。
因為人的大腦可以處理的資訊有限。若要建立一個日益變大的應用程式,就必須學習「如何讓每個開發人員在不了解整個應用程式的情況下,也能完成軟體開發」。


 “無緒” 並不是一個貶義詞。它用來區別兩種層次的理解水平。

1. 淺層理解:指對事物的了解程度僅限於掌握使用方法即可。
2. 深層理解:指對掌握了事物背後的原則、規律、原理。

在日常生活中的“無緒”

生活中我們通常只需要用到 淺層理解。例如,刷牙不需要知道化學式。不需要理解冰箱原理就可以冷凍食品。當然,也有一些人需要了解更深入的內容。像是冰箱的維修人員就要了解較深入的領域知識。但即便如此,維修人員所需要的知識仍屬於 淺層理解,因為他們也不需要了解事物背後的每個小細節和原理。

當然也可以學習每件事物背後的知識原理,但是必要性與 CP 值通常不大。因此大多數人在日常生活中只需要 淺層理解 就足夠了。

軟體開發中的“無緒”

在軟體開發中,“無緒” 也表示大部分的時間中,開發人員只需要 淺層理解 就足以應付工作。這裡的 淺層理解 並不是指開發人員不需要懂得編寫程式。以下舉個例子來說明軟體開發中的 淺層理解 與 深層理解 之間的差異。

「電子商務網站」:

某天 PM 告知下一個專案是「電子商務網站」。那麼,實作這個網站有兩種做法:

實作方法一:

在專案初始階段,我需要打開 HTTP 協定的文件,解析 HTTP 傳輸格式、
研究如何實現 POST、GET 請求....等等。 
此外還要閱讀 RFC 文件,並實現文件中的各項內容。 
全部都搞定後才能開始打造「電子商務網站」。

實作方法二:

在專案初始階段,在作業系統中下載並安裝 Apache、PHP、MySQL, 
設定妥當後即開始打造「電子商務網站」。
相信 實作方法二 才是大家熟悉開發的方式,因為現代軟體都是基於組件組裝出來的,沒有人需要獨自從頭到尾完成所有內容。在一個作業系統上安裝 Web 服務並開始編寫 HTML,對現在的開發人員來說是易如反掌。但事實上光是 Web 服務就已經複雜到極點,應該沒人敢說自己了解 Web 服務的所有內容。這一現象正是 淺層理解 的體現,讓開發人員在大部分的時間中,只需要掌握系統、框架、程式庫的使用方法,即可以將現成的組件應用到自己的應用程式,或是在組件上堆疊自己的應用程式。

設計原則中的“無緒”

我們的目標是找到一種軟體開發的實踐方式:讓開發人員不用深入了解所有組件或者模組的實現原理,僅用最少的知識就可以很好地完成自己所需要的功能。這種開發方式被稱為「選擇性無緒(selective cluelessness)」。

選擇性無緒 的思維,正好符合軟體設計原則的 緊湊性當一個程式具有緊湊性時,即具有「易於理解、使用、組合」等特性。這些特性讓使用者幾乎可以不用閱讀文件,即可自然而然的使用這些程式。但是要注意的是,緊湊性並不等同於「容易學習」。
以下提供一個緊湊與不緊湊的範例:

原生的 JavaScript 的 Date 物件是不緊湊的:

 moment.js 的 moment 物件是緊湊的:


若程式設計得當,維護人員就可以使用 淺層理解 來學習你的程式。若程式設計得不夠緊湊,維護人員往往需要將頭腦切換成 深層理解 的模式來探索你的程式碼,並學習是如何運作的。

因此編寫程式的過程中,應該時時刻刻想著如何讓你的程式變得 “無緒”,讓使用者可以用最少的力氣學習你的程式。這樣的設計思維適用於「函式、類別、模組、類別庫、架構、框架以及系統」的情境。也就是 Martin Rinard 所說的:
軟體設計要盡可能做到 “無緒”。讓開發人員可以在對系統很少了解的前提下,仍然可以完成開發的工作。

自學中的“無緒”

軟體技術的發展都是基於無緒的,每個無緒的新技術中總會埋藏一些知識。如果每一項新技術都是新的知識,那我們就只能把每項技術都試過一遍,才能將技術轉化成知識。這樣的學習方法導致我們沒辦法用過去的經驗來學習新技術,導致較低的學習效率。

幸好人類的大腦有傑出的 抽象能力,也就是我們常說的推理、歸納、一般化、舉一反三等等,意思都差不多。
學習一項新技術時,試著將技術抽象一下,排除不相關的細節,找出技術背後的知識。
通常可以透過下列三個問題來找出技術背後的知識:
  1. 技術的本質是什麼?
  2. 想解決什麼問題?
  3. 前置知識是什麼?
知識總是會和無關緊要的細節糾纏在一起,當知識和細節糾纏在一起時,知識只能被應用在狹窄的情境。當你從技術歸納出背後的知識時,會發現有許多技術的知識本質是相同的。這幫助你在學習新技術時,能夠看透新技術無緒的表面,推理出新技術內部的原理。理解內部的原理後,新技術也只剩下外面一層皮,學習速度自然加快許多。

學習新知識時也要盡量學習作者的思維。去了解作者為什麼要這樣設計,以及學習作者如何設計;學會這些思維層面的知識,會幫助「未來的你」進行思考。遇到新技術或問題時,會有更多推測與決策的能力。

重視知識的本質

對一個開發人員來說非常重要,海量的新技術總是不斷的成長,讓很多人感嘆跟不上新技術。新技術數量不斷成長的對策,就是 抓住不變的知識。大量的新技術其實只是一層皮,支撐在背後的技術跟知識都是數十年來不變的東西。演算法及資料結構不會過時;程式設計理論[^1]不會過時;開發論及方法論[^2]不會過時;良好的編寫程式習慣[^3]永遠不會過時;分析問題與決策[^4]的能力不會過時...

因此在學習新技術的同時,也別忘了閱讀軟體界大神們的 經典書籍 以及上述 不變的知識。因為這些和思維相關的知識,能夠幫助我們進行更好的決策、學習、判斷與知識堆疊。

文章內容整理自以下書籍並加以歸納與簡化:

註腳


[^1]: 程式設計理論: OOP、OOAD
[^2]: 開發論及方法論: CI/CD、DDD、Clean Architecture、BBD、TDD、ATDD、Specification By Example
[^3]: 良好的編寫程式習慣: Clean Code、易讀程式之美學、單元測試
[^4]: 分析問題與決策: 重構、SOLID 原則、Design Pattern

留言

這個網誌中的熱門文章

Git Commit Message 這樣寫會更好,替專案引入規範與範例

Gitlab 合併請求 Merge Request 是什麼?

PHP OO 物件導向基礎教學