軟件維護和演變
可維護性度量
模塊化設計和模塊化原則
OO設計原則:SOLID
OO設計原則:GRASP
總結程序員
什麼是軟件維護?編程
軟件工程中的軟件維護是交付後修改軟件產品以糾正故障,提升性能或其餘屬性。軟件維護:修復錯誤,改善性能
在「ISO / IEC 14764:2006軟件工程 - 軟件生命週期過程 - 維護」設計模式
運維工程師安全
維護是軟件生產中最困難的方面之一,由於維護包含了全部其餘階段的各個方面
用戶報告故障並由維護工程師處理。網絡
維護工程師必須具有出色的調試技能app
軟件維護的類型運維
糾正性維修25%糾錯性編輯器
適應性維護21%適應性模塊化
完善性維護50%完善性函數
預防性維護4%預防性
雷曼關於軟件演化的規律(Lehman’s Laws on Software Evolution)
反饋系統
持續變化
持續增加
質量降低
增長複雜性
自我調節
軟件維護和進化的目標
軟件維護和演化的目標:爲了提升軟件的適應性和適應性,並保持其活力,即「長期軟件(低熵軟件)」
提升軟件的適應性,延續軟件生命
Linux內核發展的一個例子:可維護性指數
維護不只僅是op工程師的任務......
維護不只僅是維護和操做工程師的任務,也是軟件設計人員和開發人員的潛在任務。 軟件維護不只僅是運維工程師的工做,而是從設計和開發階段就開始了
對他們來講,在設計和施工階段必須考慮軟件的將來潛在變化/擴展;在設計與開發階段就要考慮未來的可維護性
所以,靈活和可擴展的設計/結構被全面考慮,換句話說,「易於改變/擴展」。 設計方案的「容易改變」
這就是所謂的軟件構建的「可維護性」,「可擴展性」和「靈活性」。
可維護性建設的例子
模塊化設計與實現模塊化
OO設計原則OO設計原則
OO設計模式OO設計模式
基於狀態的構造技術(自動機編程)
表驅動的構造技術
基於語法的構造技術(Grammar-based construction)
許多可維護性的名字
可維護性
可擴展性
靈活性
可適應性
可管理性
可支持性
有關可維護性的問題
Code review的時候常常問的關於可維護性的問題:
一些經常使用的可維護性度量標準
圈複雜度 - 測量代碼的結構複雜度。
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之間的索引值,表示維護代碼的相對容易性。 高價值意味着更好的可維護性。 它的計算基於:
一些經常使用的可維護性度量標準
繼承的層次數
類之間的耦合度
單元測試覆蓋率
模塊化編程
模塊化編程是一種強調將程序功能分離爲獨立,可互換模塊的設計技術,每種模塊都包含執行所需功能一個方面所需的一切。
將整個程序的代碼高度分解爲結構化編程和OOP。
模塊化編程設計的目標是將系統劃分爲模塊,並經過如下方式在組件之間分配責任:
模塊化下降了程序員在任什麼時候候都必須處理的整體複雜性,假設:
內聚和耦合的原則多是評估設計可維護性的最重要的設計原則。
(1)評估模塊性的五個標準
Decomposability(可分解性)
Composability(可組合性)
Understandability(可理解性)
Continuity(可持續性)
Protection(出現異常以後的保護)
(2)模塊化設計的五條原則
Direct Mapping (直接映射)
Few Interfaces (儘量少的接口)
Small Interfaces (儘量小的接口)
Explicit Interfaces (顯式接口)
Information Hiding (信息隱藏)
(3)耦合和內聚
耦合
耦合是模塊之間依賴關係的度量。 若是兩個模塊之間的變化可能須要另外一個模塊的變動,則兩個模塊之間存在依賴關係。
模塊之間的耦合度取決於:
HTML,CSS和JavaScript之間的耦合
一個精心設計的網絡應用程序模塊化:
內聚
內聚是衡量一個模塊的功能或責任有多強烈程度的一個指標。
若是一個模塊的全部元素都朝着相同的目標努力,那麼它就具備很高的內聚。
最好的設計在模塊內具備高內聚力(也稱爲強內聚力)和模塊之間的低耦合(也稱爲弱耦合)。
SOLID: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:
若是一個類包含了多個責任,那麼將引發不良後果:
SRP是原則中最簡單的一種,也是最難作到的一種。(最簡單的原則,倒是最難作好的原則)
類應擴展(對擴展性的開放)
但關閉修改。(對修改的封閉)
Key:abstraction(關鍵的解決方案:抽象技術)
「軟件實體(類,模塊,函數等)應該被打開以進行擴展,可是爲了修改而關閉」,即,使用繼承和組合來改變類的行爲
開放封閉原則 - 幾個問題...。
不可能在不修改GraphEditor的狀況下添加新的Shape
重要的是要了解GraphEditor添加一個新的形狀
GraphEditor和Shape之間的緊密耦合
不參與GraphEditor就很難測試特定的Shape
If-Else-/Case應該被避免
OCP表示單一選擇
只要軟件系統必須支持一組替代方案,系統中的一個且只有一個模塊應該知道他們的詳盡列表。
編輯器:一組命令(插入,刪除等)
圖形系統:圖形類型集(矩形,圓形等)
編譯器:語言結構集(指令,循環,表達式等)
「使用指針或對基類的引用的函數必須可以使用派生類的對象而不知道它」,即,子類在使用它們的基類時應該表現得很好
LSP:子類型必須可替代其基本類型。(子類型必須可以替換其基類型)
派生類必須能夠經過基類接口使用,而不須要客戶端了解其差別。 (派生類必須可以經過其基類的接口使用,客戶端無需瞭解兩者之間的差別)
在第5-2節中已經討論過可複用性。
「客戶不該該被迫依賴他們不使用的接口」,即保持接口小。
不要強制類來實現它們不能實現的方法(Swing / Java)
不要用不少方法污染界面
避免「胖」的接口
客戶不該該被迫依賴他們不使用的方法。(客戶端不該依賴於它們不須要的方法)
接口屬於客戶端,而不屬於層次結構。
這個原則處理「胖」接口的缺點。(「胖」接口具備不少缺點)
具備「胖」接口的類是接口不具備內聚性的類。(不夠聚合)
高級模塊不該該依賴於低級模塊。 二者都應該取決於抽象。
應該使用大量的接口和抽象!
爲何DIP?
優勢:
嘗試設計測試
例如:你會避免循環依賴。 若是您必須從UI單獨測試,業務邏輯將更好地與UI代碼隔離
什麼是GRASP模式
通常責任分配軟件模式(原則),縮寫爲GRASP,包含爲OOP中的類和對象分配責任的準則。
GRASP模式是幫助理解基本對象設計的學習輔助,並以有條理,合理,可解釋的方式應用設計推理。
這種理解和使用設計原則的方法是基於對班級分配責任的模式。
GRASP是關於如何爲「類」和「對象」指派「職責」的一系列原則
什麼是責任
對象的責任:與對象的義務有關
瞭解:
這樣作:
軟件維護和演變可維護性度量模塊化設計和模塊化原則OO設計原則:SOLIDOO設計原則:GRASP