1. 子程式
子程式是為實現乙個特定的目的而編寫的乙個可被呼叫的方法或過程。例如 c++ 中的函式(funtion), j**a 中的方法(method)。對於某些使用方式, c 和 c++ 中的巨集(macro)也可以認為是子程式。你可以把建立高質量子程式的很多技術應用到所有這些情況中。
2. 高質量的子程式
拋開計算機本身,子程式也算得上是電腦科學中一項最為重大的發明了。子程式的使用使得程式變得更加易讀,更易於理解,比任何變成語言的任何功能特性都更容易。
子程式也是迄今為止發明出來的用以節約空間和提高效能的最為重要的手段。設想,如果對每個子程式呼叫都重複寫**,而不是轉到相應的子程式,那麼**會變得多麼臃腫。再設想一下,如果要對一段**的效能進行改善,但這些**反覆出現在不同的地方,而不是被納入乙個子程式,那該有多困難。正是子程式使得現代的程式設計成為可能。
3. 建立子程式的正當理由
3.1. 降低複雜度
建立子程式乙個最主要的原因,就是為了降低程式的複雜度。可以通過建立子程式來隱藏一些資訊,這樣就不必再去考慮這些資訊了。當然,在你要編寫這個子程式的時候肯定是要考慮他們的。不過一旦程式寫好了,你就應該能忘記這些細節,可以直接呼叫該子程式而無須了解其內部工作細節。建立子程式還有其他一些原因 —— 如縮小**規模、改善可維護性、提高正確性等。但是如果沒有子程式的抽象能力,我們的智力將根本無法管理複雜的程式。
當內部迴圈或條件判斷的巢狀層次很深時,就意味著需要從子程式中提取出新的子程式了。把巢狀的部分提取出來形成乙個獨立的子程式,可以降低外圍子程式的複雜度。
3.2. 引入中間、易懂的抽象
把一段**放入乙個命名恰當的子程式內,是說明這段**用意最好的方法之一。與讀下面這一串語句相比,
讀懂下面這條語句就更容易:if(node <> null) then
while ( node.next <> null) do
node = node.next
leafname = node.next
end while
else
leafname = ""
end if
leafname = getleafname(node);
這段新程式如此之短,只要給它取個好的名字就足夠說明它的用意了。與上面的 8 行**相比,這個名字提供了更高層次的抽象,從而使**更具可讀性,也更容易理解,同時也降低了原來包含著上面那段**的程式的複雜度。
3.3. 避免**重複
毋庸置疑,建立子程式最普遍的原因是為了避免**重複。事實上,如果在兩段子程式內編寫相似的**,就意味著**分解出現了差錯。這時應該把兩段子程式中的重複**提取出來,將其中的相同部分放入乙個基類,然後再把兩段程式中的差異**放入派生類中。還有另乙個辦法,你也可以把相同的**放入新的子程式中,再讓其餘的**來呼叫這個子程式。
與**的重複出現相比,讓相同的**只出現一次可以節約空間。**改動起來也更方便,因為你只需要在一處修改即可。這時的**也會更加可靠,因為為了驗證**的正確性,你只需要檢查一處**。同時,這樣做也會使改動更加可靠,因為你可以避免需要相同的更改時,卻做了一些略有不同的修改。
3.4. 支援子類化
覆蓋(override)簡短而規整的子程式所新**的數量,要比覆蓋冗長而邋遢的子程式更少。如果你能讓覆蓋的子程式保持簡單,那你在實現派生類的時候也會減少犯錯的機率。
3.5. 隱藏順序
把處理事件的順序隱藏起來是乙個好主意。比如,如果乙個程式通常都是先從使用者那裡讀取資料,然後再從乙個資料夾中讀取輔助資料,那麼,無論是從使用者那裡讀取資料的子程式還是從檔案中讀取資料的子程式,都不應該依賴另乙個子程式是否已執行。
再舉乙個有關順序的例子,假設你寫了兩行**,先讀取棧頂的資料,然後減少 stacktop 變數的值。你應該把這兩行**放到乙個叫 popstack() 的子程式中。從而把這兩行**所必須執行黨的順序隱藏起來。把這種資訊隱藏起來,比讓它們在系統內到處散布要好得多。
3.6. 隱藏指標操作
指標操作的可讀性通常都很差,而且也容易出錯。通過把這些操作隔離在子程式內部,你就可以把精力集中於操作的意圖本身,而不是指標操作機制的細節。同時,如果此類操作都能在乙個位置完成,那麼你對**的正確性就會更有把握。如果你發現了比指標更合適的資料型別,也可以對程式做出修改,而不用擔心會破壞了那些原本要使用指標的**。
3.7. 提高可移植性
可以用子程式來隔離程式中不可移植的部分。從而明確識別和隔離未來的移植工作。不可移植的部分包括程式語言所提供的非標準功能、對硬體的依賴,以及對作業系統的依賴等。
3.8. 簡化複雜的波爾判斷
為了理解程式的流程,通常並沒有必要去研究那些複雜的布林判斷的細節。應該把這些判斷放入函式中,以提高**的可讀性,因為:(1)這樣就把判斷的細節放到一邊了;(2)乙個具有描述性的函式名字可以概括出該判斷的目的。
把布林判斷的邏輯放入單獨的函式中,也強調了它的重要性。這樣做也會激勵人們在函式內部做出更多的努力,提高判斷**的可讀性。最終,**的主流程和判斷**都變得更加清晰。
3.9. 改善效能
通過使用子程式,你可以只在乙個地方優化**。把**集中在一處可以更方便地查出哪些**的執行效率低下。同時,在一處進行的優化,就能使用到(無論是直接呼叫還是間接使用)該子程式的所有**都從中受益。把**集中到一處之後,想用更高效的演算法或更快速高效的語言來重寫**也更容易做了。
3.10 . 確保所有的子程式都很小
編寫有效的子程式時,乙個最大的心理障礙是不情願為乙個簡單的目的而編寫乙個簡單的子程式。乙個乙個只有三行**的子程式可能看起來有些大才小用,單經驗可以表明,乙個很好而又小巧的子程式會有很多用。
高質量的子程式
1.什麼是子程式?子程式是為實現乙個特定的目的而編寫的乙個可被呼叫的方法或過程。2.建立子程式的理由 除此之外還有很多其他的理由比如 隔離複雜度,隱藏實現細節,限制變化帶來的影響,隱藏全域性資料,形成 控制點,促成可重用 達到特定的重構牧的等等。在子程式層上設計 內聚性 指子程式中各種操作之間聯絡的...
高質量的子程式1
建立子程式最主要的目的是提高程式的可管理性,其次,節省 空間也只是乙個次要原因 提高可讀性,可靠性和可修改性等原因都更重要一些。我們先來看乙個低質量的子程式的例子 void handlestuffle corp data inputrec,int crntqtr,emp data emprec,do...
第七章 高質量的子程式
子程式是為實現乙個特定的目的而編寫的乙個可被呼叫的方法 method 或過程 procedure 這裡列出一些建立子程式的正當理由 除此之外,建立類的很多理由也是建立子程式的理由 關於內聚性的討論一般會涉及到內聚性的幾個層次。理解一些概念比記住一些特定的術語更加重要。好的程式名字能清晰地描述子程式所...