溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

系統(tǒng)設計之怎么降低復雜性

發(fā)布時間:2021-10-21 10:30:08 來源:億速云 閱讀:118 作者:iii 欄目:編程語言

本篇內容主要講解“系統(tǒng)設計之怎么降低復雜性”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“系統(tǒng)設計之怎么降低復雜性”吧!

一、熵增定律

1、熵增定律

熵的概念最早起源于物理學,用于度量一個熱力學系統(tǒng)的無序程度。熱力學第二定律,又稱“熵增定律”,表明了在自然過程中,一個孤立的系統(tǒng)總是從最初的集中、有序的排列狀態(tài),趨向于分散、混亂和無序;當熵達到最大時,系統(tǒng)就會處于一種靜寂狀態(tài)。

通俗的講:系統(tǒng)的熵增過程,就是由原始到死亡的過程。“熵”是“活躍”的反義詞,代表負能量。

非生命,比如物質總是向著熵增演化,屋子不收拾會變亂,手機會越來越卡,耳機線會凌亂,熱水會慢慢變涼,太陽會不斷燃燒衰變……直到宇宙的盡頭——熱寂。

2、軟件系統(tǒng)的熵增

在軟件開發(fā)、維護過程中。軟件的生命力總是從最初的理想狀態(tài),逐步趨向于復雜、混亂和無序狀態(tài)發(fā)展,直到軟件不可維護而被迫下線或重構。這種損壞軟件質量的因素的逐步增長,叫做軟件的熵增現(xiàn)象,也即本文討論的軟件復雜性。

二、系統(tǒng)復雜性的表現(xiàn)

1、表象

  1. 代碼混亂、新人不易上手

  2. 代碼高度冗余,復用性低,開發(fā)效率低

  3. 擴展和修改困難,牽一發(fā)動全身

  4. 業(yè)務數(shù)據(jù)錯亂

  5. 程序性能低下

  6. 系統(tǒng)難以移置

  7. BUG率居高不下

  8. 其它……

2、深層原因

(1)變更放大

復雜性的第一個征兆是,看似簡單的變更需要在許多不同地方進行代碼修改

(2)認知負荷

復雜性的第二個癥狀是認知負荷,這是指開發(fā)人員需要多少知識才能完成一項任務。較高的認知負擔意味著開發(fā)人員必須花更多的時間來學習所需的信息,并且由于錯過了重要的東西而導致錯誤的風險也更大。

(3)未知的未知

復雜性的第三個癥狀是,必須修改哪些代碼才能完成任務,或者開發(fā)人員必須獲得哪些信息才能成功地執(zhí)行任務,這些都是不明顯的。

3、小結

復雜性的三種表現(xiàn)形式中,未知的未知是最糟糕的。一個未知的未知意味著你需要知道一些事情,但是你沒有辦法找到它是什么,甚至是否有一個問題。你不會發(fā)現(xiàn)它,直到錯誤出現(xiàn)后,你做了一個改變。更改放大是令人惱火的,但是只要清楚哪些代碼需要修改,一旦更改完成,系統(tǒng)就會工作。同樣,高的認知負荷會增加改變的成本,但如果明確要閱讀哪些信息,改變仍然可能是正確的。對于未知的未知,不清楚該做什么,或者提出的解決方案是否有效。唯一確定的方法是讀取系統(tǒng)中的每一行代碼,這對于任何大小的系統(tǒng)都是不可能的。甚至這可能還不夠,因為更改可能依賴于一個從未記錄的細微設計決策。

三、復雜性的原因

復雜性是由兩件事引起的:依賴性和模糊性。

1、依賴關系

依賴關系是軟件的基本組成部分,不能完全消除。實際上,我們在軟件設計過程中有意引入了依賴性。每次編寫新類時,都會圍繞該類的 API 創(chuàng)建依賴關系。但是,軟件設計的目標之一是減少依賴關系的數(shù)量,并使依賴關系保持盡可能簡單和明顯。

2、模糊性

當重要的信息不明顯時,就會發(fā)生模糊。

一個簡單的例子是一個變量名,它是如此的通用,以至于它沒有攜帶太多有用的信息(例如,時間)?;蛘?,一個變量的文檔可能沒有指定它的單位,所以找到它的惟一方法是掃描代碼,查找使用該變量的位置。

晦澀常常與依賴項相關聯(lián),在這種情況下,依賴項的存在并不明顯。例如,如果向系統(tǒng)添加了一個新的錯誤狀態(tài),可能需要向一個包含每個狀態(tài)的字符串消息的表添加一個條目,但是對于查看狀態(tài)聲明的程序員來說,消息表的存在可能并不明顯。

不一致性也是造成不透明性的一個主要原因:如果同一個變量名用于兩個不同的目的,那么開發(fā)人員就無法清楚地知道某個特定變量的目的是什么。

3、依賴性和模糊性的積累

