大綱
什麼是軟體複用?
如何衡量“可複用性”?
可複用元件的級別和形態
- 原始碼級別複用
- 模組級別的複用:類/抽象類/介面
- 庫級別的複用:API /包
- 系統級別的複用:框架
對可複用性的外部觀察
- 型別變化
- 例行分組
- 實施變更
- 代表獨立
- 分解常見行為
總結
什麼是軟體複用?
軟體複用
軟體複用是使用現有軟體元件實施或更新軟體系統的過程。
軟體複用的兩個觀點
- 建立:以系統方式建立可複用資源(面向複用程式設計:開發出可複用的軟體)
- 使用:複用資源作為建立新系統的構建塊(基於複用程式設計:利用已有的可複用軟體搭建應用系統)
為什麼複用?
- “創造可重複使用而不是暫時性文物的動力具有審美和知識以及經濟動機,並且是人類對不朽渴望的一部分。
- 它將人與其他生物區分開來,並從原始社會文明“(Wegner,1989)。
為什麼複用?
重複使用具有成本效益,並且具有及時性降低成本和開發時間
- 通過縮短軟體生產週期時間來提高軟體生產力(開發速度更快,人員更少的軟體)
- 不浪費資源不必要地“重新發明輪子”
- 降低維護成本(可生產更好的質量,更可靠和更高效的軟體)
經過充分測試,可靠,穩定,生成可靠的軟體
- 重複使用已經存在一段時間並被除錯的功能是構建穩定子系統的基礎
重複使用標準化,在不同應用中保持一致
- 複用GUI庫可在應用程式中產生常見的外觀。
- 與常規,一致的設計保持一致。
重複使用成本
可複用元件的設計和構建應該採用明確,開放的方式,具有簡潔的介面規範,易於理解的文件以及面向未來的使用。做到這些,需要代價。
複用成本很高:涉及跨越組織,技術和流程變更,以及支援這些變更的工具成本,以及培訓人員使用新工具和變更的成本。 不僅面向複用程式設計代價高,基於複用程式設計代價也高
面向複用開發:開發可複用的軟體
可複用元件的開發成本高於特定等價物的成本。 這種額外的可複用性增強成本應該是一個組織而不是專案成本。 開發成本高於一般軟體的成本:要有足夠高的適應性
通用元件的空間效率可能較低,執行時間可能長於其特定的等效項。 效能差些:針對更普通場景,缺少足夠的針對性。
基於複用開發:使用已有軟體進行開發
必須開發和維護用於體系結構,設計,文件和程式碼的元件管理工具,例如儲存庫。可複用軟體庫,對其進行有效的管理
一個關鍵問題:適應往往無法拿來就用,需要適配
- 可能需要將額外的功能新增到元件。 新增完成後,新元件可以重新使用。
- 可以從元件中刪除不需要的功能,以提高其效能或減少其空間要求
- 某些元件操作的實現可能需要修改。
如何衡量“可複用性”?
衡量可複用性
軟體資產在不同應用場景中的重複使用頻率如何?
- 資產使用的可能性越高,其可複用性越高。
- 編寫一次,重複使用多次。
為重複使用此資產需支付多少費用?
- 購買資產和其他強制性庫的成本
- 調整和擴充套件它的成本
- 例項化它的成本
- 更改與其互動的系統的其他部分的成本
可複用性
可複用性意味著對構建,打包,分發,安裝,配置,部署,維護和升級問題進行一些明確的管理。
具有高可複用性的軟體資產應該:
- 簡短(小尺寸)和簡單(低複雜度)
- 行動式和標準合規性
- 適應性和靈活性
- 可擴充套件性
- 通用和引數化
- 模組化
- 易變(可變)設計假設的本地化
- 改變要求時的穩定性
- 豐富的文件
可重複使用元件的級別和形態
複用水平
可複用元件可能是程式碼
- 最普遍:大多數程式設計師與複用有關
但是,從更廣泛和更高層次上看待可以重複使用的觀點帶來的好處。
- 要求
- 設計和規格
- 資料
- 測試用例
- 檔案
我們在這節課中關注的是什麼
原始碼級別:方法,語句等
模組級別:類和介面
庫級別:API
- Java庫,.jar
架構級別:框架框架
程式碼複用的型別
白盒複用:原始碼可見,可修改和擴充套件
- 程式碼本身可用時複用程式碼。 通常需要某種修改或改編
- Pro:您可以自定義模組以適應特定的情況,這允許在更多情況下複用
- Con:你現在擁有自定義的結果,所以它增加了你的程式碼複雜度。 您需要內部元件的內在知識。
黑盒複用:原始碼不可見,不能修改
- 通過提供一些“膠水”來重新組合現有程式碼的形式,但不必更改程式碼本身 – 通常是因為您無法訪問程式碼。只能通過API介面來使用,無法修改程式碼
- Pro:簡潔和清潔
- Con:很多時候這是不可能的
可複用元件分佈的格式
形式:
- 原始碼
- 包,如.jar,.gem,.dll,
可複用軟體元件的來源:
- 組織的內部程式碼庫(Guava)
- 第三方提供的庫(Apache)
- 語言自己提供的庫(JDK)
- 來自教程,示例,書籍等的程式碼示例
- 原生程式碼專家或知識淵博的同事
- 現有的系統程式碼
- 開源產品(請務必遵守任何許可協議)
(1)原始碼複用
複用程式碼 – 最低階別
將部分/全部複製/貼上到您的程式中
維護問題
- 需要在多個地方更正程式碼
- 使用太多的程式碼(很多版本)
過程中出現錯誤的風險很高
可能需要知道如何使用的軟體工作
需要訪問原始碼
(2)模組級複用:類/介面
複用類
類是程式碼複用的原子單元
- 不需要原始碼,類檔案或jar / zip
- 只需要包含在類路徑中
- 可以使用javap工具來獲取類的公共方法頭
文件非常重要(Java API)
封裝有助於複用
程式碼管理較少
版本控制,向後相容性仍然存在問題
需要一起打包相關的類 – 靜態連結
複用類的方法:繼承
Java提供了一種名為Inheritance的程式碼複用方法
- 類擴充套件現有類的屬性/行為
- 另外,他們可能會覆蓋現有的行為
不需要放置僅僅轉發或委託工作的虛擬方法
更好地捕捉現實世界
通常需要在實現之前設計繼承層次結構
無法取消屬性或方法,因此一定要小心,不要過分
複用類的方法:委託
委託只是當一個物件依賴另一個物件來實現其功能的某個子集時(一個實體將某個事物傳遞給另一個實體)
- 例如分揀機正在委託比較器的功能
審慎的委託支援程式碼複用
- 分揀機可以重複使用任意的排序順序
- 比較器可以重複使用需要比較整數的任意客戶端程式碼
顯式委託:將傳送物件傳遞給接收物件
隱式委託:由語言的成員查詢規則
委託可以被描述為在實體之間共享程式碼和資料的低階機制。
(3)庫級複用:API /包
庫:一組提供可複用功能的類和方法(API)
框架:可以定製到應用程式中的可重複使用的框架程式碼
框架呼叫回客戶端程式碼
- 好萊塢原則:“不要打電話給我們。 我們會打電話給你。“
一般區別:庫與框架
框架作為主程式加執行,執行過程中呼叫開發者所寫的程式
開發者構造可執行軟體實體,其中涉及到對可複用庫的呼叫
(4)系統級複用:框架
應用程式框架
框架是子系統設計,包含一系列抽象和具體類以及每個類之間的介面
框架:一組具體類,抽象類,及其之間的連線關係 – 只有“骨架”,沒有“血肉”
框架是一種抽象,其中提供通用功能的軟體可以通過額外的使用者編寫的程式碼進行選擇性更改,從而提供特定於應用程式的軟體。 開發者根據框架的規約,填充自己的程式碼進去,形成完整系統
可複用性利用了應用領域知識和經驗豐富的開發人員的先前努力
- 資料處理,圖形使用者介面等
- 將框架看作是更大規模的API複用,除了提供可複用的API,還將這些模組之間的關係都確定下來,形成了整體應用的領域複用
框架:領域複用
系統通過新增元件來填充缺失的設計元素並例項化抽象類來實現
- 通常通過選擇性覆蓋來擴充套件框架; 或者程式設計師可以新增專門的使用者程式碼來提供特定的功能—定義從抽象類祖先繼承操作的具體類
- 鉤子方法,被應用程式覆蓋以擴充套件框架。 鉤子(Hook)方法系統地將應用程式域的介面和行為與應用程式在特定上下文中所需的變體解耦。
- 控制反轉:與庫或標準使用者應用程式不同,控制流不是由呼叫者決定的,而是由框架決定的。
- 不可修改的框架程式碼:框架程式碼不應該被修改,同時接受使用者實現的擴充套件。 換句話說,使用者可以擴充套件框架,但不應修改其程式碼。
控制反轉(Inverse of Control)
由第三方的容器來控制物件之間的依賴關係,而非傳統實現中由程式碼直接操控。
控制權由程式碼中轉到了外部容器,帶來的好處就是降低了物件之間的依賴程度,提高靈活性和可維護性。
框架設計
框架與應用程式不同
- 抽象級別不同,因為框架為相關問題家族提供解決方案,而不是單一解決方案。
- 為了適應這一系列問題,該框架是不完整的,包含熱點和掛鉤以允許定製
框架可以用擴充套件它們的技術來分類。
- 白盒框架
- 黑盒框架
白盒和黑盒框架
白盒框架:
- 通過繼承和動態繫結實現的可擴充套件性。
- 通過繼承框架基類並重寫預定義的鉤子方法來擴充套件現有功能
- 通常使用模板方法模式等設計模式來覆蓋鉤子方法。
黑盒框架
- 通過為可插入框架的元件定義介面來實現可擴充套件性。
- 通過定義符合特定介面的元件來複用現有功能
- 這些元件通過委託與框架整合。
類庫與框架
類庫:
- 較少的域特定
- 提供更小的複用範圍。
- 類庫是被動的; 對控制流程沒有限制。
框架:
- 類為相關應用系列合作。
- 框架活動; 影響控制流程。
在實踐中,開發人員經常使用兩種:
- 框架通常在內部使用類庫來簡化框架的開發。
- 框架事件處理程式使用類庫來執行基本任務(例如字串處理,檔案管理,數值分析……)。
元件與框架
元件
- 類的獨立例項
- 連線在一起形成完整的應用程式。
- 黑盒定義了一套連貫的操作,
- 可以基於介面的語法和語義使用。
- 元件甚至可以在二進位制程式碼級複用。
•優點是應用程式不一定需要在元件更改時重新編譯。
構架:
- 經常用於開發元件
- 元件通常插入黑盒框架。
可複用性的外部觀察
對可複用性的外部觀察
型別可變
功能分組
實現可變
表示獨立
共性抽取
型別可變
可複用元件應該是型別引數化的,以便它們可以適應不同的資料型別(輸入,計算和輸出);
- 可重複使用的模組應該適用於許多不同型別的元素,而不需要開發人員對軟體文字進行手動更改。
換句話說,我們需要一個用於描述型別引數化模組的工具,這個模組也被稱為通用模組。
通用性:可複用元件應該是通用的。
型別可變(泛型):適應不同的型別,且滿足LSP
實現可變
在實踐中有很多種適用的資料結構和演算法。
我們不能期望單個模組能夠處理所有可能性,這種變化確實是這樣; 這將是巨大的。
我們需要一系列模組來涵蓋所有不同的實現。
實現可變:ADT有多種不同的實現,提供不同的表示和抽象功能,但具有同樣的規範(前置條件,後置條件,不變式),從而可以適應不同的應用場景
功能分組
一個自給自足的可複用模組需要包含一組功能,每個操作一個功能。
完整性
提供完備的細粒度操作,保證功能的完整性,不同場景下複用不同的操作(及其組合)
表示獨立性
可複用模組的一般形式應該使客戶能夠指定一個操作而不知道它是如何實現的。
表示獨立性是資訊隱藏規則的延伸,對於大型系統的順利開發至關重要:實施決策經常會改變,客戶應該受到保護。 內部實現可能會經常變化,但客戶端不應受到影響。
表示獨立反映了客戶對可複用性的看法 – 忽略內部實現細節和變體的能力
表示獨立性,資訊隱藏
共性抽取
分解共同行為,反映了供應商的觀點,更一般地反映了可複用類的開發者的觀點。
目標是利用家庭或實施子系列中可能存在的任何通用性。
將共同的行為(共性)抽象出來,形成可複用實體
如上所述,在某些問題領域可用的各種實現通常需要基於模組族的解決方案。
這些類別中的每一個都涵蓋了許多變體,但通常可以在這些變體之間找到顯著的共性。
總結
什麼是軟體複用?
如何衡量“可複用性”?
可複用元件的級別和形態
- 原始碼級別複用
- 模組級複用:類/介面
- 庫級:API /包
- 系統級複用:框架
對可複用性的外部觀察
- 型別可變
- 功能分組
- 實現可變
- 表示獨立
- 共性抽取