<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    自寫自看

    軟件最大的追求是什么? (轉(zhuǎn)載)

    前段時(shí)間讀了《軟件的最大追求是什么》,擊節(jié)叫好,深以為然,雖然該文章很多地方顯得有點(diǎn)極端。

    如今的軟件系統(tǒng)越來越復(fù)雜,如果軟件的結(jié)構(gòu)不好會(huì)影響軟件的可維護(hù)性,重構(gòu)代碼是一件極其痛苦的事情。

    關(guān)于軟件的復(fù)雜性問題,我做了一些思考:

    1) Cyclomatic Complexity (圈復(fù)雜性 = number of decision points +1    其中number of decision points是指一個(gè)if else之類的條件判斷語句 (引自《軟件的最大追求是什么》)

    if else 語句可以被行為模式/策略模式代替,不妨看下列的例子:

    假設(shè)我們要根據(jù)條件判斷來完成不同的行為,用if else 是這樣寫的:

    main() {

    if(case A){

    //do with strategy A

    }else(case B){

    //do with strategy B

    }else(case C){

    //do with strategy C

    }

    }



    用策略模式則如下:

    class runner{

    do();

    }



    class A extends runner{

    do(){

    //do with strategy A

    }

    }



    class B extends runner{

    do(){

    //do with strategy B

    }

    }



    class C extends runner {

    do(){

    //do with strategy C

    }

    }



    main(){

    runner.do();

    }



    用了策略模式后main()中的語句的確簡單多了,再也看不到該死的if else了^_^酷~~~



    可實(shí)際上是這樣簡單嗎???仔細(xì)研究一下上面的代碼就能看出問題出來,首先這兩段代碼中的A、B、C的實(shí)際意義是不一樣的:第一段代碼中ABC代表的是某一個(gè)邏輯條件的值而第二段中的ABC則是具體的類;第二段得到如此簡化的前提是它得到的邏輯條件就是一個(gè)類;如果得到的仍然只是一個(gè)邏輯條件,那么為了達(dá)到代碼簡化的效果,必須由另一個(gè)類(或方法)完成這種邏輯條件到具體類的轉(zhuǎn)換,會(huì)出現(xiàn)類似下列的代碼

    class RunnerFactory{

    runner getInstante(case){

    if (case A) return new A();

    else if (case B) return new B();

    else if (case C) return new C(); } }



    從測(cè)試的角度來說,兩者的測(cè)試分支都是3,復(fù)雜度相同,而第二種方法在很多的時(shí)候貌似還要測(cè)試借口的有效性。用策略模式還有一個(gè)缺點(diǎn)就是會(huì)使系統(tǒng)中的類的數(shù)量大大的增加,如上的例子,采用if else類的數(shù)量為1,而采用策略模式的類個(gè)數(shù)為5個(gè)或6個(gè)(主要取決于邏輯映射是否用單獨(dú)的類)。

    如果邏輯判斷的條件有三個(gè),每個(gè)邏輯條件有三種可能的話,用策略模式系統(tǒng)至少會(huì)增加10個(gè)新類;如果條件更多的話類的個(gè)數(shù)也會(huì)更多 這么看來GOF的策略模式還要它干嘛??

    當(dāng)然不是,策略模式在很多情況下是一種非常好的解決方案。

    這還要從if else 語句造成程序復(fù)雜以至難以維護(hù)的真正原因說起。就我個(gè)人的感覺真正造成if else語句難以維護(hù)的原因是每一個(gè)邏輯分支中的處理語句過長。比如我現(xiàn)在工作中維護(hù)的代碼,常常一個(gè)條件下面的業(yè)務(wù)處理語句有兩三千行,每次我光確定某個(gè)邏輯分支的結(jié)束位置就要找半天,頭暈-_-!。如果是多層條件的話情況就更糟了。一個(gè)分支就一千多行,幾個(gè)分支上萬行自然很難維護(hù)。 if else 語句本質(zhì)上是程序的流程控制語句,而分支中N長的代碼通常是業(yè)務(wù)處理語句。

    行為模式/策略模式就是把流程判斷和業(yè)務(wù)處理進(jìn)行了一次解耦,將業(yè)務(wù)邏輯封裝成一個(gè)個(gè)單獨(dú)的類。換句話說,行為模式/策略模式并不是不需要if else 語句(事實(shí)上該判斷的還是要判斷),只不過的換了地方或者是別的代碼幫你做了。另一方面,進(jìn)行邏輯判斷的語句被集中起來而不是分散在程序的各個(gè)角落,有利于邏輯本身的維護(hù)。策略模式/行為模式還有一個(gè)明顯的好處就是如果新增加了一種狀態(tài),我們只需要新增加一個(gè)策略類(同上的ABC)就可以了,避免了在程序中改動(dòng)那些大段大段讓人厭煩的if else 語句。

    所以對(duì)于你的程序來說到底是使用設(shè)計(jì)模式還是簡單的使用if else 關(guān)鍵在于你的程序是否復(fù)雜,有沒有必要將控制邏輯和業(yè)務(wù)邏輯進(jìn)行解耦。當(dāng)然如果你可以用別的方式實(shí)現(xiàn)解耦也是非常好的。



    2) Response for Class(RFC) 當(dāng)一個(gè)類和很多其他類存在依賴時(shí),它就變得復(fù)雜甚至難以修改和維護(hù),這樣,RFC值越大,表示你的系統(tǒng)味道越壞。(引自《軟件的最大追求是什么》)



    復(fù)雜性是由類與類之間的依賴關(guān)系(dependency)造成的。

    具體如下所示:

    interface Runner;

    class A implement runner{ do(){}; }



    一個(gè)大型的系統(tǒng)中很多地方用到了runner接口,于是在很多地方出現(xiàn)了如下的相同代碼:

    {

    Runner r = new A();

    r.do();

    }



    如果因?yàn)槟撤N原因runner接口的實(shí)現(xiàn)類改為B,則在所有用到runner接口的地方代碼都要統(tǒng)統(tǒng)改為:

    {

    //Runner r = new A();

    Runner r = new B(); r.do();

    }



    這些遍布系統(tǒng)各個(gè)角落的改動(dòng)是繁瑣且容易出錯(cuò)的。

    于是出現(xiàn)了各種框架和模式,其中最著名的當(dāng)然是IOC(Inversion of Control)反轉(zhuǎn)控制或者稱之為依賴型注射(Dependency Injection) 那些討厭的代碼變成了如下:

    {

    ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml");

    Runner r = (Runner)ctx.getBean("Runner");

    r.do();

    }



    這樣我們就不需要對(duì)各個(gè)角落的代碼進(jìn)行維護(hù)了,容器會(huì)自動(dòng)的為我們選擇合適的類。

    我到覺得維護(hù)的工作還是我們的,為了讓容器注射入合適的類,我們必須要維護(hù)一個(gè)叫Spring.xml的配置文件,或者如果你不喜歡配置文件這個(gè)東東的話(比如偶)就得自己寫一個(gè)注冊(cè)類,將依賴關(guān)系一一注冊(cè)進(jìn)去。你還要為使用該接口的類定義一個(gè)以該接口為參數(shù)的構(gòu)造函數(shù)或者該接口的setter方法,好讓容器可以將實(shí)現(xiàn)類順利的注射進(jìn)來。

    該做的還是要做,只不過換了一個(gè)地方做而已。但就是換了個(gè)地方,實(shí)現(xiàn)了對(duì)依賴關(guān)系的集中維護(hù)(又是集中),大大的改善了系統(tǒng)的結(jié)構(gòu),明確了不同職責(zé)單位之間的分工。呵呵,有時(shí)自己也極端的覺得設(shè)計(jì)的工作說到底就是解決代碼結(jié)構(gòu)的問題^_^



    IOC一直是和輕量級(jí)框架聯(lián)系在一起的。所謂的重量級(jí)框架EJB也有實(shí)現(xiàn)相同功能的解決方案:Service Locator Service Locator就是一個(gè)定位器,它維護(hù)了一個(gè)數(shù)據(jù)結(jié)構(gòu)(比如一個(gè)表),通過這個(gè)定位器你可以準(zhǔn)確的定位到你的接口想要的實(shí)現(xiàn)類,Service Locator同樣使你免去了改變接口實(shí)現(xiàn)類后的維護(hù)惡夢(mèng):

    {

    Runner r = (Runner)ServiceLocator.lookup("Runner");

    r.do();

    }



    無論是IOC還是Service Locator都幫助你維護(hù)了類之間的依賴關(guān)系。那么是否我們?cè)诰幊讨幸欢ㄒ媚兀@又是個(gè)權(quán)衡的問題,IOC帶來了很多的好處,不過我個(gè)人認(rèn)為它的代碼是讓人費(fèi)解的(你根本不知道它做了什么),并且為了用它,一方面你要借助于容器,另一方面你要編寫配置文件,要為依賴型注射提供合適的途徑。

    如果你的系統(tǒng)類之間的依賴型錯(cuò)綜復(fù)雜,需求的變化常常導(dǎo)致實(shí)現(xiàn)類的變化,同時(shí)你又希望采用測(cè)試驅(qū)動(dòng)的快速開發(fā)模式,IOC毫無疑問是一個(gè)完美的解決方案;如果你的系統(tǒng)不存在上述的問題,為什么不簡簡單單的在程序中寫死呢,何苦去維護(hù)一堆配置文件(我所在的開發(fā)部門貌似都比較痛恨配置文件這個(gè)東東)。Service Locator也有很多缺點(diǎn),被罵的最多的就是沒法快速測(cè)試。

    反轉(zhuǎn)控制,即轉(zhuǎn)換控制權(quán)。依賴關(guān)系控制權(quán)的轉(zhuǎn)換是對(duì)代碼結(jié)構(gòu)的一次重構(gòu),重構(gòu)的目標(biāo)還是解耦,讓不同的職責(zé)代碼集中放到不同的地方,于是程序員可以更加專注的解決特定的問題,比如業(yè)務(wù)邏輯。

    程序設(shè)計(jì)的發(fā)展就是對(duì)代碼結(jié)構(gòu)的不斷調(diào)整,不斷解耦,讓特定的代碼解決特定的問題而不是什么都混在一起。從面向過程到面向?qū)ο箅y道不是這樣嗎,封裝的本質(zhì)也是解耦。



    在實(shí)際問題的解決當(dāng)中,最重要的信條就是合適,要記住任何結(jié)構(gòu)的改進(jìn)都會(huì)付出代價(jià),你的改進(jìn)是否值得你為此付出的代價(jià)。比如當(dāng)你做一個(gè)嵌入式程序的時(shí)候你首要考慮的自然是效率問題;而如果你做的是一個(gè)ERP產(chǎn)品,在系統(tǒng)設(shè)計(jì)的時(shí)候,光系統(tǒng)的可維護(hù)性問題就讓你不得不絞盡腦汁考慮一下代碼的結(jié)構(gòu)。



    一句話,只做最對(duì)的。

    程序設(shè)計(jì)的最大追求就是在合適的地方做正確的事。

    posted on 2008-02-25 14:11 昨夜人生 閱讀(211) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 天天综合亚洲色在线精品| 久久久精品视频免费观看| 亚洲视频人成在线播放| a成人毛片免费观看| 久久亚洲AV成人出白浆无码国产| 波多野结衣在线免费视频| 小说区亚洲自拍另类| 久热综合在线亚洲精品| 免费国产作爱视频网站| 成人午夜免费视频| 亚洲蜜芽在线精品一区| 免费在线观看a级毛片| 日韩免费高清大片在线| 小说专区亚洲春色校园| 亚洲成年人在线观看| 四虎永久在线免费观看| 日韩精品内射视频免费观看| 国产精品亚洲五月天高清| 亚洲视频在线免费观看| 大胆亚洲人体视频| AV免费网址在线观看| 在线涩涩免费观看国产精品| 亚洲色欲啪啪久久WWW综合网| 亚洲色欲色欲www在线丝| 成全视频免费高清| 2019中文字幕免费电影在线播放 | 亚洲国产精品SSS在线观看AV| 成人免费a级毛片| 日韩免费高清大片在线| 国产成人无码免费看片软件| 亚洲男人的天堂网站| 78成人精品电影在线播放日韩精品电影一区亚洲 | 色偷偷亚洲男人天堂| 亚洲综合一区二区| 亚洲av综合av一区| 伊人亚洲综合青草青草久热| 国产免费观看网站| 日本一区二区三区免费高清| 91九色老熟女免费资源站| 免费91最新地址永久入口| 国产精品免费大片一区二区|