構件
適用於軟體工程領域的零件
構件是系統中實際存在的可更換部分。它實現特定的功能,符合一套介面標準並能實現一組介面。
在工程實際操縱中,各種機械與結構得到廣泛應用。組成機械與結構的零、構件,在工程力學中統稱為構件。
機器中每一個獨立的運動單元體稱為一個構件。
[structural member]∶機構的組成單個元,它是一個和某相鄰構件有相對運動的剛體。
橋樑構架;抗壓構件的設計。
[component part]∶組成部(分)。
電動機的各種構件人財產。
在機構學中組成機構的﹑彼此間具有確定的相對運動關係的基本單元﹐如曲柄滑塊機構中的曲柄﹑連桿﹑滑塊和機架﹐凸輪機構中的凸輪﹑從動桿和機架。在結構學中則指結構物中的計算或製造單元﹐它們是固定在一起的﹐彼此間除由於應變有微量位移外﹐沒有相對運動﹐如梁﹑柱﹑拉杆等。
軟體工程中的構件
軟體構件應具備以下屬性
(1)有用性(Usefulness):構件必須提供有用的功能;
(2)可用性(Usability):構件必須易於理解和使用;
(3)質量(Quality):構件及其變形必須能正確工作;
(4)適應性(Adaptability):構件應該易於通過參數化等方式在不同語境中進行配置;
(5)可移植性(Portability):構件應能在不同的硬體運行平台和軟體環境中工作。
日曆、工作流構件、訂單構件、用戶界面控制等等都可以是構件。
2.1.3 構件的特點
構件具有以下幾個特點:
(1)自描述:構件必須能夠識別其屬性、存取方法和事件,這些信息可以使開發環境將第三方軟體構件無縫地結合起來;
(2)可定製:允許提供一個典型的圖形方式環境,軟體構件的屬性只能通過控制面板來設置;
(4)連接機制:構件必須能產生事件或者具有讓程序員從語義上實現相互連接的其他機制。
採用構件軟體不需要重新編譯,也不需要源代碼並且不局限於某一種編程語言。該過程叫做二進位復用(Binary Reuse),因為它是建立在介面而不是源代碼級別的復用之上的。雖然軟體構件必須遵守一致的介面,但是它們的內部實現是完全自動的。因此,可以用過程語言和面向對象語言創建構件。
由於構件技術是由基於面向對象技術而發展起來的,與面向對象的設計中的對象相類似,它們都是針對軟體復用,都是被封裝的代碼,但它們之間仍存在很大差異。
差別
(1)在純面向對象的設計中,對象(類)、封裝和繼承三者缺一不可,但對構件可以沒有繼承性,只要實現封裝即可;
(2)從構件和對象的生成方式上,對象生成屬於實例化的過程,比較單一,而生成構件的方式較多;
(3)構件是設計的概念,與具體編程語言無關,不像對象屬於編程中的概念,要依賴於具體的編程語言;
(4)在對構件操作時不允許直接操作構件中的數據,數據真正被封裝了。而對象的操作通過公共介面部分,這樣數據是可能被訪問操作的;
(5)對象對軟體復用是通過繼承實現的,構件對軟體復用不僅可以通過繼承還可以通過組裝時的引用來實現。
因此,構件不是對象,只是與對象類似。
從力學角度來說,結構是指可以承受一定力的結構形態,它可以抵抗能引起形狀和大小改變的力。每種事物都有它的架構形態,這種架構形態體現著它的結構。一個較複雜的結構由許多不同的部分組成,這些組成部分通常成為構件。
構件是系統中實際存在的可更換部分,它實現特定的功能,符合一套介面標準並實現一組介面。構件代表系統中的一部分物理實施,包括軟體代碼(源代碼、二進位代碼或可執行代碼)或其等價物(如腳本或命令文件)。
構件化技術服務流程
有關如何將設計類映射為代碼的詳細信息,請參見活動:實施構件。另請參見指南:類。
實施構件與修改構件在項目的配置管理環境中進行。實施員在為他們提供的專用開發工作區(請參見活動:創建開發工作區)中,按照工件:工作單所指定的內容開展工作。在該工作區中,創建源元素並將其置於配置管理之下,或者在通常的檢出、編輯、構建、單元測試、檢入周期中進行修改(請參見活動:進行變更)。完成某個構件集(根據一個或多個工作單的定義以及即將生成的工作版本要求)后,實施員將把有關新的和修改過的構件交付(請參見活動:交付變更內容)到子系統集成工作區,以便與其他實施員的工作進行集成。最後,實施員可以在方便的時候對專用開發工作區進行更新(或者重新調整基線),使該工作區與子系統集成工作區保持一致(請參見活動:更新工作區)。
當實施類時,應遵循編程指南。
實施的主要基礎是具有公有操作、屬性與關聯關係的類。務必要注意,並不是所有公有操作、屬性與關聯關係都在設計過程中定義。
實施的輔助基礎是用例實現,用例實現顯示了類和對象如何通過交互來執行用例。
最好以遞增的方式實施類;編譯、鏈接和運行一些回歸測試,每天進行三兩次。
在從零開始實施一個類之前,可考慮修改現有的實施類(一般可通過建立子類或進行實例化來修改)。
要實施操作,請執行以下步驟:
選擇演演算法
選擇適合演演算法的數據結構
根據需要定義新的類和操作
編寫操作代碼
許多操作都十分簡單,可以從該操作及其規約中立即實施。
之所以需要特殊演演算法,主要是為了實施定義了規約的複雜操作,並優化那些以簡單但卻低效的演演算法為定義的操作。
選擇適合演演算法的數據結構
選擇演演算法包括選擇演演算法所基於的數據結構。許多實施數據結構是容器類,例如數組、列表、隊列、棧、集合、無序單位組,以及這些類的各種不同形式。許多面向對象的語言和編程環境都提供了具有這些可復用構件的類庫。
根據需要定義新的類和操作
比如,可以使用新類來保存中間結果,也可對類添加新的低級操作來分解複雜操作。通常,這些操作是類的私有操作,所以在類之外看不見這些操作。
編寫操作代碼
要編寫操作的代碼,可從介面語句開始,例如 C++ 中的成員函數聲明、Ada 中的子程序規約或 Visual Basic 中的方法。請遵循編程指南。
對象的狀態可通過引用其屬性值來實施,而不必作特殊說明。這種對象的狀態轉移將隱含於變化的屬性值中,而變化的行為通過條件語句來編程。但對於複雜行為,該方法不能令人滿意,因為它往往會導致複雜的結構;而當添加更多狀態或當行為發生變化時,將很難更改這些結構。
如果構件(或其組成部分)的行為隨狀態而定,則通常會有一個或多個狀態圖來說明組成該構件的模型元素的行為。這些狀態圖可用作實施過程中的重要輸入。有關詳細信息,請參見指南:狀態圖。
狀態圖中所示的狀態機將表現對象的狀態,並詳盡說明狀態轉移及所需的行為。可以通過以下幾種方法來實施狀態機:
對於簡單的狀態機,定義一項列舉可能狀態的屬性,然後使用該屬性在 Java 或 C++ 中的 switch 語句中選擇進入消息的行為。但這種方法不太適用於複雜的狀態機,它可能會導致運行時性能降低。如需此方法的示例,請參見 [DOUG98],第 4 章 4.4.3
對於較複雜的狀態機,可使用狀態模式。有關狀態模式的說明,請參見 [GAM94]。[DOUG98],第 6 章 6.2.3 狀態模式也說明了這種方法
表驅動法對於極複雜的狀態機十分有效,其特點是易於變更。當使用這種方法時,各個狀態在表中都有相應的條目,這些條目將輸入映射到後繼狀態和相關的轉移動作。如需此方法的示例,請參見 [DOUG98],第 6 章 6.2.3 狀態表模式。
要實施具有并行子狀態的狀態機,可以將狀態管理委派給主動對象(每個對象都被委派一個并行子狀態),因為并行子狀態代表了獨立的計算(但仍可能進行交互)。每個子狀態均可通過上述方法之一來進行管理。
通過委託關係復用實施
如果一個類或一個類的某些部分可通過復用現有類來實施,則應通過委託關係(而不要繼承)來實現。
委託表示一個類藉助於其他類來得以實施。該類通過使用變數來引用其他類的對象。當調用某操作時,該操作將調用被引用對象(屬於被複用的類)中的操作,以實際執行該操作。這樣,它就將職責委派給了其他類。
單向關聯關係將作為指針(包含對象引用的屬性)來進行實施。如果多重性為一,則將單向關聯關係當作簡單指針來實施。如果多重性為多個,則將其當作指針集來實施。但如果“多”端是有序排列的,則可以使用列表,而不使用集合。
雙向關聯關係將作為屬性,使用單向關聯關係的技術在兩個方向上實施。
限定關聯關係將作為限定對象中的查詢表(如一個 Smalltalk Dictionary 類)來實施。查詢表中的選擇器值是限定詞,而目標值是另一個類的對象。
如果必須按順序訪問限定詞的值,就應將限定片語織成經過排序的數組或樹。在這種情況下,訪問時間將與 log N 成比例,其中 N 為限定詞值的數目。
如果限定詞取自於一個緊湊的有限集,就可以將限定詞的值映射到一個整數範圍,並將關聯關係當作數組來有效地進行實施。如果關聯關係已基本上填滿(而不是稀疏填充),此方法會更加有效;而對於完全填滿的有限集,它可以算是理想的方法。
許多面向對象的語言和編程環境都提供了具有可復用構件的類庫,可用於實施不同種類的關聯關係。
可以作為內置基本變數、可復用的構件類或定義一個新類來實現屬性。定義新類通常是較為靈活的方法,但它卻會帶來不必要的間接性。例如,實施僱員的社會保障號時,既可將它作為類型“字元串”的屬性,也可將它作為一個新類。另一種可能的情況是:屬性組組成了新類。
向設計提供反饋
在以上任何步驟中,如果發現了設計錯誤,都必須向設計提供返工反饋。如果所需的變更較小,就可以由同一個人來設計並實施類,而無需提出正式的變更請求。他可在設計中進行變更。
如果所需的變更影響到幾個類(例如在公有操作中的變更),則應向 CCB(變更控制委員會)提交正式的變更請求。請參見活動:修復缺陷。
在開始單元測試之前,可以先作一些檢查。測試是一項花費較多的工作,因此最好先執行以下幾項檢查:
始終對代碼進行編譯。將編譯器的警告等級設置到最詳細的程度。
通過想像對操作進行檢查。通讀代碼,儘可能考慮到所有情況,發現各種異常情況。一旦進行了新的實施活動,就需進行此項工作。
使用工具檢查代碼中是否存在錯誤。例如,使用靜態代碼規則檢查程序。
部署構件的示例 |
可執行文件例如 .exe 文件
鏈接庫例如 .dll 文件
Applet 例如 Java 中的 .class 文件
Web 頁面例如 .htm 和 .html 文件
資料庫表
工作產品構件的示例
源代碼文件例如 C++ 和 CORBA IDL 中的 .h、.cpp 和 .hpp 文件,或 Java 中的 .java 文件二進位文件例如鏈接到可執行文件的 .o 文件和 .a 文件。SOM 文件IDL 和一些綁定編譯文件例如 UNIX 中的 makefile
使用
設計中的類和對象被作為部署構件進行實施。您需要確定如何將設計類映射為代碼;這應該在項目專用的設計指南中有所說明。
有關如何將設計類映射為代碼的詳細信息,請參見活動:實施構件。另請參見指南:類。
實施構件與修改構件在項目的配置管理環境中進行。實施員在為他們提供的專用開發工作區(請參見活動:創建開發工作區)中,按照工件:工作單所指定的內容開展工作。在該工作區中,創建源元素並將其置於配置管理之下,或者在通常的檢%8D%95%E5%85%83%E6%B5%8B%E8%AF%95" target="_new" class=innerlink>單元測試、檢入周期中進行修改(請參見活動:進行變更)。完成某個構件集(根據一個或多個工作單的定義以及即將生成的工作版本要求)后,實施員將把有關新的和修改過的構件交付(請參見活動:交付變更內容)到子系統集成工作區,以便與其他實施員的工作進行集成。最後,實施員可以在方便的時候對專用開發工作區進行更新(或者重新調整基線),使該工作區與子系統集成工作區保持一致(請參見活動:更新工作區)。
當實施類時,應遵循編程指南。
實施的主要基礎是具有公有操作、屬性與關聯關係的類。務必要注意,並不是所有公有操作、屬性與關聯關係都在設計過程中定義。
實施的輔助基礎是用例實現,用例實現顯示了類和對象如何通過交互來執行用例。
最好以遞增的方式實施類;編譯、鏈接和運行一些回歸測試,每天進行三兩次。
在從零開始實施一個類之前,可考慮修改現有的實施類(一般可通過建立子類或進行實例化來修改)。
實施操作
要實施操作,請執行以下步驟:
選擇演演算法 選擇適合演演算法的數據結構 根據需要定義新的類和操作 編寫操作代碼 選擇演演算法許多操作都十分簡單,可以從該操作及其規約中立即實施。
之所以需要特殊演演算法,主要是為了實施定義了規約的複雜操作,並優化那些以簡單但卻低效的演演算法為定義的操作。
選擇適合演演算法的數據結構選擇演演算法包括選擇演演算法所基於的數據結構。許多實施數據結構是容器類,例如數組、列表、隊列、棧、集合、無序單位組,以及這些類的各種不同形式。許多面向對象的語言和編程環境都提供了具有這些可復用構件的類庫。
根據需要定義新的類和操作比如,可以使用新類來保存中間結果,也可對類添加新的低級操作來分解複雜操作。通常,這些操作是類的私有操作,所以在類之外看不見這些操作。
編寫操作代碼要編寫操作的代碼,可從介面語句開始,例如 C++ 中的成員函數聲明、Ada 中的子程序規約或 Visual Basic 中的方法。請遵循編程指南。
實施構件工作流程明細
實施構件工作流程明細
對象的狀態可通過引用其屬性值來實施,而不必作特殊說明。這種對象的狀態轉移將隱含於變化的屬性值中,而變化的行為通過條件語句來編程。但對於複雜行為,該方法不能令人滿意,因為它往往會導致複雜的結構;而當添加更多狀態或當行為發生變化時,將很難更改這些結構。
如果構件(或其組成部分)的行為隨狀態而定,則通常會有一個或多個狀態圖來說明組成該構件的模型元素的行為。這些狀態圖可用作實施過程中的重要輸入。有關詳細信息,請參見指南:狀態圖。
狀態圖中所示的狀態機將表現對象的狀態,並詳盡說明狀態轉移及所需的行為。可以通過以下幾種方法來實施狀態機:
對於簡單的狀態機,定義一項列舉可能狀態的屬性,然後使用該屬性在 Java 或 C++ 中的 switch 語句中選擇進入消息的行為。但這種方法不太適用於複雜的狀態機,它可能會導致運行時性能降低。如需此方法的示例,請參見【DOUG98】,第 4 章 4.4.3 對於較複雜的狀態機,可使用狀態模式。有關狀態模式的說明,請參見【GAM94】。【DOUG98】,第 6 章 6.2.3 狀態模式也說明了這種方法 表驅動法對於極複雜的狀態機十分有效,其特點是易於變更。當使用這種方法時,各個狀態在表中都有相應的條目,這些條目將輸入映射到後繼狀態和相關的轉移動作。如需此方法的示例,請參見【DOUG98】,第 6 章 6.2.3 狀態表模式。要實施具有并行子狀態的狀態機,可以將狀態管理委派給主動對象(每個對象都被委派一個并行子狀態),因為并行子狀態代表了獨立的計算(但仍可能進行交互)。每個子狀態均可通過上述方法之一來進行管理。
通過委託關係復用實施
如果一個類或一個類的某些部分可通過復用現有類來實施,則應通過委託關係(而不要繼承)來實現。
委託表示一個類藉助於其他類來得以實施。該類通過使用變數來引用其他類的對象。當調用某操作時,該操作將調用被引用對象(屬於被複用的類)中的操作,以實際執行該操作。這樣,它就將職責委派給了其他類。
實施關聯關係
單向關聯關係將作為指針(包含對象引用的屬性)來進行實施。如果多重性為一,則將單向關聯關係當作簡單指針來實施。如果多重性為多個,則將其當作指針集來實施。但如果“多”端是有序排列的,則可以使用列表,而不使用集合。
雙向關聯關係將作為屬性,使用單向關聯關係的技術在兩個方向上實施。
限定關聯關係將作為限定對象中的查詢表(如一個 Smalltalk Dictionary 類)來實施。查詢表中的選擇器值是限定詞,而目標值是另一個類的對象。
如果必須按順序訪問限定詞的值,就應將限定片語織成經過排序的數組或樹。在這種情況下,訪問時間將與 log N 成比例,其中 N 為限定詞值的數目。
如果限定詞取自於一個緊湊的有限集,就可以將限定詞的值映射到一個整數範圍,並將關聯關係當作數組來有效地進行實施。如果關聯關係已基本上填滿(而不是稀疏填充),此方法會更加有效;而對於完全填滿的有限集,它可以算是理想的方法。
許多面向對象的語言和編程環境都提供了具有可復用構件的類庫,可用於實施不同種類的關聯關係。
實施屬性
可以作為內置基本變數、可復用的構件類或定義一個新類來實現屬性。定義新類通常是較為靈活的方法,但它卻會帶來不必要的間接性。例如,實施僱員的社會保障號時,既可將它作為類型“字元串”的屬性,也可將它作為一個新類。
屬性的備選實施。
另一種可能的情況是:屬性組組成了新類,如下例所示。這兩種實施都是正確的。
將 Line 中的屬性當作 Point 類的關聯關係來實施。
向設計提供反饋
在以上任何步驟中,如果發現了設計錯誤,都必須向設計提供返工反饋。如果所需的變更較小,就可以由同一個人來設計並實施類,而無需提出正式的變更請求。他可在設計中進行變更。
如果所需的變更影響到幾個類(例如在公有操作中的變更),則應向 CCB(變更控制委員會)提交正式的變更請求。請參見活動:修復缺陷。
評估代碼
在開始單元測試之前,可以先作一些檢查。測試是一項花費較多的工作,因此最好先執行以下幾項檢查:
始終對代碼進行編譯。將編譯器的警告等級設置到最詳細的程度。通過想像對操作進行檢查。通讀代碼,儘可能考慮到所有情況,發現各種異常情況。一旦進行了新的實施活動,就需進行此項工作。使用工具檢查代碼中是否存在錯誤。例如,使用靜態代碼規則檢查程序。
一個理解術語直觀含義的方法就是列舉它的所有特性。具體的做法是這樣的:如果一樣東西具有屬性a1、a2和a3,它就是A。例如,在著名的Wegner定義(1987)里,如果一種語言支持對象、類和繼承,那麼它就可以被認為是面向對象的。
構件的特性是:
# 獨立部署單元;
# 作為第三方的組裝單元;
# 沒有(外部的)可見狀態。
這些特性有幾種含義。一個構件是獨立可部署的,意味著它必須能跟它所在的環境及其他構件相分離。因此,構件必須封裝自己全部內部特性。並且,構件作為可部署單元,具有原子性,是不可拆分的。
在這樣的約束下,如果第三方廠商能將一個構件和其他構件組裝在一起,那麼這個構件必須具備良好的內聚性,還必須將自己的依賴條件和所提供的服務說明清楚。換句話說,構件必須封裝它的實現,並且只通過良好定義的介面和外部環境進行交互。
最後,一個構件不能有任何(外部的)可見狀態——這要求構件不能與自己的拷貝有所區別。但對於不影響構件功能的某些屬性則沒有這種限制。