良好程式碼的優點大同小異。
不好的程式碼的糙點卻各有巧妙之處。
先說: Top down 和 Bottom up 是兩者都會交叉使用的設計方式。
由上而下的設計是從高度抽象層開始
由下而上的設計,從細節開始
開發心智模式 ≠ 使用者心智模式
由上而下與由下而上各有各自的譬諭方式(抽象)與術語使用。
人腦同一時間只能專注在特定範圍的細節,過多的細節會被分類或分解成多層次。[1]
要程式碼無法成為友善的知識記錄的載具,原因也是因為這一段是使用者不熟悉的,直接閱讀不只是英文,而是充滿一堆譬諭或術語。
而很巧的是,這個角度在 UX/UI 領域的書[2]也有介紹,由上而下,將是設計一個網站的全域導覽、輔助導覽....等,提供使用者一個資訊空間,讓使用者了解自己身處空間的何處,並且前往哪裡可以找到想找到的內容。
其實道理和開發者追縱原始碼是一樣的,從「由上而下」的這個設計,也許是一個框架開始,追縱每一個使用者互動,或者每一個網路請求為起點,了解接下來會發生的事會是什麼範圍的程式碼,若出錯了也了解哪個範圍的程式碼需要修改,好的框架使用,會帶領你前往出錯的地方,也會保證不會出錯的範圍。
簡單的說
對使用者的 UX/UI 要「以使用者友善」的角度切入設計概念模型。
對開發者的程式碼安排,要「以開發者
友善」的角度切入整個專案原始碼,一樣要設計概念模型。
由上而下寫的是 solution domain 的 code,有時會是以特定框架 (前後端框架)、Design Pattern (微架構) 組合、者某種重複的程式 (middleware) 和程式進入點 (像是 event 或 API) 的角度開始了解程式。而且,優良的由上而下設計,可以提供開發者一個概念模型,讓開發者可以用一種熟悉的概念快速上手整個程式的運作。
由下而上,往往要做的是
呼應到《沒有銀彈》的隱藏複雜度與借鏡物理學進步的原因。
數學和物理學之所以能在過去三個世紀突飛猛進,就是藉由為複雜現象建立出簡單的模型 (model) ,然後從模型中推導出現象的特性,並透過實驗來驗證這些特性。
這種方式之所以行得通,是因為在模型中所排除掉的複雜性 並非現象的本質。[4]
一樣很巧的是,這個角度在 UX/UI 領域的書[2]也有介紹,由下而上,將是盤點整個網站的內容,並且將其分類與整理在一個表格上,每個內容要怎麼呈現尚未決定,但是會先知道網站可以提供的內容有哪些,可以弄成一覽表最好。
這個道理,其實也和開發者會將「即將解決的問題」寫成各種 Class 和 Methods 歸納得好好的就是良好的由下而上的設計,將問題內會需要表達的主詞先找到都做成 Class 就是優良的設計。
在此的重點「要以使用者熟悉
」的角度切入整個專案原始碼。使用用的是使用者熟悉的字彙與術語,要將程式碼寫得像是在「操作真實世界的事物」般,可以感覺到愈寫愈清楚專案在做什麼。(這是真的)
由下而上在於描述 problem domain 內容的 code。往往在這一段,糙 code 來自於不夠深入了解問題核心而隨意命名或者不知道邏輯分類,也因為不了解問題真實面貌,造成耦合性與內聚性安排不恰當。
盤點你要解決的問題中,有幾個名詞,將它們整理成心智圖,並且將它們所屬的動詞都建成相關的抽象資料型別。再將心智圖整理成 Class Diagram ,目前處理的問題中會需要設計什麼樣的類別,誰與誰可以共用,漸漸的就會在這個地方,再次使用上 Design Pattern 也說不定呢。
經過較為仔細的設計流程,就比較不會在架構設計上出現糙 code 。之後再重構時也會比較有架構
後端框架其實很容易理解,兩個主詞: API 和 資料表。
由上而下的設計
回答這些問題
相信每一個寫過後端的工程師,每天都在回答過這三個問題。
而且,共同的語言會這麼問
其中,「這個 controller 做了什麼」的問題可以透過上次有寫過的重點「邏輯分類」,讓邏輯再被分解成多層次。甚至分到由下而上的層次。
簡單的說,由上而下所寫的程式碼,往往是 solution domain 的 code。
由下而上的設計
回答這些問題
相信每一個寫過後端的工程師,每天都在回答過這三個問題。
而且,共同的語言會這麼問
是不是有 一個 model 可以是很多種實體
的 case ,透過一個欄位的 type 可以切換呢?model 彼此之間是不是有什麼特別的關係?(除了關聯式資料表上的關係之外)
在這要特別提到
「將 table 裡的資料 query 出來」應該屬於 model 的 constructor 或 getter,而不屬於放在 controller 上的 code。
原因在於要設計 最小條件搜尋唯一值
或 最小條件搜尋列表
,這在整個專案中是永遠不變 (也許會增減),而且是依照不同 table 的命名而所有不同的。(不是每個 table 都會設計垃圾筒機制,改變 enable 欄位的 boolean 值)
對於 UX/UI 的領域,是使用者工作會用到的範圍。而對開發者來說,意思是「真正寫程式的地方」,要考慮的是在框架中的哪裡呼叫什麼 Object.Methods 然後再寫一些邏輯判斷。
由下而上提供的 function 是不是有非同步?需要在這裡寫重複使用的程式碼,再互相呼叫嗎?(有點像是 Vux 的 Action)
優良的程式碼,在這一層會很薄。幾乎就只是在串接框架和內容之間。沒有寫什麼太多的 code。若有太多的邏輯與複雜的判斷,要嘛屬於框架,要嘛屬於內容。也就是說,如果你的邏輯沒有歸納到這兩層,也許就是糙 code。程式設計就是不斷的增厚框架的應用,不斷的豐富內容的抽象資料型別。然後再框架呼叫抽象資料型別。
[1]: 《Code Complete 2/e》Ch5
[2]: 《資訊架構學 4/e》第十三章 設計與文件
[3]: Problem Domain vs. Solution Domain
[4]: 《人月神話》, 沒有銀彈: 軟體工程的本質性與附屬性工作, p.239
這篇文章感覺滿滿的兼用卡....@@"
而且還有沒改好的關鍵字....
連續兩次的
"以 Web back-end 為例"
都是被說成
"由上而下"...??
原來是計劃寫二篇文章