最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談如何降低軟件復雜性

 更新時間:2021年05月20日 14:49:09   作者:華為云開發(fā)者社區(qū)  
軟件的復雜性是我們程序員在日常開發(fā)中所必須面對的東西,學會如何 “弄清楚什么是軟件復雜性,找到導致軟件復雜的原因,并利用各種手法去戰(zhàn)勝軟件的復雜性” 是一門必備的能力。

前言

在進行軟件開發(fā)時,我們常常會追求軟件的高可維護性,高可維護性意味著當有新需求來時,系統(tǒng)易擴展;當出現(xiàn)bug時,開發(fā)人員易定位。而當我們說一個系統(tǒng)的可維護性太差時,往往指的是該系統(tǒng)太過復雜,導致給系統(tǒng)增加新功能時容易出現(xiàn)bug,而出現(xiàn)bug之后又難以定位。

那么,軟件的復雜性又是如何定義的呢?

John Ousterhout給出的定義如下:

Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system.

可見,軟件的復雜性是一個很泛的概念,任何使軟件難以理解和難以修改的東西,都屬于軟件的復雜性。為此,John Ousterhout提出了一個公式來度量一個系統(tǒng)的復雜性:

公式中,表示系統(tǒng)中的模塊,表示該模塊的認知負擔(Cognitive Load,即一個模塊難以理解的程度),表示在日常開發(fā)中在該模塊花費的開發(fā)時間。

從公式上看,一個軟件的復雜性由它的各個模塊的復雜性累加而成,而模塊復雜性 = 模塊認知負擔 * 模塊開發(fā)時間,也就是模塊的復雜性即和模塊本身有關(guān),也跟在該模塊上花費的開發(fā)時間有關(guān)。需要注意的是,如果一個模塊非常難以理解,但是后續(xù)開發(fā)過程中幾乎沒有涉及到它,那么它的復雜性也是很低的。

導致軟件復雜的原因

導致軟件復雜的原因可以細分出很多種來,而概括起來莫過于兩種:依賴(dependencies)和隱晦(obscurity)。前者會讓修改起來很費勁而且容易出現(xiàn)bug,比如當修改模塊1時,往往也涉及到模塊2、模塊3、... 的改動;后者會讓軟件難以理解,定位一個bug,甚至是僅僅讀懂一段代碼都需要花費大量的時間。

軟件的復雜性往往伴隨著如下幾種癥狀:

霰彈式修改(Change amplification)。當只需要修改一個功能,但又不得不對許多模塊作出改動時,我們稱之為霰彈式修改。這通常是因為模塊之間耦合過重,相互依賴太多導致的。 比如,有一組Web頁面,每個頁面都是一個HTML文件,每個HTML都有一個背景屬性。由于各個HTML的背景屬性都是分開定義的,因此如果需要把背景顏色從橙色修改為藍色時,就需要改動所有的HTML文件。

霰彈式修改的典型例子

認知負擔(Cognitive load)。當我們說一個模塊隱晦、難以理解時,它就有過重的認知負擔,這種情況下往往需要讀者花費大量時間才能明白該模塊的功能。比如,提供一個不帶任何注釋的calculate接口,它有2個int類型的入?yún)⒑鸵粋€int類型的返回值。從該函數(shù)的簽名上看,調(diào)用者根本無法得知函數(shù)的功能是什么,他只能通過花時間去閱讀源碼來確定函數(shù)功能后才敢去調(diào)用該函數(shù)。

int calculate(int val1, int val2);

不確定性(Unknown unknowns)。相比于前兩種癥狀,不確定性的破壞性更大,它通常指一些在開發(fā)需求時,你必須注意的,但是又無從得知的點。它常常是因為一些隱晦的依賴導致的,會讓你在開發(fā)完一個需求之后感覺心里很沒譜,隱約覺得自己的代碼哪里有問題,但又不清楚問題在哪,只能祈禱在測試階段能夠暴露而不要漏洞商用階段。

如何降低軟件的復雜性

對 “戰(zhàn)術(shù)編程” Say No!

