結構化程式設計的主要原則
1、自頂向下
程式設計時,應先考慮總體,後考慮細節;先考慮全局目标,後考慮局部目标。不要一開始就過多追求衆多的細節,先從最上層總目标開始設計,逐漸使問題具體化。
2、逐漸求精
對複雜問題,應設計一些子目标作為過渡,逐漸細化。
3、子產品化
一個複雜問題,肯定是由若幹稍簡單的問題構成。子產品化是把程式要解決的總目标分解為子目标,再進一步分解為具體的小目标,把每一個小目标稱為一個子產品。
4、限制使用goto語句
結構化程式設計方法的起源來自對GOTO語句的認識和争論。肯定的結論是:在塊和程序的非正常出口處往往需要用GOTO語句,使用GOTO語句會使程式執行效率較高;在合成程式目标時,GOTO語句往往是有用的,如傳回語句用GOTO。否定的結論是:GOTO語句是有害的,是造成程式混亂的禍根,程式的品質與GOTO語句的數量呈反比,應該在所有進階程式設計語言中取消GOTO語句。取消GOTO語句後,程式易于了解、易于排錯、容易維護,容易進行正确性證明。作為争論的結論,1974年Knuth發表了令人信服的總結,并證明了:
- GOTO語句确實有害,應當盡量避免;
- 完全避免使用GOTO語句也并非是個明智的方法,有些地方使用GOTO語句,會使程式流程更清楚、效率更高。
- 争論的焦點不應放在是否取消GOTO語句上,而應放在用什麼樣的程式結構上。其中最關鍵的是,應在以提高程式清晰性為目标的結構化方法中限制使用GOTO語句;
面向對象程式設計的主要原則
1、單一職責原則(Single-Responsibility Principle)
就一個類而言,應該隻專注于做一件事和僅有一個引起它變化的原因。所謂職責,我們可以了解為功能,就是設計的這個類功能應該隻有一個,而不是兩個或更多。也可以了解為引用變化的原因,當你發現有兩個變化會要求我們修改這個類,那麼你就要考慮撤分這個類了。因為職責是變化的一個軸線,當需求變化時,該變化會反映類的職責的變化。
優點:消除耦合,減小因需求變化引起代碼僵化。
2、裡氏代換原則(Liskov Substitution Principle)
子類型必須能夠替換它們的基類型。一個軟體實體如果使用的是一個基類,那麼當把這個基類替換成繼承該基類的子類,程式的行為不會發生任何變化。軟體實體察覺不出基類對象和子類對象的差別。
優點:可以很容易的實作同一父類下各個子類的互換,而用戶端可以毫不察覺。
3、依賴倒置原則(Dependence Inversion Principle)
要依賴于抽象,不要依賴于具體,用戶端依賴于抽象耦合;抽象不應依賴于細節,細節應依賴于抽象;要針對接口程式設計,不針對實作程式設計。
優點:使用傳統過程化程式設計所建立的依賴關系,政策依賴于細節,這是糟糕的,因為政策受到細節改變的影響。依賴倒置原則使細節和政策都依賴于抽象,抽象的穩定性決定了系統的穩定性。
怎樣做到依賴倒置?
- 以抽象方式耦合是依賴倒轉原則的關鍵。抽象耦合關系總要涉及具體類從抽象類繼承,并且需要保證在任何引用到基類的地方都可以改換成其子類,是以,裡氏代換原則是依賴倒轉原則的基礎。
- 在抽象層次上的耦合雖然有靈活性,但也帶來了額外的複雜性,如果一個具體類發生變化的可能性非常小,那麼抽象耦合能發揮的好處便十分有限,這時可以用具體耦合反而會更好。
階層化:所有結構良好的面向對象構架都具有清晰的層次定義,每個層次通過一個定義良好的、受控的接口向外提供一組内聚的服務。
依賴于抽象:建議不依賴于具體類,即程式中所有的依賴關系都應該終止于抽象類或者接口。盡量做到:
- 任何變量都不應該持有一個指向具體類的指針或者引用;
- 任何類都不應該從具體類派生;
- 任何方法都不應該覆寫它的任何基類中的已經實作的方法;
4、接口隔離原則(Interface Segregation Principle)
使用多個專一功能的接口比使用一個的總接口總要好。從一個客戶類的角度來講:一個類對另外一個類的依賴性應當是建立在最小接口上的。過于臃腫的接口是對接口的污染,不應該強迫客戶依賴于它們不用的方法。
優點:會使一個軟體系統功能擴充時,修改的壓力不會傳到别的對象那裡。
如何實作接口隔離原則?
- 利用委托分離接口;
- 利用多繼承分離接口;
5、迪米特原則(Law of Demeter)
迪米特法則又叫做最少知識原則(Least Knowledge Principle或簡寫為LKP),就是說,一個對象應當對其他對象有盡可能少的了解,對象與對象之間應使用盡可能少的方法來關聯,避免千絲萬縷的關系。
在軟體系統中,一個子產品設計的好不好的最主要、最重要的标志,就是該子產品在多大的程度上将自己的内部資料和其他與實作有關的細節隐藏起來。一個設計好的子產品可以将它所有的實作細節隐藏起來,徹底地将提供給外界的API和自己的實作分割開來。這樣一來,子產品與子產品之間就可以僅僅通過彼此的API互相通信,而不理會子產品内部的工作細節。這一概念就是“資訊的隐藏”,或叫做“封裝”,也就是大家熟悉的軟體設計的基本教義之一。資訊的隐藏非常重要的原因在于,它可以使各個子系統之間脫藕,進而允許它們獨立地被開發、優化、使用、閱讀以及修改。
如何實作迪米特法則?
迪米特法則的主要用意是控制資訊的過載,在将其運用到系統設計中應注意以下幾點:
- 在類的劃分上,應當建立有弱耦合的類,類之間的耦合越弱,就越有利于複用
- 在類的結構設計上,每一個類都應當盡量降低成員的通路權限。一個類不應當public自己的屬性,而應當提供取值和指派的方法讓外界間接通路自己的屬性。
- 在類的設計上,隻要有可能,一個類應當設計成不變類
- 在對其它對象的引用上,一個類對其它對象的引用應該降到最低
- 對于頂級的類來說,隻有兩個可能的通路性等級:package-private和public,一個類可以設定成為package-private的,就不應該把它設定成為public的
- 謹慎使用Serializable:如果一個類實作了Serializable接口的話,用戶端就可以将這個類串行後再并行化。假如以後這個類一旦修改,用戶端勢必也将改動。是以能不用就不用
6、開放-封閉原則(Open-Closed Principle)
對擴充開放,對修改關閉。
優點:按照OCP原則設計出來的系統,降低了程式各部分之間的耦合性,其适應性、靈活性、穩定性都比較好。當已有軟體系統需要增加新的功能時,不需要對作為系統基礎的抽象層進行修改,隻需要在原有基礎上附加新的子產品就能實作所需要添加的功能。增加的新子產品對原有的子產品完全沒有影響或影響很小,這樣就無須為原有子產品進行重新測試。
如何實作“開-閉”原則?
- 在面向對象設計中,不允許更改的是系統的抽象層,而允許擴充的是系統的實作層。
- 解決問題關鍵在于抽象化,抽象化是面向對象設計的第一個核心本質。對一個事物抽象化,即封裝了事物的本質,看不到任何細節。
- 在面向對象程式設計中,通過抽象類及接口,規定了具體類的特征作為抽象層,相對穩定,不需更改,進而滿足“對修改關閉”;而從抽象類導出的具體類可以改變系統的行為,進而滿足“對擴充開放”。
- 對實體進行擴充時,不必改動軟體的源代碼或者二進制代碼。
優秀程式設計的18大原則
1、避免重複原則(DRY - Don’t repeat yourself)
程式設計的最基本原則是避免重複。在程式代碼中總會有很多結構體,如循環、函數、類等等。一旦你重複某個語句或概念,就很容易形成一個抽象體。
2、抽象原則(Abstraction Principle)
與DRY原則相關。要記住,程式代碼中每一個重要的功能,隻能出現在源代碼的一個位置。
3、簡單原則(Keep It Simple and Stupid)
簡單是軟體設計的目标,簡單的代碼占用時間少,漏洞少,并且易于修改。
4、避免建立你不要的代碼(Avoid Creating a YAGNI (You aren’t going to need it))
除非你需要它,否則别建立新功能。
5、盡可能做可運作的最簡單的事(Do the simplest thing that could possibly work)
盡可能做可運作的最簡單的事。在程式設計中,一定要保持簡單原則。作為一名程式員不斷的反思“如何在工作中做到簡化呢?”這将有助于在設計中保持簡單的路徑。
6、别讓我思考(Don’t make me think)
這是Steve Krug一本書的标題,同時也和程式設計有關。所編寫的代碼一定要易于讀易于了解,這樣别人才會欣賞,也能夠給你提出合理化的建議。相反,若是繁雜難解的程式,其他人總是會避而遠之的。
7、開閉原則(Open/Closed Principle)
你所編寫的軟體實體(類、子產品、函數等)最好是開源的,這樣别人可以拓展開發。不過,對于你的代碼,得限定别人不得修改。換句話說,别人可以基于你的代碼進行拓展編寫,但卻不能修改你的代碼。
8、代碼維護(Write Code for the Maintainer)
一個優秀的代碼,應當使本人或是他人在将來都能夠對它繼續編寫或維護。代碼維護時,或許本人會比較容易,但對他人卻比較麻煩。是以你寫的代碼要盡可能保證他人能夠容易維護。用書中原話說“如果一個維護者不再繼續維護你的代碼,很可能他就有想殺了你的沖動。”
9、最小驚訝原則(Principle of least astonishment)
最小驚訝原則通常是在使用者界面方面引用,但同樣适用于編寫的代碼。代碼應該盡可能減少讓讀者驚喜。也就是說,你編寫的代碼隻需按照項目的要求來編寫。其他華麗的功能就不必了,以免弄巧成拙。
10、單一責任原則(Single Responsibility Principle)
某個代碼的功能,應該保證隻有單一的明确的執行任務。
11、低耦合原則(Minimize Coupling)
代碼的任何一個部分應該減少對其他區域代碼的依賴關系。盡量不要使用共享參數。低耦合往往是完美結構系統和優秀設計的标志。
12、最大限度凝聚原則(Maximize Cohesion)
相似的功能代碼應盡量放在一個部分。
13、隐藏實作細節(Hide Implementation Details)
隐藏實作細節原則,當其他功能部分發生變化時,能夠盡可能降低對其他元件的影響。
14、迪米特法則又叫作最少知識原則(Law of Demeter)
該代碼隻和與其有直接關系的部分連接配接。(比如:該部分繼承的類,包含的對象,參數傳遞的對象等)。
15、避免過早優化(Avoid Premature Optimization)
除非你的代碼運作的比你想像中的要慢,否則别去優化。假如你真的想優化,就必須先想好如何用資料證明,它的速度變快了。
“過早的優化是一切罪惡的根源”——Donald Knuth
16、代碼重用原則(Code Reuse is Good)
重用代碼能提高代碼的可讀性,縮短開發時間。
17、關注點分離(Separation of Concerns)
不同領域的功能,應該由不同的代碼和最小重疊的子產品組成。
18、擁抱改變(Embrace Change)
這是Kent Beck一本書的标題,同時也被認為是極限程式設計和靈活方法的宗旨。
參考連結:
http://blog.csdn.net/coolingcoding/article/details/8043265
http://blog.csdn.net/xyylchq/article/details/6291925
http://jingyan.baidu.com/article/75ab0bcbfb2670d6864db219.html
=======================================================================
高洪臣 (Gavin Gao)