降低耦合

按照軟件工程學粗淺的理解,耦合就是程序中模塊與模塊間的關係的總和。上面的“模塊”一詞是一個模糊的概念,可以是一個變量、一個函數、一個類,或者是一個package(在大型軟件項目中)。

顯然,如果這樣定義耦合的話,我們編的任何程序都有它的存在,而且它顯然是不可避免的——你的程序用到了一個函數,它要調用其它函數,或被其它函數所調用,或讀和寫某個變量——在我們粗淺的定義裏,這些都是耦合了。

但耦合不僅是函數A調用函數B所以A與B之間存在耦合這麼簡單。事實上,這已經是比較輕的一種耦合。它帶來的後果僅僅是:如果函數B改名了、被移除了、改變功能了就會影響到A的功能的實現,這種情況在我們的信息學競賽的編程過程中並不多見,而且很有可能在編譯期就被檢查和改正。我想說的是更深一點的東西: 比如,函數A和函數B共同使用某個全局的變量或數組,那麼它們對它就必須有某種哪怕是最顯而易見的約定,否則就會出問題。

爲何要降低耦合?很簡單,我們希望我們的程序儘量清晰,而不是一團蛛網或漿糊;這樣利於閱讀和思考,也利於修改和優化。比如說若函數A依賴於函數B的實現中某個細微的對於全局變量的副作用,那麼我們可以說A和B之間的耦合很深;這可能導致我們簡單地修改了B之後發現A不能正常工作 了;這可能花費我們大量的時間來尋找原因,畢竟“由於B的副作用被消除導致A的崩潰”這種事情太晦澀了,這不是我們希望看到的。

接下來說如何降低耦合:

1.一個函數只做一件事。我看到過的一些OI程序似乎在“吝嗇”地使用函數。也就是說持“能少一個函數就少一個函數”的態度。然而爲了減少耦合,我們應該把龐大的、笨重的東西拆成小部件,讓每一個小部件和儘量少的外部的東西耦合。另外,單個函數的行數多了會導致出錯這也是廣泛的共識。

2.不要過早在意細節優化。我知道,有些OI程序中有很巧妙的東西,比如說在排序的同時算前綴和之類。可是,真的需要這樣做 嗎?爲了少寫幾次for或者是爲了還不清楚的“效率”?效率不是想當然的東西,只有Profile能告訴你真正的效率如何瓶頸在哪裏。先用最清楚的邏輯描述出程序的框架,如果真的有時間效率問題那一般來說是算法複雜度的問題,在程序編好且正確之後再考慮細節優化吧。這是耦合度增加的溫牀。

3.減少全局變量的數量。全局變量是耦合的多發地。在軟件的開發過程中甚至有些專門對付它們的模式,例如“Singleton”。相信我,你能減少它們。在這一點上我不想說太多。

4.試圖面向對象。我知道很難讓人像我一樣,每當要在程序中用到某種數據結構——不管是最簡單的隊列還是複雜些的並查集或者Suffix Tree——我都會編一個class,而且很可能是Template Class。我並不是炫耀,我只是想減少耦合,我只是想使程序更清晰些。“面向對象”這個話題會在本系列中單列一篇文章來做更詳盡的分析。

我不知道你是否聽說過UML、MVC等等這些在軟件工程界很“時髦”的縮寫詞。我認爲這些技術(尤其是MVC)存在的主要目的就是爲了減少耦合。所以說,不要再寫像塗了膠水的繩結一樣的程序了,試圖減少耦合,從今天開始。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章