很多程序員在進行特性開發(fā)或bug修復時,關(guān)注點往往是如何簡單快速讓程序跑起來,這就是典型的戰(zhàn)術(shù)編程(Tactical programming)方法,它追求的是短期的效益——節(jié)省開發(fā)時間。戰(zhàn)術(shù)編程最普遍的體現(xiàn)就是在編碼之前沒有進行模塊設(shè)計,想到哪里就寫到哪里。戰(zhàn)術(shù)編程在系統(tǒng)前期可能會比較方便,一旦系統(tǒng)龐大起來、模塊之間的耦合變重之后,添加或修改功能、修復bug都會變得寸步難行。隨著系統(tǒng)變得越來越復雜,最后不得不對系統(tǒng)進行重構(gòu)甚至重寫。

與戰(zhàn)術(shù)編程相對的就是戰(zhàn)略編程(Strategic programming),它追求的是長期的效益——增加系統(tǒng)可維護性。僅僅是讓程序跑起來還不足以滿足,還需要考慮程序的可維護性,讓后續(xù)在添加或修改功能、修復bug時都能夠快速響應(yīng)。因為考慮的點比較多,也就注定戰(zhàn)略編程需要花費一定的時間去進行模塊設(shè)計,但相比于戰(zhàn)術(shù)編程后期導致的問題,這一點時間也是完全值得的。

戰(zhàn)術(shù)編程 VS 戰(zhàn)略編程

讓模塊更“深”一點!

一個模塊由接口(interface)和實現(xiàn)(implementation)兩部分組成,如果把一個模塊比喻成一個矩形,那么接口就是矩形頂部的邊,而實現(xiàn)就是矩形的面積(也可以把實現(xiàn)看成是模塊提供的功能)。當一個模塊提供的功能一定時,深模塊(Deep module)的特點就是矩形頂部的邊比較短,整體形狀高瘦,也即接口比較簡單;淺模塊(Shallow module)的特點就是矩形頂部的邊比較長,整體形狀矮胖,也即接口比較復雜。

深模塊 VS 淺模塊

模塊的使用者往往只看到接口,模塊越深,模塊暴露給調(diào)用者的信息就越少,調(diào)用者與該模塊的耦合性也就越低。因此,把模塊設(shè)計得更“深”一點,有助于降低系統(tǒng)的復雜性。

那么,怎樣才能設(shè)計出一個深模塊呢?

更簡單的接口

簡單的接口比簡單的實現(xiàn)更重要,更簡單的接口意味著模塊的易用性更好,調(diào)用者使用起來更方便。而簡單的實現(xiàn) + 復雜的接口這種形式,一方面影響了接口的易用性,另一方面則加深了調(diào)用者與模塊的耦合。因此,在進行模塊設(shè)計時,最好遵守“把簡單留給別人,把復雜留給自己”的原則。

異常也屬于接口的一部分,在編碼過程中,應(yīng)該杜絕沒經(jīng)過處理,就隨意將異常往上拋的現(xiàn)象,這樣只會增加系統(tǒng)的復雜性。

更通用的接口

在設(shè)計接口時,你往往有兩種選擇:(1)設(shè)計成專用的接口;(2)設(shè)計成通用的接口。前者實現(xiàn)起來更方便,而且完全可以滿足當前的需求,但可擴展性低,屬于戰(zhàn)術(shù)編程;后者則需要花時間對系統(tǒng)進行抽象,但可擴展性高,屬于戰(zhàn)略編程。通用的接口意味著該接口適用的場景不止一個,典型的就是“一個接口,多個實現(xiàn)”的形式。

有些程序員可能會反駁,在無法預知未來變化的情況下,通用就意味著過度設(shè)計。過度通用確實屬于過度設(shè)計,但對接口進行適度的抽象并不是,相反它可以使系統(tǒng)更有層次感,可維護性也更高。

隱藏細節(jié)