復雜性不是由單個災難性錯誤引起的;它堆積成許多小塊。單個依賴項或模糊性本身不太可能顯著影響軟件系統(tǒng)的可維護性。之所以會出現(xiàn)復雜性,是因為隨著時間的流逝,成千上萬的小依賴性和模糊性逐漸形成。最終,這些小問題太多了,以至于對系統(tǒng)的每次可能更改都會受到其中幾個問題的影響。

四、降低復雜性的方法

1、日常開發(fā)留出一點戰(zhàn)略規(guī)劃時間

大多數(shù)程序員日常以戰(zhàn)術編程的心態(tài)來進行軟件開發(fā)。例如新功能或錯誤修復。乍一看,這似乎是完全合理的:還有什么比編寫有效的代碼更重要的呢?但是戰(zhàn)術編程幾乎不可能產(chǎn)生出良好的系統(tǒng)設計。

與之相對應的是戰(zhàn)略規(guī)劃,成為一名優(yōu)秀的軟件設計師的第一步是要意識到僅工作代碼是不夠的。盡管代碼當然必須工作,但不應將“能跑通的代碼”視為主要目標。戰(zhàn)略設計的主要目標必須是制作出出色的設計,考慮后續(xù)的可維護性及擴展性。

戰(zhàn)略性編程需要一種投資心態(tài)。盡管前提投入會比戰(zhàn)術編程花費更多的時間,但隨著系統(tǒng)的迭代,戰(zhàn)略編程的優(yōu)勢就開始逐漸顯現(xiàn)。

當然既然是投資,就要考慮投入產(chǎn)出比,不應該吹毛求疵,只要發(fā)現(xiàn)一點不合理的地方就整體大重構。推薦的方式小步快跑的方式,在日常開發(fā)中留出5%-10%的時間來做戰(zhàn)略設計。

2、模塊的設計

開發(fā)一個新模塊,如果有不可避免的復雜性。兩種設計思路哪個更好:1、應該讓模塊用戶處理復雜性,2、應該在模塊內部處理復雜性?如果復雜度與模塊提供的功能有關,則第二個答案通常是正確的答案。

作為開發(fā)人員,很容易以相反的方式行事:解決簡單的問題,然后將困難的問題推給其他人。如果出現(xiàn)不確定如何處理的條件,最簡單的方法是引發(fā)異常并讓調用方處理它。這樣的方法短期內會使您的生活更輕松,但它們會加劇復雜性。大多數(shù)模塊擁有的用戶多于開發(fā)人員,因此此模塊還會有許多人來維護。作為模塊開發(fā)人員,您應該努力使模塊用戶的生活盡可能輕松,即使這對您來說意味著額外的工作。另一種更好的方法是,模塊具有簡單的接口比簡單的實現(xiàn)更為重要。

模塊是設計應該是深的,最好的模塊是那些其接口比其實現(xiàn)簡單得多的模塊。這樣的模塊具有兩個優(yōu)點。1、一個簡單的接口可以將模塊強加于系統(tǒng)其余部分的復雜性降至最低。2、如果以不更改其接口的方式修改了一個模塊,則該修改不會影響其他模塊。如果模塊的接口比其實現(xiàn)簡單得多,則可以在不影響其他模塊的情況下更改模塊的許多方面。

3、如何編寫注釋

編寫注釋的原因是,使用編程語言編寫的語句無法捕獲編寫代碼時開發(fā)人員想到的所有重要信息。注釋記錄了這些信息,以便后來的開發(fā)人員可以輕松地理解和修改代碼。注釋的指導原則是,注釋應描述代碼中不明顯的內容。

注釋的最重要原因之一是抽象,其中包括許多從代碼中看不到的信息。抽象的思想是提供一種思考問題的簡單方法,但是代碼是如此詳細,以至于僅通過閱讀代碼就很難看到抽象。注釋可以提供一個更簡單,更高級的視圖(“調用此方法后,網(wǎng)絡流量將被限制為每秒 maxBandwidth 字節(jié)”)。即使可以通過閱讀代碼推斷出此信息,我們也不想強迫模塊用戶這樣做:閱讀代碼很耗時,并且迫使他們考慮很多不需要使用的信息模塊。開發(fā)人員應該能夠理解模塊提供的抽象,而無需閱讀其外部可見聲明以外的任何代碼。

4、重視命名

名稱是一種抽象形式:名稱提供了一種簡化的方式來考慮更復雜的基礎實體。良好的名字是一種文檔形式:它們使代碼更易于理解。它們減少了對其他文檔的需求,并使檢測錯誤更加容易。相反,名稱選擇不當會增加代碼的復雜性,并造成可能導致錯誤的歧義和誤解。

命名需滿足以下幾個要求:

(1)準確性

名稱最常見的問題是名稱太籠統(tǒng)或含糊不清。結果,讀者很難說出這個名字指的是什么。讀者可能會認為該名稱所指的是與現(xiàn)實不符的事物,如上面的代碼錯誤所示??紤]以下方法聲明:

/**
 * Returns the total number of indexlets this object is managing.
 */
int IndexletManager::getCount() {...}

