摘要:設計方案的容易改變這就是所謂的軟件構建的可維護性,可擴展性和靈活性。這也可能表明類型或方法可能難以維護。基于源代碼中不同運算符和操作數的數量的合成度量。對修改的封閉這種模塊的源代碼是不可侵犯的。
大綱
軟件維護和演變
可維護性度量
模塊化設計和模塊化原則
OO設計原則:SOLID
OO設計原則:GRASP
總結
什么是軟件維護?
軟件工程中的軟件維護是交付后修改軟件產品以糾正故障,提高性能或其他屬性。軟件維護:修復錯誤,改善性能
在“ISO / IEC 14764:2006軟件工程 - 軟件生命周期過程 - 維護”
運維工程師
維護是軟件生產中最困難的方面之一,因為維護包含了所有其他階段的各個方面
用戶報告故障并由維護工程師處理。
維護工程師必須具備出色的調試技能
故障可能存在于產品中的任何地方,故障的原因可能在于現在不存在的規格或設計文檔(錯誤/問題本地化)。
需要高超的診斷技能,測試技能和文檔技能(測試,修復和記錄更改)。
軟件維護的類型
糾正性維修25%糾錯性
對交付后執行的軟件產品進行無功修改,以糾正發現的問題;
適應性維護21%適應性
修改交付后執行的軟件產品,以保持軟件產品在變化或變化的環境中可用;
完善性維護50%完善性
交付后增強軟件產品以提高性能或可維護性;
預防性維護4%預防性
交付后對軟件產品進行修改,以便在軟件產品發生有效故障前檢測并糾正軟件產品中的潛在故障。
雷曼關于軟件演化的規律(Lehman’s Laws on Software Evolution)
反饋系統
持續變化
持續增長
質量下降
增加復雜性
自我調節
保持組織穩定
保持熟悉
軟件維護和進化的目標
軟件維護和演化的目標:為了提高軟件的適應性和適應性,并保持其活力,即“長期軟件(低熵軟件)”
提高軟件的適應性,延續軟件生命
Linux內核發展的一個例子:可維護性指數
維護不僅僅是op工程師的任務......
維護不僅僅是維護和操作工程師的任務,也是軟件設計人員和開發人員的潛在任務。 軟件維護不僅僅是運維工程師的工作,而是從設計和開發階段就開始了
對他們來說,在設計和施工階段必須考慮軟件的未來潛在變化/擴展;在設計與開發階段就要考慮將來的可維護性
因此,靈活和可擴展的設計/結構被全面考慮,換句話說,“易于改變/擴展”。 設計方案的“容易改變”
這就是所謂的軟件構建的“可維護性”,“可擴展性”和“靈活性”。
可維護性建設的例子
模塊化設計與實現模塊化
低耦合和高內聚力
OO設計原則OO設計原則
SOLID,GRASP
OO設計模式OO設計模式
工廠方法模式,Builder模式
橋模式,代理模式
紀念模式,狀態模式
基于狀態的構造技術(自動機編程)
表驅動的構造技術
基于語法的構造技術(Grammar-based construction)
許多可維護性的名字
可維護性
“軟件系統或組件可輕松修改以糾正故障,改善性能或其他屬性,或適應變化的環境”。
可擴展性
軟件設計/實現將未來的增長考慮在內,并被視為擴展系統能力的系統性測量以及實現擴展所需的工作量。
靈活性
軟件根據用戶需求,外部技術和社會環境等容易改變的能力。
可適應性
一種交互式系統(自適應系統)的能力,可以根據所獲得的有關其用戶及其環境的信息,使其行為適應個人用戶。
可管理性
如何有效和輕松地監控和維護軟件系統,以保持系統的正常運行,安全并平穩運行。
可支持性
基于包含質量文檔,診斷信息以及知識豐富且可用的技術人員的資源,可以有效地使軟件在部署后保持運行。
有關可維護性的問題
Code review的時候經常問的關于可維護性的問題:
結構和設計簡單:改變事物有多容易?
事情緊密或松散(即關注點分離)?
包/模塊中的所有元素是否具有凝聚力,其職責是否清晰且密切相關?
它是否具有過深的繼承層次結構,還是贊成繼承的組合?
方法定義中存在多少個獨立的執行路徑(即,cycolmatic復雜度)?
存在多少代碼重復?
一些常用的可維護性度量標準
圈復雜度 - 測量代碼的結構復雜度。
它是通過計算程序流程中不同代碼路徑的數量而創建的。
具有復雜控制流程的程序將需要更多的測試來實現良好的代碼覆蓋率,并且將不易維護。
CC = E-N + 2,CC = P + 1,CC =區域的數量
Lines of Code(代碼行數) - 表示代碼中的近似行數。
非常高的數值可能表明某種類型或方法試圖做太多工作,應該分手。
這也可能表明類型或方法可能難以維護。
對于給定的問題,令:
η_1=不同運算符的數目
η_2=不同的操作數的數量
Ν_1=運算符總數
Ν_2=操作數總數
從這些數字中可以計算出幾項度量:
程序詞匯表:η=η_1+η_2
程序長度:N=Ν_1+Ν_2
計算的程序長度:N ?=η_1 log_2?〖η_1 〗+η_2 log_2?〖η_2 〗
體積:V=N×log_2?η
難度:D=η_1/2×Ν_2/η_2
代價:E=D×V
難度測量與程序編寫或理解的難度有關
代價度量使用以下關系轉化為實際編碼時間,
編程所需的時間:T=E/18 秒
Halstead提供的錯誤(B)是對執行錯誤數量的估計。
提供的錯誤數量:B = E^(2/3)/3000或更接近的B = V/3000也被接受。
Halstead Volume:基于源代碼中(不同)運算符和操作數的數量的合成度量。
一些常用的可維護性度量標準
可維護性指數(MI)- 計算介于0和100之間的索引值,表示維護代碼的相對容易性。 高價值意味著更好的可維護性。 它的計算基于:
Halstead體積(HV)
圈復雜性(CC)
每個模塊的平均代碼行數(LOC)
每個模塊注釋行的百分比(COM)。
一些常用的可維護性度量標準
繼承的層次數
表示擴展到類層次結構的根的類定義的數量。 等級越深,就越難理解特定方法和字段在何處被定義或重新定義。
類之間的耦合度
通過參數,局部變量,返回類型,方法調用,泛型或模板實例化,基類,接口實現,在外部類型上定義的字段和屬性修飾來測量耦合到唯一類。
良好的軟件設計決定了類型和方法應該具有高內聚性和低耦合性。
高耦合表示一種設計難以重用和維護,因為它與其他類型之間存在許多相互依賴關系。
單元測試覆蓋率
指示代碼庫的哪些部分被自動化單元測試覆蓋。 (將在第7章中研究)
模塊化設計和模塊化原則模塊化編程
模塊化編程是一種強調將程序功能分離為獨立,可互換模塊的設計技術,每種模塊都包含執行所需功能一個方面所需的一切。
將整個程序的代碼高度分解為結構化編程和OOP。
模塊化編程設計的目標是將系統劃分為模塊,并通過以下方式在組件之間分配責任:
模塊內高凝聚力(高內聚)
模塊之間的耦合松耦合(低耦合)
模塊化降低了程序員在任何時候都必須處理的總體復雜性,假設:
將功能分配給將相似功能組合在一起的模塊(分離關注點)
模塊之間有小而簡單的定義明確的接口(信息隱藏)
內聚和耦合的原則可能是評估設計可維護性的最重要的設計原則。
(1)評估模塊性的五個標準
Decomposability(可分解性)
較大的組件是否分解為較小的組件?
Composability(可組合性)
較大的組件是否由較小的組件組成?
Understandability(可理解性)
組件是否可多帶帶理解
Continuity(可持續性)
規范的小改動是否會影響本地化和有限數量的組件?
Protection(出現異常之后的保護)
運行時異常的影響是否局限于少數相關組件?
(2)模塊化設計的五條原則
Direct Mapping (直接映射)
Few Interfaces (盡可能少的接口)
Small Interfaces (盡可能小的接口)
Explicit Interfaces (顯式接口)
Information Hiding (信息隱藏)
(3)耦合和內聚
耦合
耦合是模塊之間依賴關系的度量。 如果兩個模塊之間的變化可能需要另一個模塊的變更,則兩個模塊之間存在依賴關系。
模塊之間的耦合度取決于:
模塊之間的接口數量(數量)和
每個接口的復雜性(由通信類型決定)(質量)
HTML,CSS和JavaScript之間的耦合
一個精心設計的網絡應用程序模塊化:
指定數據和語義的HTML文件
規定HTML數據的外觀和格式的CSS規則
定義頁面行為/交互性的JavaScript
內聚
內聚是衡量一個模塊的功能或責任有多強烈程度的一個指標。
如果一個模塊的所有元素都朝著相同的目標努力,那么它就具有很高的內聚。
最好的設計在模塊內具有高內聚力(也稱為強內聚力)和模塊之間的低耦合(也稱為弱耦合)。
OO設計原則:SOLIDSOLID:5類設計原則
(SRP) The Single Responsibility Principle 單一責任原則
(OCP) The Open-Closed Principle 開放-封閉原則
(LSP) The Liskov Substitution Principle Liskov替換原則
(DIP) The Dependency Inversion Principle 依賴轉置原則
(ISP) The Interface Segregation Principle 接口聚合原則
“類改變不應該有一個以上的原因”,即一個類應該集中精力做一件事,只能一件事。
責任:“變更的理由”(責任:變化的原因)
SRP:
類改變不應該有一個以上的原因。 (不應有多于1個的原因使得一個類發生變化)
一個類,一個責任。(一個類,一個責任)
如果一個類包含了多個責任,那么將引起不良后果:
引入額外的包,占據資源
導致頻繁的重新配置,部署等
SRP是原則中最簡單的一種,也是最難做到的一種。(最簡單的原則,卻是最難做好的原則)
(2)開放/封閉原則(OCP)類應擴展(對擴展性的開放)
這意味著模塊的行為可以擴展。 我們可以根據應用程序的需求變化,或者為了滿足新應用程序的需求,使模塊以新的和不同的方式運行。 (模塊的行為應是可擴展的,從而該模塊可表現出新的行為以滿足需求的變化)
但關閉修改。(對修改的封閉)
這種模塊的源代碼是不可侵犯的。 沒有人可以對其進行源代碼更改。(但模塊自身的代碼是不應被修改的)
擴展模塊行為的正常方法是對該模塊進行更改。(擴展模塊行為的一般途徑是修改模塊的內部實現)
無法更改的模塊通常被認為具有固定的行為。(如果一個模塊不能被修改,那么它通常被認為是具有固定的行為)
Key:abstraction(關鍵的解決方案:抽象技術)
“軟件實體(類,模塊,函數等)應該被打開以進行擴展,但是為了修改而關閉”,即,使用繼承和組合來改變類的行為
開放封閉原則 - 幾個問題...。
不可能在不修改GraphEditor的情況下添加新的Shape
重要的是要了解GraphEditor添加一個新的形狀
GraphEditor和Shape之間的緊密耦合
不參與GraphEditor就很難測試特定的Shape
If-Else-/Case應該被避免
OCP表示單一選擇
只要軟件系統必須支持一組替代方案,系統中的一個且只有一個模塊應該知道他們的詳盡列表。
編輯器:一組命令(插入,刪除等)
圖形系統:圖形類型集(矩形,圓形等)
編譯器:語言結構集(指令,循環,表達式等)
“使用指針或對基類的引用的函數必須能夠使用派生類的對象而不知道它”,即,子類在使用它們的基類時應該表現得很好
LSP:子類型必須可替代其基本類型。(子類型必須能夠替換其基類型)
派生類必須可以通過基類接口使用,而不需要客戶端了解其差異。 (派生類必須能夠通過其基類的接口使用,客戶端無需了解二者之間的差異)
在第5-2節中已經討論過可復用性。
(4)接口隔離原理(ISP)“客戶不應該被迫依賴他們不使用的接口”,即保持接口小。
不要強制類來實現它們不能實現的方法(Swing / Java)
不要用很多方法污染界面
避免“胖”的接口
客戶不應該被迫依賴他們不使用的方法。(客戶端不應依賴于它們不需要的方法)
接口屬于客戶端,而不屬于層次結構。
這個原則處理“胖”接口的缺點。(“胖”接口具有很多缺點)
具有“胖”接口的類是接口不具有內聚性的類。(不夠聚合)
該類的接口可以分解為多組成員函數。(胖接口可分解為多個小的接口)
每個小組服務一組不同的客戶端(不同的接口向不同的客戶端提供服務)。
因此有些客戶使用一組成員函數,而其他客戶使用其他組。(客戶端只訪問自己所需要的端口)
(5)依賴倒置原理(DIP)高級模塊不應該依賴于低級模塊。 兩者都應該取決于抽象。
抽象不應該依賴于細節(抽象的模塊不應依賴于具體的模塊)
細節應該取決于抽象(具體應依賴于抽象)
應該使用大量的接口和抽象!
為什么DIP?
優點:
將類契約正式化。
您根據前置和后置條件定義例程的服務。 這非常清楚會發生什么。
嘗試設計測試
創建一個測試友好的設計
測試友好的模塊可能會展現其他重要的設計特征。
例如:你會避免循環依賴。 如果您必須從UI多帶帶測試,業務邏輯將更好地與UI代碼隔離
OO設計原則:GRASP什么是GRASP模式
一般責任分配軟件模式(原則),縮寫為GRASP,包含為OOP中的類和對象分配責任的準則。
GRASP模式是幫助理解基本對象設計的學習輔助,并以有條理,合理,可解釋的方式應用設計推理。
這種理解和使用設計原則的方法是基于對班級分配責任的模式。
GRASP是關于如何為“類”和“對象”指派“職責”的一系列原則
什么是責任
對象的責任:與對象的義務有關
了解:
了解私有封裝數據
了解相關對象
了解它可以派生或計算的事物
這樣做:
自己做一些事情,比如創建一個對象或者做一個計算
在其他對象中發起行動
控制和協調其他對象的活動。
總結軟件維護和演變
可維護性度量
模塊化設計和模塊化原則
OO設計原則:SOLID
OO設計原則:GRASP
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71346.html
摘要:大綱什么是軟件復用如何衡量可復用性可復用組件的級別和形態源代碼級別復用模塊級別的復用類抽象類接口庫級別的復用包系統級別的復用框架對可復用性的外部觀察類型變化例行分組實施變更代表獨立分解常見行為總結什么是軟件復用軟件復用軟件復用是使用現有軟件 大綱 什么是軟件復用?如何衡量可復用性?可復用組件的級別和形態 源代碼級別復用 模塊級別的復用:類/抽象類/接口 庫級別的復用:API /包 系...
摘要:建模語言建模語言是可用于表達信息或知識或系統的任何人造語言,該結構由一組一致的規則定義,目標是可視化,推理,驗證和傳達系統設計。將這些文件安排到不同的地方稱為源代碼樹。源代碼樹的結構通常反映了軟件的體系結構。 大綱 軟件構建的一般過程: 編程/重構 審查和靜態代碼分析 調試(傾倒和記錄)和測試 動態代碼分析/分析 軟件構建的狹義過程(Build): 構建系統:組件和過程 構建變體...
摘要:軟件評測師教程閱讀持續更新。。。。單元測試又稱模塊測試,是針對軟件設計的最小單位程序模塊進行正確性檢驗的測試工作其目的在于檢查每個程序單元能否正確實現詳細設計說明中的模塊功能性能接口和設計約束等要求,發現各模塊內部可能存在的各種錯誤。 軟件評測師教程閱讀持續更新。。。。 目錄大綱閱讀時間完成...
摘要:共性的步驟在抽象類內公共實現,差異化的步驟在各個子類中實現子類為每個步驟提供不同的實現。模板方法將算法的骨架定義為抽象類,允許其子類提供具體行為。迭代器依次訪問對象的元素而不暴露其基礎表示。 大綱 結構模式 Adapter允許具有不兼容接口的類通過將自己的接口包裝到已有類的接口中來一起工作。 Decorator動態添加/覆蓋對象的現有方法中的行為。 Facade為大量代碼提供簡化的界...
摘要:遵循特定規則,利用操作符,終止節點和其他非終止節點,構造新的字符串非終結符是表示字符串的樹的內部節點。語法中的生產具有這種形式非終結符終結,非終結符和運算符的表達式語法的非終結點之一被指定為根。 大綱 基于狀態的構建 基于自動機的編程 設計模式:Memento提供了將對象恢復到之前狀態的功能(撤消)。 設計模式:狀態允許對象在其內部狀態改變時改變其行為。 表驅動結構* 基于語法的構...
閱讀 1743·2021-09-22 15:25
閱讀 1307·2019-08-29 12:34
閱讀 1907·2019-08-26 13:57
閱讀 3188·2019-08-26 10:48
閱讀 1443·2019-08-26 10:45
閱讀 792·2019-08-23 18:23
閱讀 733·2019-08-23 18:01
閱讀 1944·2019-08-23 16:07