在進行模塊設(shè)計時,還要學會區(qū)分對于調(diào)用者而言,哪些信息是重要的,哪些信息是不重要的。隱藏細節(jié)指的就是只給調(diào)用者暴露重要的信息,把不重要的細節(jié)隱藏起來。隱藏細節(jié)一則使模塊接口更簡單,二則使系統(tǒng)更易維護。

如何判斷細節(jié)對于調(diào)用者是否重要?以下有幾個例子:

1、對于Java的Map接口,重要的細節(jié):Map中每一個元素都是由<Key, Value>組成的;不重要的細節(jié):Map底層是如何存儲這些元素、如何實現(xiàn)線程安全等。

2、對于文件系統(tǒng)中的read函數(shù),重要的細節(jié):每次讀操作從哪個文件讀、讀多少字節(jié);不重要的細節(jié):如何切換到內(nèi)核態(tài)、如何從硬盤里讀數(shù)據(jù)等。

3、對于多線程應(yīng)用程序,重要的細節(jié):如何創(chuàng)建一個線程;不重要的細節(jié):多核CPU如何調(diào)度該線程。

進行分層設(shè)計!

設(shè)計良好的軟件架構(gòu)都有一個特點,就是層次清晰,每一層都提供了不同的抽象,各個層次之間的依賴明確。不管是經(jīng)典的Web三層架構(gòu)、DDD所提倡的四層架構(gòu)以及六邊形架構(gòu),抑或是所謂的Clean Architecture,都有著鮮明的層次感。

在進行分層設(shè)計時,需要注意的是,每一層都應(yīng)該提供不同的抽象,并要盡量避免在一個模塊中出現(xiàn)大量的Pass-Through Mehod。比如在DDD的四層架構(gòu)中,領(lǐng)域?qū)犹峁┝藢︻I(lǐng)域業(yè)務(wù)邏輯的抽象,應(yīng)用層提供了對系統(tǒng)用例的抽象,接口層提供了對系統(tǒng)訪問接口的抽象,基礎(chǔ)設(shè)施層則提供對如數(shù)據(jù)庫訪問這類的基礎(chǔ)服務(wù)的抽象。

所謂的Pass-Through Mehod是指那些“在函數(shù)體內(nèi)直接調(diào)用其他函數(shù),而本身只做了極少的事情”的函數(shù),通常其函數(shù)簽名與被其調(diào)用的函數(shù)簽名很類似。Pass-Through Mehod所在的模塊通常都是淺模塊,讓系統(tǒng)增加了無謂的層次和函數(shù)調(diào)用,會使系統(tǒng)更加復雜。

Pass-Through Mehod(選自《A Philosophy of Software Design》中的例子)

學會寫代碼注釋!

注釋是降低軟件復雜性的性價比極高的一種手法,它只需要花費20%的時間,即可獲取80%的價值。它可以提高晦澀難懂的代碼的可讀性;可以起到隱藏代碼復雜細節(jié)的作用,比如接口注釋可以幫助開發(fā)者在沒有閱讀代碼的情況下快速了解該接口的功能和用法;如果寫的好,它還可以改善系統(tǒng)的設(shè)計。

具體如何寫好代碼注釋,參考《教你寫好代碼注釋》一文。

總結(jié)

軟件的復雜性是我們程序員在日常開發(fā)中所必須面對的東西,學會如何 “弄清楚什么是軟件復雜性,找到導致軟件復雜的原因,并利用各種手法去戰(zhàn)勝軟件的復雜性” 是一門必備的能力。有句話說得很好,“代碼質(zhì)量決定生活質(zhì)量”,當你把軟件的復雜性降低了,bug減少了,系統(tǒng)可維護性更高了,自然也就帶來了更好的生活質(zhì)量。

模塊設(shè)計是降低軟件復雜度最有效的手段,學會使用“戰(zhàn)略編程”的方法,并堅持下去。我們常常提倡“一次把事情做對”,但這對于模塊設(shè)計而言并不適用,幾乎沒有人可以第一次就把一個模塊設(shè)計成完美的模樣。二次設(shè)計是一個非常有效的手法,與其在系統(tǒng)腐化之后再花大量時間進行重構(gòu)或重寫,還不如在第一次完成模塊設(shè)計后,再花點時間進行二次設(shè)計,多問問自己:是否有更簡單的接口?是否有更通用的設(shè)計?是否有更簡潔高效的實現(xiàn)?

