天天看點

業務太複雜?教你如何降低軟體的複雜性

John Ousterhout 是斯坦福大學計算機系教授,也是 Tcl 語言的創造者。

今年四月,他出版了一本新書《軟體設計的哲學》(A Philosophy of Software Design)。這是課程講稿,160多頁,亞馬遜全部是五星好評。

業務太複雜?教你如何降低軟體的複雜性
我還沒讀這本書,但是我看了作者在谷歌的一次演講(Youtube),介紹了這本書的主要内容。我覺得非常值得看,大部分書教你怎麼寫正确的代碼,這本書教你如何正确設計軟體。
業務太複雜?教你如何降低軟體的複雜性

下面我就根據演講視訊和網上的書評,做一下筆記。

一、什麼是複雜性

Ousterhout 教授認為,軟體設計的最大目标,就是降低複雜性(complexity)。 所謂複雜性,就是任何使得軟體難于了解和修改的因素。

Complexity is anything that makes software hard to understand or to modify.

複雜性的來源主要有兩個:代碼的含義模糊和互相依賴。

Complexity is caused by obscurity and dependencies.

模糊指的是,代碼裡面的重要資訊,看不出來。

依賴指的是,某個子產品的代碼,不結合其他子產品,就會無法了解。

Obscurity is when important information is not obvious.

Dependency is when code can't be understood in isolation.

複雜性的危害在于,它會遞增。你做錯了一個決定,導緻後面的代碼都基于前面的錯誤實作,整個軟體變得越來越複雜。"我們先把産品做出來,後面再改進",這根本做不到。

Complexity is incremental, the result of thousands of choices. Which makes it hard to prevent and even harder to fix.

二、複雜性的隔離

降低複雜性的基本方法,就是把複雜性隔離。"如果能把複雜性隔離在一個子產品,不與其他子產品互動,就達到了消除複雜性的目的。"

Isolating complexity in places that are rarely interacted with is roughly equivalent to eliminating complexity.

改變軟體設計的時候,修改的代碼越少,軟體的複雜性越低。

Reduce the amount of code that is affected by each design decision, so design changes don't require very many code modifications.

複雜性盡量封裝在子產品裡面,不要暴露出來。如果多個子產品耦合,那就把這些子產品合并成一個。

When a design decision is used across multiple modules, coupling them together.

三、接口和實作

子產品分成接口和實作。接口要簡單,實作可以複雜。

Modules are interface and implementation. The best modules are where interface is much simpler than implementation.

It's more important for a module to have a simple interface than a simple implementation.

業務太複雜?教你如何降低軟體的複雜性

好的 class 應該是"小接口,大功能",糟糕的 class 是"大接口,小功能"。好的設計是,大量的功能隐藏在簡單接口之下,對使用者不可見,使用者感覺不到這是一個複雜的 class。

最好的例子就是 Unix 的檔案讀寫接口,隻暴露了5個方法,就囊括了所有的讀寫行為。

業務太複雜?教你如何降低軟體的複雜性

四、減少抛錯

有些軟體設計者喜歡抛錯,一遇到問題,就抛出一個 Exception。這也導緻了複雜性,使用者必須面對所有的 Exception。"反正我告訴你出錯了,怎麼解決是你的事。"

正确的做法是,除了那些必須告訴使用者的錯誤,其他錯誤盡量在軟體内部處理掉,不要抛出。

業務太複雜?教你如何降低軟體的複雜性

Tcl 語言的最初設計是,unset() 方法用來删除已經存在的變量,如果變量不存在,該方法抛錯。Ousterhout 教授說,這個設計是一個錯誤,完全不應該抛錯,隻要把 unset() 定義成讓一個變量不存在,就解決問題了。

業務太複雜?教你如何降低軟體的複雜性

另一個例子是,Windows 系統不能删除已經打開的檔案,會有錯誤提醒。這也是一個設計錯誤,有些使用者實在删不掉這些檔案,不得不重新開機系統。Unix 的做法是,總是允許使用者删除檔案,但是不清理記憶體,已經打開的檔案在記憶體裡面繼續存在,是以不會幹擾其他程式的運作,那些程式退出儲存檔案的時候,發現檔案不存在才會報錯。這個設計比較好。

原文釋出時間為:2018-09-27

本文作者:阮一峰

本文來自雲栖社群合作夥伴“Hollis”,了解相關資訊可以關注“Hollis”。

繼續閱讀