在前文《程式碼的架構可讀性》中,我提到了軟體程式碼在架構上的可讀性。架構上的可讀性有異於程式碼片段的可讀性。在過去,很多時候我們談到程式碼的可讀性時,討論多半著墨在一段程式碼的可讀性,例如小到幾行程式碼、一個函式,大到一個類別,探討著如何讓閱讀的人可以輕易了解這一段程式碼的作用、目的,以及撰寫方式的背後原由。

這種將察看可讀性的範圍,設定在一段程式碼片段的方式,可以說是從比較微觀的觀點,來看待程式碼的可讀性。相反的,其實我們還可以從另一種較為巨觀的觀點來切入,而這種較為巨觀的觀點,就是我所謂架構上的可讀性。

了解程式碼與其他程式碼、系統之間的關係
當我們試著了解一整個從未接觸過系統的程式碼時,你會先試著細讀散布在整個系統中每一個函式的內容嗎?

應該不會,因為透過這種方式來了解,不僅沒有效率,而且其實見樹不見林。你需要的是先建立起系統的整體圖像及脈絡,即使對個別的類別或函式的內容都還不了解,但是透過了解類別的介面、類別之間的關係,以及它們互動的方式,你能夠更快的了解系統的全貌。之後,基於對全貌的了解,也才能夠更快速地找到所需要細節程式碼片段於何處,以及這一段程式碼和整個系統、其他程式碼之間的關聯性。相較於較微觀層次上的程式碼片段可讀性,這種較為巨觀層次上的可讀性,其實就是架構上的可讀性。

程式碼片段的可讀性不好,會讓讀者很難明白該片段究竟在寫些什麼、為什麼要這樣子來撰寫。同樣的,程式碼架構的可讀性不好,也會讓讀者很難了解各個程式模組之間的關係,以及它們究竟是如何互動,以達成系統中的各種操作情境。有些架構設計者做出來的架構不僅簡潔,而且清晰易懂,讓人一目了然。

即使還不知道各個模組內部的細節實作究竟是如何達成的,卻可以讓人在很短的時間內,知道每個模組的權責,以及每個模組之間的相依關係。也可以讓人很容易透過舉一反三的方式,知道某一個操作情境在系統中執行時,會經由那些模組間的互動因而達成。

相反的,也有一些架構設計者所設計出來的架構可讀性不佳,讀者很難掌握架構設計時的中心精神,有時候甚至毫無架構可言。在這種情況下,程式碼的讀者連系統的概略全貌,都很難掌握了,更別提要逐一鑽進每個細節裡。即使程式碼微觀的可讀性再怎麼好,如果巨觀的可讀性不好,一樣會影響到讀者理解系統程式碼的順利與否。

增進程式碼架構可讀性的方法

若程式碼在架構上有了好的可讀性,基於剛加入團隊或打算開始接手進行維護或修改的新成員,就能輕易上手。因為對新成員而言,即使沒有讀完整個系統所有的程式碼,也能輕易找到自己必須維護或修改的片段,也能基於架構的中心思想,預期自己對特定程式碼片段所做的修改,會對其他程式模組產生什麼樣的效應。同時,知道如何基於現有的架構做功能的擴充。而這正是有良好可讀性的架構的優點。

那麼要如何增加程式碼在架構上的可讀性呢?其實不論是微觀層次上的可讀性,或是巨觀層次上的可讀性,都具備一些共通的特性。

可讀性的第一個要點就是「一致性」。當我們用微觀的觀點來看程式碼片段的可讀性時,我們會說,變數、函式、類別的命名要有一致的規則,程式碼中排版的方式也都必須遵守一定的慣例。這就是一致性的重要性。倘若你的程式碼中充斥著各種不同的命名規則及排版慣例,那麼,讀者就不容易基於命名或排版對程式碼做預期。有了「吾道一以貫之」的一致性原則後,讀者就很容易基於這個原則來做推演,很容易可以舉一反三進而明白程式碼的用意。

微觀的可讀性如此,巨觀的可讀性亦然。

例如,在你的程式架構中,存取永續性資料的部份,固定由一個資料存取層來進行存取,而關於商務邏輯的處理,則一律依據不同的子系統封裝在各個所謂Facade(代表單一子系統唯一入口的設計模式)的類別中。對子系統之外的客戶端程式碼,不僅不會直接操作任何資料,而且也僅能透過Facade類別取得商務邏輯的服務。

如此一來,在架構上的可讀性就會很清楚。因為讀者只要搞懂上述的責任分層原則,就很容易了解不同類型的商務邏輯都被置放在不同的Facade類別中,而僅有在Facade類別中才能存取永續性的資料。想要修改特定類型的商務邏輯,只要依據Facade的分類原則,找到正確對應的Facade類別,再去讀懂該Facade中程式碼的行為,就能夠修改。

反之,若是有些商務邏輯被封裝在Facade類別中,有些則散落在一些客戶端程式碼裡,那麼就產生不一致的情況。對讀者而言,就很難明白究竟那些類型的服務是在客戶端程式碼中,有些是被封裝在Facade裡。這就是一致性的重要性。

可讀性的第二個重要特質就是「單純」。

這道理很簡單,愈簡單的東西愈容易明白,愈複雜的東西愈容易困惑讀者,甚至誤導讀者的思路。

在微觀的層次上,程式設計者可能技巧不足,所以把可以寫的單純的東西給寫複雜了。但也有可能因為熟知語言,反而賣弄炫技,也把可以寫的單純的東西給寫複雜了。在巨觀的層次上亦然。設計者可能因為設計能力不佳,建構不出足夠單純的架構,或是擴充性及延展性不足,導致在需求逐步演化的情況下,致使架構疊床架屋愈形複雜。另一方面,設計者也可能因為過度工程化(Over Engineering)的原因,做出了遠超乎真正需求的架構。無論是基於何種理由,複雜化都是使得可讀性降低的原因。

可讀性的第三個重要的特性是「善用共通的語彙或概念」。

例如,像MVC(Model-View-Controller),便是一個廣為人所知的設計模式,當你在你的架構中使用MVC的語彙時,已經熟知MVC的讀者,很快便能意會。又好比事件驅動式的架構,也是眾所熟悉的既成架構概念,運用它在你所設計的系統中,也能夠讓讀者立即明白。

利用註解與圖解來協助

除了程式碼自身所展現的可讀性之外,還有一些輔助性的資訊可以協助讀者理解。對於微觀上的需求,也就是針對程式碼片段,常見重要的輔助性資訊就是註解。

好的註解可以補程式碼自身說明力的不足。而對於巨觀上的需求,我們很難直接透過程式碼片段中的註解來了解系統架構的全貌。有什麼其他的輔助性資訊可以協助我們了解呢?有個方式便是透過表示軟體模型的視覺化圖示,好比大家所熟知的UML中的各種圖示。相較於平鋪直述的程式原始碼,這些具體而微的模型圖,可以協助讀者更快理解系統的架構,以及大體的運作方式。

對於軟體系統程式碼的讀者而言,無論是微觀層次上的可讀性,或是巨觀層次上的可讀性,都是一樣重要。

讀者在嘗試理解系統時,多半是由巨觀至微觀,先了解整體的架構,接著就很容易找到所需的對應細節。過往我們所探討的可讀性不少都集中在微觀層次,本文試著繼續拋磚引玉,希望可以吸引大家一同思考,如何提高巨觀層次上的程式碼可讀性。

專欄作者

熱門新聞

Advertisement