"羅馬不是一天建成的",降低軟件的復雜性也一樣,貴在堅持。

以上就是淺談如何降低軟件復雜性的詳細內(nèi)容,更多關(guān)于如何降低軟件復雜性的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 笛卡爾乘積介紹

    笛卡爾乘積介紹

    笛卡爾(Descartes)乘積又叫直積。假設(shè)集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}
    2013-05-05
  • 在VScode上使用latex編輯pdf的方法

    在VScode上使用latex編輯pdf的方法

    這篇文章主要介紹了在VScode上使用latex編輯pdf的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Windows API函數(shù)大全(完整)

    Windows API函數(shù)大全(完整)

    Windows API函數(shù)大全,從事軟件開發(fā)的朋友可以參考下
    2012-05-05
  • App開發(fā)建議技巧

    App開發(fā)建議技巧

    有同學問我,對應(yīng)用開發(fā)你有沒有值得注意或小技巧的地方可以分享的。比如適配、優(yōu)化、排查錯誤什么的。雞排把自己的總結(jié)筆記整理出來了。供大家參考
    2018-01-01
  • 詳解軟件系統(tǒng)穩(wěn)定性的三大秘密

    詳解軟件系統(tǒng)穩(wěn)定性的三大秘密

    隨著軟件復雜性越來越高,穩(wěn)定性的保障越來越難,隨著服務(wù)規(guī)模越來越大,穩(wěn)定性的重要性越來越高。工程師在設(shè)計和開發(fā)軟件的時候,要堅持底板思維。
    2021-05-05
  • 趣味函數(shù)式編程圣經(jīng)

    趣味函數(shù)式編程圣經(jīng)

    這篇文章主要介紹了函數(shù)式編程的的相關(guān)資料,有趣的講解了函數(shù)式編程的相關(guān)知識,幫助大家更好的理解學習,感興趣的朋友可以了解下
    2020-06-06
  • 使用uniapp打包上架微信小程序完整教程

    使用uniapp打包上架微信小程序完整教程

    這篇文章主要介紹了uniapp打包上架微信小程序完整教程,需要的朋友可以參考下
    2022-12-12
  • 作為程序員必須了解的縮寫和專業(yè)名詞

    作為程序員必須了解的縮寫和專業(yè)名詞

    這篇文章主要介紹了作為程序員必須了解的縮寫和專業(yè)名詞,文中講解非常詳細,對想學編程的朋友有所幫助,感興趣的可以了解下
    2020-07-07
  • 怎樣制作“別人家的”Chrome插件

    怎樣制作“別人家的”Chrome插件

    Chrome插件有很多實用API可以讓我們使用,通過Chrome插件我們還可以做很多的事情,例如翻譯網(wǎng)頁文字等。本文將教你怎樣制作“別人家的”Chrome插件,感興趣的小伙伴一起來看看吧
    2021-08-08
  • 詳解敏捷過程中的需求管理

    詳解敏捷過程中的需求管理

    企業(yè)在做敏捷轉(zhuǎn)型中,需求無法按時交付的困擾你是否也遇到過呢?
    2021-05-05

最新評論

融水| 贡嘎县| 屯昌县| 齐齐哈尔市| 天气| 花垣县| 海丰县| 洞头县| 岑溪市| 新化县| 阳高县| 陕西省| 长顺县| 深泽县| 宁晋县| 贵定县| 玉门市| 丰宁| 双柏县| 绿春县| 古蔺县| 嘉定区| 富平县| 融水| 高密市| 丹江口市| 沙河市| 赤峰市| 宜君县| 岢岚县| 康马县| 浦县| 定安县| 布拖县| 武川县| 黄陵县| 张家港市| 安塞县| 津南区| 竹溪县| 吴忠市|