1. 程式人生 > >軟體設計的哲學:第八章 降低複雜性

軟體設計的哲學:第八章 降低複雜性

目錄

  • 8.1 示例:編輯器文字類
  • 8.2 示例:配置引數
  • 8.3 做過了頭
  • 8.4 結論

本章介紹了另一種思考如何建立更深層次類的方法。假設您正在開發一個新模組,並且發現了一個不可避免的複雜性。哪個會更好呢:應該讓模組的使用者處理複雜性,還是應該在模組內部處理複雜性? 如果複雜性與模組提供的功能有關,那麼第二個答案通常是正確的。大多數模組的使用者都比開發人員多,所以開發人員比使用者遭罪更好。作為一個模組開發人員,您應該努力使您模組的使用使用者生活的儘可能輕鬆,即使這意味著您需要額外的工作。表達這一思想的另一種方式是, 對於模組來說,擁有一個簡單的介面比簡單的實現更重要。

作為一名開發人員,很容易採取相反的方式:解決簡單的問題,把困難的問題推給其他人。 如果出現不確定如何處理的情況,最簡單的方法是丟擲異常,讓呼叫者處理它。如果您不確定要實現什麼策略,您可以定義一些配置引數來控制策略,並讓系統管理員為它們找出最佳值。

這樣的方法在短期內會使你的生活更容易,但它們會增加複雜性,因此許多人必須處理一個問題,而不是一個人。例如,如果一個類丟擲一個異常,那麼該類的每個呼叫者都必須處理它。如果類匯出配置引數,則每個安裝中的每個系統管理員都必須學習如何設定它們。

8.1 示例:編輯器文字類

考慮為GUI文字編輯器管理檔案文字的類,這在第6章和第7章中討論過。該類提供了將檔案從磁碟讀入記憶體、查詢和修改檔案在記憶體中的副本以及將修改後的版本寫回磁碟的方法。當學生必須實現這個類時,他們中的許多人選擇了一個面向行的介面,該介面具有讀取、插入和刪除整行文字的方法。這導致了類的簡單實現,但也為更高級別的軟體帶來了複雜性。在使用者介面級別,操作很少涉及整行。例如,擊鍵會導致在現有行中插入單個字元;複製或刪除選擇項可以修改幾個不同行的部分。使用面向行的文字介面,為了實現使用者介面,高階軟體必須分割和連線行。

面向字元的介面(如6.3節中描述的介面)將複雜性拉低。使用者介面軟體現在可以插入和刪除任意範圍的文字,而不需要分割和合並行,因此變得更加簡單。text類的實現可能會變得更加複雜:如果它在內部將文字表示為行集合,那麼它將不得不分割和合並行來實現面向字元的操作。這種方法更好,因為它封裝了文字類中分割和合並的複雜性,從而降低了系統的整體複雜性。

8.2 示例:配置引數

配置引數是一個向上而不是向下移動複雜性的例子。類可以匯出一些控制其行為的引數,而不是在內部確定特定的行為,例如快取的大小或放棄之前重試請求的次數。然後該類的使用者必須為引數指定適當的值。配置引數在當今的系統中非常流行;有些系統有數百個。

支持者認為配置引數是好的,因為它們允許使用者根據自己的特定需求和工作負載調整系統。在某些情況下,底層基礎結構程式碼很難知道應用的最佳策略,而使用者對他們的域要熟悉得多。例如,使用者可能知道某些請求比其他請求的時間要求更嚴格,因此使用者為這些請求指定更高的優先順序是有意義的。在這種情況下,配置引數可以在更廣泛的領域內獲得更好的效能。

然而,配置引數也為避免處理重要問題並將其傳遞給其他人提供了一個簡單的藉口。在許多情況下,使用者或管理員很難或不可能確定引數的正確值。在其他情況下,只需在系統實現中做一點額外的工作,就可以自動確定正確的值。考慮一個必須處理丟失的包的網路協議。如果它傳送了一個請求,但是在特定的時間段內沒有收到響應,它將重新發送請求。確定重試間隔的一種方法是引入配置引數。但是,傳輸協議可以自己計算一個合理的值,方法是測量成功請求的響應時間,然後對重試間隔使用該時間的倍數。這種方法降低了複雜性,使使用者不必確定正確的重試間隔。它還具有動態計算重試間隔的額外優點,因此如果操作條件發生變化,它將自動調整。相反,配置引數很容易過時。

因此,您應該儘可能避免配置引數。在匯出配置引數之前,先問問自己:“使用者(或更高級別的模組)能夠確定比我們在這裡確定的更好的值嗎?”當你建立配置引數時,看看你是否能自動計算出合理的預設值,這樣使用者只需要在特殊情況下提供值。理想情況下,每個模組應該完全解決一個問題;配置引數導致解決方案不完整,增加了系統的複雜性。

8.3 做過了頭

當把複雜性往下傳遞時要謹慎,這種想法很容易被誇大。一種極端的方法是將整個應用程式的所有功能都放到一個類中,這顯然是沒有意義的。如果(a)被降低的複雜性與類的現有功能密切相關,(b)降低複雜性將導致應用程式中其他地方的許多簡化,(c)降低複雜性將簡化類的介面,那麼降低複雜性是最有意義的。請記住,目標是最小化整個系統的複雜性。

第6章描述了一些學生如何在反映使用者介面的text類中定義方法,例如實現backspace鍵功能的方法。這似乎是件好事,因為它將複雜性向下傳遞。但是,將使用者介面的知識新增到text類並不能簡化高階程式碼,而且使用者介面知識也與text類的核心功能無關。在這種情況下,降低複雜性只會導致資訊洩漏。

8.4 結論

在開發模組時,尋找機會讓自己承擔一些額外的痛苦,以減少使用者的痛