術語“計數(shù)”太籠統(tǒng)了:計數(shù)什么?如果有人看到此方法的調用,除非他們閱讀了它的文檔,否則他們不太可能知道它的作用。像 getActiveIndexlets 或 numIndexlets 這樣的更精確的名稱會更好:因為使用這些名稱,讀者可能無需查看其文檔就能猜測該方法返回的內容。

(2)一致性

在任何程序中,都會反復使用某些變量。例如,文件系統(tǒng)反復操作塊號。對于每種常見用法,請選擇一個用于該目的的名稱,并在各處使用相同的名稱。例如,文件系統(tǒng)可能總是使用 fileBlock 來保存文件中塊的索引。一致的命名方式與重用普通類的方式一樣,可以減輕認知負擔:一旦讀者在一個上下文中看到了該名稱,他們就可以重用其知識并在不同上下文中看到該名稱時立即做出假設。

一致性具有三個要求:

  1. 始終將通用名稱用于給定目的;

  2. 除了給定目的外,切勿使用通用名稱;

  3. 確保目的足夠狹窄,以使所有具有名稱的變量都具有相同的行為。

(3)通過命名能構建起系統(tǒng)功能圖

選擇名稱的目標是在讀者的腦海中創(chuàng)建一幅關于被命名事物的性質的圖像。

一個好名字傳達了很多有關底層實體是什么,以及同樣重要的是,不是什么的信息。在考慮特定名稱時,請問自己:“如果有人孤立地看到該名稱,而沒有看到其聲明,文檔或使用該名稱的任何代碼,他們將能夠猜到該名稱指的是什么?還有其他名稱可以使畫面更清晰嗎?” 當然,一個名字可以輸入多少信息是有限制的。更泛化一些,能根據(jù)幾個名字構建起一個模塊的視圖,根據(jù)模塊的名稱構建起單個系統(tǒng)的視圖,根據(jù)單個系統(tǒng)命名構建起整個業(yè)務的視圖。

5、輔助工具

(1)敏捷開發(fā)

敏捷開發(fā)是一種軟件開發(fā)方法,它是在 1990 年代末期出現(xiàn)的,其思想涉及如何使軟件開發(fā)更加輕量,靈活和增量。

敏捷開發(fā)中最重要的元素之一是開發(fā)應該是漸進的和迭代的概念。在敏捷方法中,軟件系統(tǒng)是通過一系列迭代開發(fā)的,每個迭代都添加并評估了一些新功能。

現(xiàn)代的敏捷開發(fā)思想已經(jīng)融合進了devops、持續(xù)集成等工具當中,在企業(yè)中可以使用現(xiàn)成的工具來實現(xiàn)軟件開發(fā)的快速驗證及迭代,開源工具也有很多。比如Jenkins。

持續(xù)集成工具中集成了很多有用的工具,比如靜態(tài)代碼檢查、單元測試、自動化測試、預合并、自動部署等功能。

(2)Coca

Coca是一個用于系統(tǒng)重構、系統(tǒng)遷移和系統(tǒng)分析的瑞士軍刀。它可以分析代碼中的 badsmell,行數(shù)統(tǒng)計,分析調用與依賴,進行 Git 分析,以及自動化重構等。

借助coca工具,可以實現(xiàn)快速掌握系統(tǒng)整體的情況,比如重點方法調用圖、類之間關系、系統(tǒng)命名健康情況、代碼質量評估等。

示例一:類依賴關系

系統(tǒng)設計之怎么降低復雜性

示例二:方法調用圖

系統(tǒng)設計之怎么降低復雜性

示例三:變量命名出現(xiàn)次數(shù)統(tǒng)計

+------------------+--------+
|      WORDS       | COUNTS |
+------------------+--------+
| context          |    590 |
| resolve          |    531 |
| path             |    501 |
| content          |    423 |
| code             |    416 |
| resource         |    373 |
| property         |    372 |
| session          |    364 |
| attribute        |    349 |
| properties       |    343 |
| headers          |    330 |
+------------------+--------+

示例四:代碼質量評估

+--------------------------------+-------+-----------------------+-------+-----------+
|              TYPE              | COUNT |         LEVEL         | TOTAL |   RATE    |
+--------------------------------+-------+-----------------------+-------+-----------+
| Nullable / Return Null         |     0 | Method                |  1615 | 0.00%     |
| Utils                          |     7 | Class                 |   252 | 2.78%     |
| Static Method                  |     0 | Method                |  1615 | 0.43%     |
| Average Method Num.            |  1615 | Method/Class          |   252 |  6.408730 |
| Method Num. Std Dev / 標準差   |  1615 | Class                 | -     |  7.344917 |
| Average Method Length          | 13654 | Without Getter/Setter |  1100 | 12.412727 |
| Method Length Std Dev / 標準差 |  1615 | Method                | -     | 20.047092 |
+--------------------------------+-------+-----------------------+-------+-----------+

到此,相信大家對“系統(tǒng)設計之怎么降低復雜性”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI