- 面向物件分析與設計 教程
- 面向物件分析與設計 - 首頁
- 面向物件分析與設計 - 面向物件正規化
- 面向物件分析與設計 - 面向物件模型
- 面向物件分析與設計 - 面向物件系統
- 面向物件分析與設計 - 面向物件原則
- 面向物件分析與設計 - 面向物件分析
- 面向物件分析與設計 - 動態建模
- 面向物件分析與設計 - 功能建模
- 面向物件分析與設計 - UML分析模型
- 面向物件分析與設計 - UML基本符號
- 面向物件分析與設計 - UML結構圖
- 面向物件分析與設計 - UML行為圖
- 面向物件分析與設計 - 面向物件設計
- 面向物件分析與設計 - 實現策略
- 面向物件分析與設計 - 測試與質量保證
- 面向物件分析與設計 有用資源
- 面向物件分析與設計 - 快速指南
- 面向物件分析與設計 - 有用資源
面向物件分析與設計 - 快速指南
面向物件分析與設計 - 面向物件正規化
簡史
面向物件正規化起源於一種新的程式設計方法的初始概念,而對設計和分析方法的興趣則來得較晚。
第一種面嚮物件語言是 Simula(模擬真實系統),由挪威計算中心的研究人員於 1960 年開發。
1970 年,艾倫·凱和他在施樂帕洛阿爾託研究中心的團隊建立了一臺名為 Dynabook 的個人電腦,以及第一種純面向物件程式語言 (OOPL) - Smalltalk,用於為 Dynabook 程式設計。
在 1980 年代,Grady Booch 發表了一篇題為“面向物件設計”的論文,主要介紹了 Ada 程式語言的設計。在隨後的版本中,他將自己的想法擴充套件到了一種完整的面向物件設計方法。
在 1990 年代,Coad 將行為思想融入面向物件方法。
其他重要的創新包括 James Rumbaugh 的物件建模技術 (OMT) 和 Ivar Jacobson 的面向物件軟體工程 (OOSE)。
面向物件分析
面向物件分析 (OOA) 是識別軟體工程需求並將軟體規範以軟體系統物件模型的形式開發的過程,該模型包含相互互動的物件。
面向物件分析與其他形式的分析的主要區別在於,在面向物件方法中,需求圍繞物件組織,物件集成了資料和函式。它們以系統互動的現實世界物件為模型。在傳統的分析方法中,這兩個方面——函式和資料——被分別考慮。
Grady Booch 將 OOA 定義為:“面向物件分析是一種分析方法,它從問題域詞彙中發現的類和物件的視角來檢查需求”。
面向物件分析 (OOA) 的主要任務包括:
- 識別物件
- 透過建立物件模型圖來組織物件
- 定義物件的內部結構或物件屬性
- 定義物件的行為,即物件動作
- 描述物件如何互動
OOA 中常用的模型包括用例和物件模型。
面向物件設計
面向物件設計 (OOD) 涉及實現面向物件分析過程中產生的概念模型。在 OOD 中,分析模型中與技術無關的概念被對映到實現類,識別約束並設計介面,從而產生解決方案域的模型,即關於如何在具體技術上構建系統的詳細描述。
實現細節通常包括:
- 重構類資料(如有必要),
- 實現方法,即內部資料結構和演算法,
- 實現控制,以及
- 實現關聯。
Grady Booch 將面向物件設計定義為:“一種設計方法,它包含面向物件分解的過程以及用於描繪正在設計系統的邏輯和物理以及靜態和動態模型的符號”。
面向物件程式設計
面向物件程式設計 (OOP) 是一種基於物件的程式設計正規化(同時具有資料和方法),旨在結合模組化和可重用性的優點。物件,通常是類的例項,用於相互互動以設計應用程式和計算機程式。
面向物件程式設計的重要特徵包括:
- 程式設計中的自下而上的方法
- 程式圍繞物件組織,並分組到類中
- 關注資料以及操作物件資料的方法
- 透過函式進行物件之間的互動
- 透過建立新類並向現有類新增功能來重用設計
面向物件程式語言的一些示例包括 C++、Java、Smalltalk、Delphi、C#、Perl、Python、Ruby 和 PHP。
Grady Booch 將面向物件程式設計定義為:“一種實現方法,其中程式被組織成協作的物件集合,每個物件都表示某個類的例項,並且所有類都是透過繼承關係聯合起來的類層次結構的成員”。
OOAD - 物件模型
物件模型以物件的術語視覺化軟體應用程式中的元素。在本章中,我們將深入瞭解面向物件系統的一些基本概念和術語。
物件和類
物件和類的概念內在關聯,構成了面向物件正規化的基礎。
物件
物件是面向物件環境中一個現實世界的元素,可能具有物理或概念上的存在。每個物件都具有:
標識,將其與系統中的其他物件區分開來。
狀態,確定物件的特徵屬性以及物件持有的屬性的值。
行為,表示物件以其狀態變化的形式執行的外部可見活動。
可以根據應用程式的需求對物件進行建模。物件可能具有物理存在,例如客戶、汽車等;或無形的概念存在,例如專案、流程等。
類
類表示具有相同特徵屬性並表現出共同行為的物件集合。它提供了可以從中建立物件的藍圖或描述。建立作為類成員的物件稱為例項化。因此,物件是類的例項。
類的組成部分包括:
要從類例項化的一組物件的屬性。通常,一個類的不同物件在屬性的值上存在一些差異。屬性通常稱為類資料。
一組操作,描述類的物件的屬性。操作也稱為函式或方法。
示例
讓我們考慮一個簡單的類 Circle,它表示二維空間中的幾何圖形圓。該類的屬性可以識別如下:
- x-coord,表示中心的 x 座標
- y-coord,表示中心的 y 座標
- a,表示圓的半徑
其一些操作可以定義如下:
- findArea(),計算面積的方法
- findCircumference(),計算周長的的方法
- scale(),增加或減少半徑的方法
在例項化期間,至少為某些屬性分配值。如果我們建立一個物件 my_circle,我們可以分配如下值:x-coord:2,y-coord:3,a:4 來描述其狀態。現在,如果在 my_circle 上執行操作 scale(),縮放因子為 2,則變數 a 的值將變為 8。此操作會改變 my_circle 的狀態,即物件表現出某些行為。
封裝和資料隱藏
封裝
封裝是將屬性和方法都繫結到類中的過程。透過封裝,可以隱藏類的內部細節。它允許僅透過類提供的介面從外部訪問類的元素。
資料隱藏
通常,類的設計方式使得其資料(屬性)只能被其類方法訪問,並與外部的直接訪問隔離。這個隔離物件資料的過程稱為資料隱藏或資訊隱藏。
示例
在 Circle 類中,可以透過使屬性對類外部不可見並向類新增另外兩個訪問類資料的方法來實現資料隱藏,即:
- setValues(),為 x-coord、y-coord 和 a 分配值的方法
- getValues(),檢索 x-coord、y-coord 和 a 值的方法
這裡,物件 my_circle 的私有資料不能被任何未封裝在 Circle 類中的方法直接訪問。而應透過 setValues() 和 getValues() 方法訪問。
訊息傳遞
任何應用程式都需要大量物件以和諧的方式互動。系統中的物件可以使用訊息傳遞相互通訊。假設一個系統有兩個物件:obj1 和 obj2。如果 obj1 希望 obj2 執行其方法之一,則物件 obj1 會向物件 obj2 傳送訊息。
訊息傳遞的特性包括:
- 兩個物件之間的訊息傳遞通常是單向的。
- 訊息傳遞使所有物件之間的互動成為可能。
- 訊息傳遞本質上涉及呼叫類方法。
- 不同的程序中的物件可以參與訊息傳遞。
繼承
繼承是一種機制,它允許透過擴充套件和完善現有類的功能來建立新類。現有類稱為基類/父類/超類,新類稱為派生類/子類/子類。子類可以繼承或派生超類(超類)的屬性和方法,前提是超類允許這樣做。此外,子類可以新增自己的屬性和方法,並可以修改任何超類方法。繼承定義了“是-a”關係。
示例
從 Mammal 類可以派生出許多類,例如 Human、Cat、Dog、Cow 等。人類、貓、狗和奶牛都具有哺乳動物的獨特特徵。此外,每個都有其自身的特定特徵。可以說奶牛“是-a”哺乳動物。
繼承型別
單繼承 - 子類派生自單個超類。
多繼承 - 子類派生自多個超類。
多層繼承 - 子類派生自超類,而超類又派生自另一個類,依此類推。
層次繼承 - 一個類有多個子類,每個子類可能又有後續子類,繼續多個級別,以形成樹狀結構。
混合繼承 - 多繼承和多層繼承的組合,以形成網狀結構。
下圖描述了不同型別繼承的示例。
多型性
多型性最初是一個希臘詞,意思是能夠採用多種形式。在面向物件正規化中,多型性意味著以不同的方式使用操作,具體取決於它們正在操作的例項。多型性允許具有不同內部結構的物件具有共同的外部介面。多型性在實現繼承時特別有效。
示例
讓我們考慮兩個類 Circle 和 Square,每個類都有一個方法 findArea()。儘管類中方法的名稱和用途相同,但內部實現,即計算面積的過程對於每個類都是不同的。當 Circle 類的物件呼叫其 findArea() 方法時,操作會找到圓的面積,而不會與 Square 類的 findArea() 方法發生衝突。
泛化和特化
泛化和特化表示類之間層次關係,其中子類繼承自超類。
泛化
在泛化過程中,類的共同特徵被組合以形成更高層次結構中的類,即子類被組合以形成一個泛化的超類。它表示“是-a-kind-of”關係。例如,“汽車是陸地車輛的一種”,或“船是水上車輛的一種”。
特化
專業化是泛化的逆過程。在這裡,物件的組的區分特徵被用來從現有的類中形成專門的類。可以說,子類是超類的專業化版本。
下圖顯示了泛化和專業化的示例。
連結和關聯
連結
連結表示一個連線,透過該連線,一個物件與其他物件協作。Rumbaugh 將其定義為“物件之間的物理或概念連線”。透過連結,一個物件可以呼叫方法或遍歷另一個物件。連結描述了兩個或多個物件之間的關係。
關聯
關聯是一組具有共同結構和共同行為的連結。關聯描述了一個或多個類的物件之間的關係。連結可以定義為關聯的一個例項。
關聯的度
關聯的度表示參與連線的類的數量。度可以是一元的、二元的或三元的。
一元關係連線同一類的物件。
二元關係連線兩個類的物件。
三元關係連線三個或更多類的物件。
關聯的基數比率
二元關聯的基數表示參與關聯的例項的數量。基數比率有三種類型,即 -
一對一 - 類 A 的單個物件與類 B 的單個物件相關聯。
一對多 - 類 A 的單個物件與類 B 的多個物件相關聯。
多對多 - 類 A 的一個物件可能與類 B 的多個物件相關聯,反之亦然,類 B 的一個物件可能與類 A 的多個物件相關聯。
聚合或組合
聚合或組合是類之間的關係,透過這種關係,一個類可以由其他類的任何物件的組合構成。它允許物件直接放置在其他類的主體中。聚合被稱為“部分-整體”或“具有-一個”關係,能夠從整體導航到其部分。聚合物件是由一個或多個其他物件組成的物件。
示例
在“汽車具有-一個發動機”的關係中,汽車是整體物件或聚合體,而發動機是汽車的“部分”。聚合可以表示 -
物理包含 - 例如,計算機由顯示器、CPU、滑鼠、鍵盤等組成。
概念包含 - 例如,股東具有-一個股份。
物件模型的優點
既然我們已經瞭解了與面向物件相關的核心概念,那麼值得注意的是該模型提供的優勢。
使用物件模型的優點是 -
它有助於更快地開發軟體。
易於維護。假設一個模組出現錯誤,那麼程式設計師可以修復該特定模組,而軟體的其他部分仍然可以正常執行。
它支援相對輕鬆的升級。
它能夠重用物件、設計和功能。
它降低了開發風險,尤其是在複雜系統整合方面。
面向物件分析與設計 - 面向物件系統
我們知道,面向物件建模 (OOM) 技術透過使用圍繞物件組織的模型來視覺化應用程式中的事物。任何軟體開發方法都經歷以下階段 -
- 分析,
- 設計,以及
- 實現。
在面向物件的軟體工程中,軟體開發人員在最終以任何特定的程式語言或軟體工具表示之前,會根據面向物件的概念識別和組織應用程式。
面向物件軟體開發的階段
使用面向物件方法進行軟體開發的主要階段是面向物件分析、面向物件設計和麵向物件實現。
面向物件分析
在此階段,對問題進行表述,識別使用者需求,然後基於現實世界中的物件構建模型。分析會生成有關所需系統應如何工作以及如何開發的模型。這些模型不包括任何實現細節,以便任何非技術應用程式專家都能理解和檢查。
面向物件設計
面向物件設計包括兩個主要階段,即系統設計和物件設計。
系統設計
在此階段,設計所需系統的完整架構。該系統被認為是一組互動的子系統,而子系統又由分層互動的物件組成,這些物件被分組到類中。系統設計是根據系統分析模型和提出的系統架構進行的。這裡重點在於構成系統的物件,而不是系統中的過程。
物件設計
在此階段,基於系統分析階段開發的模型和系統設計階段設計的體系結構開發設計模型。識別所有所需的類。設計人員決定是否 -
- 從頭建立新的類,
- 以其原始形式使用任何現有類,或
- 從現有類繼承新類。
建立識別出的類之間的關聯並識別類的層次結構。此外,開發人員設計類的內部細節及其關聯,即每個屬性的資料結構和操作的演算法。
面向物件實現和測試
在此階段,將物件設計中開發的設計模型轉換為適當的程式語言或軟體工具中的程式碼。建立資料庫並確定特定的硬體需求。程式碼成型後,將使用專門的技術對其進行測試,以識別和消除程式碼中的錯誤。
面向物件分析與設計 - 面向物件原則
面向物件系統的原則
面向物件系統的概念框架基於物件模型。面向物件系統中有兩類元素 -
主要元素 - 主要指如果模型缺少任何一個這些元素,它就不再是面向物件的。四個主要元素是 -
- 抽象
- 封裝
- 模組化
- 層次結構
次要元素 - 次要指這些元素很有用,但不是物件模型不可或缺的部分。三個次要元素是 -
- 型別化
- 併發
- 永續性
抽象
抽象意味著專注於 OOP 中元素或物件的本質特徵,忽略其無關或偶然的屬性。本質特徵與使用物件的上下文相關。
Grady Booch 對抽象的定義如下 -
“抽象表示物件的本質特徵,這些特徵將其與所有其他型別的物件區分開來,從而相對於檢視者的視角提供清晰定義的概念邊界。”
示例 - 當設計 Student 類時,包含屬性 enrolment_number、name、course 和 address,而排除 pulse_rate 和 size_of_shoe 等特徵,因為它們與教育機構的視角無關。
封裝
封裝是將屬性和方法都繫結到類中的過程。透過封裝,可以隱藏類的內部細節以防止外部訪問。類具有提供使用者介面的方法,透過這些方法可以使用類提供的服務。
模組化
模組化是將問題(程式)分解成一組模組的過程,以降低問題的整體複雜性。Booch 將模組化定義為 -
“模組化是系統的一個屬性,該系統已分解成一組內聚且鬆散耦合的模組。”
模組化與封裝本質上是相關的。模組化可以被視為將封裝的抽象對映到具有模組內高內聚性和模組間互動或耦合性低的真實物理模組的一種方式。
層次結構
用 Grady Booch 的話說,“層次結構是抽象的排序或排序”。透過層次結構,系統可以由相互關聯的子系統組成,這些子系統可以擁有自己的子系統,依此類推,直到達到最小的級別元件。它使用“分而治之”的原則。層次結構允許程式碼重用。
OOA 中的兩種層次結構是 -
“IS-A”層次結構 - 它定義了繼承中的層次關係,透過該關係,可以從超類派生多個子類,這些子類可能再次擁有子類,依此類推。例如,如果我們從 Flower 類派生一個 Rose 類,我們可以說玫瑰“是-一個”花。
“PART-OF”層次結構 - 它定義了聚合中的層次關係,透過該關係,一個類可以由其他類組成。例如,一朵花由萼片、花瓣、雄蕊和心皮組成。可以說,花瓣是花的“部分”。
型別化
根據抽象資料型別的理論,型別是一組元素的特徵。在 OOP 中,類被視為具有與任何其他型別不同的屬性的型別。型別化是強制執行物件是單個類或型別的例項的概念。它還強制執行不同型別的物件通常不能互換;並且只有在絕對需要時才能以非常有限的方式互換。
兩種型別的型別化是 -
強型別 - 在這裡,對物件的運算在編譯時進行檢查,如 Eiffel 程式語言。
弱型別 - 在這裡,可以向任何類傳送訊息。操作僅在執行時進行檢查,如 Smalltalk 程式語言。
併發
作業系統中的併發允許同時執行多個任務或程序。當系統中存在單個程序時,據說存在單個控制執行緒。但是,大多數系統有多個執行緒,一些處於活動狀態,一些等待 CPU,一些處於掛起狀態,一些已終止。具有多個 CPU 的系統本質上允許併發的控制執行緒;但是,在單個 CPU 上執行的系統使用適當的演算法來為執行緒提供公平的 CPU 時間,以實現併發。
在面向物件的環境中,存在活動物件和非活動物件。活動物件具有獨立的控制執行緒,可以與其他物件的執行緒併發執行。活動物件彼此之間以及與純順序物件同步。
永續性
物件佔用記憶體空間並在特定時間段記憶體在。在傳統程式設計中,物件的生存期通常是建立它的程式的執行生存期。在檔案或資料庫中,物件的生存期長於建立物件的程序的持續時間。物件即使在其建立者停止存在後繼續存在,這種屬性稱為永續性。
面向物件分析與設計 - 面向物件分析
在軟體開發的系統分析或面向物件分析階段,確定系統需求,識別類並識別類之間的關係。
三種與面向物件分析結合使用的分析技術是物件建模、動態建模和功能建模。
物件建模
物件建模根據物件開發軟體系統的靜態結構。它識別物件、物件可以分組到的類以及物件之間的關係。它還識別表徵每個類的主要屬性和操作。
物件建模的過程可以在以下步驟中視覺化 -
- 識別物件並將其分組到類中
- 識別類之間的關係
- 建立使用者物件模型圖
- 定義使用者物件屬性
- 定義應在類上執行的操作
- 審查術語表
動態建模
在分析了系統的靜態行為之後,需要檢查其隨時間和外部變化而產生的行為。這就是動態建模的目的。
動態建模可以定義為“描述單個物件如何響應事件的方式,這些事件可以是其他物件觸發的內部事件,也可以是外部世界觸發的外部事件”。
動態建模的過程可以視覺化為以下步驟:
- 識別每個物件的狀態
- 識別事件並分析動作的適用性
- 構建動態模型圖,包括狀態轉換圖
- 用物件屬性表示每個狀態
- 驗證繪製的狀態轉換圖
功能建模
功能建模是面向物件分析的最後一個組成部分。功能模型顯示了物件內部執行的過程以及資料在方法之間移動時如何變化。它指定了物件建模操作的含義和動態建模的動作。功能模型對應於傳統結構化分析中的資料流圖。
功能建模的過程可以視覺化為以下步驟:
- 識別所有輸入和輸出
- 構建顯示功能依賴關係的資料流圖
- 說明每個功能的目的
- 識別約束
- 指定最佳化標準
結構化分析與面向物件分析
結構化分析/結構化設計 (SASD) 方法是基於瀑布模型的傳統軟體開發方法。使用 SASD 開發系統的階段如下:
- 可行性研究
- 需求分析與規格說明
- 系統設計
- 實施
- 實施後審查
現在,我們將瞭解結構化分析方法和麵向物件分析方法的相對優勢和劣勢。
面向物件分析的優缺點
| 優點 | 缺點 |
|---|---|
| 關注資料而不是像結構化分析中的過程。 | 功能在物件內受限。這對於本質上是過程性或計算性的系統可能是一個問題。 |
| 封裝和資料隱藏的原則幫助開發人員開發無法被系統其他部分篡改的系統。 | 它無法識別哪些物件會生成最佳的系統設計。 |
| 封裝和資料隱藏的原則幫助開發人員開發無法被系統其他部分篡改的系統。 | 面向物件的模型不容易顯示系統中物件之間的通訊。 |
| 它透過模組化有效地管理軟體複雜性。 | 無法在一個圖中表示所有物件之間的介面。 |
| 與遵循結構化分析的系統相比,它更容易從小型系統升級到大型系統。 |
結構化分析的優缺點
| 優點 | 缺點 |
|---|---|
| 由於它採用自頂向下的方法,與面向物件分析的自底向上方法相反,因此比 OOA 更容易理解。 | 在傳統的結構化分析模型中,一個階段必須在下一個階段完成之前完成。這在設計中提出了一個問題,特別是如果出現錯誤或需求發生變化時。 |
| 它基於功能。識別總體目的,然後進行功能分解以開發軟體。這種強調不僅可以更好地理解系統,而且還可以生成更完整的系統。 | 構建系統的初始成本很高,因為需要一次性設計整個系統,幾乎沒有後期新增功能的選擇。 |
| 其中的規範是用簡單的英語編寫的,因此非技術人員可以更容易地分析。 | 它不支援程式碼重用。因此,開發時間和成本天生就很高。 |
OOAD - 動態建模
動態模型表示系統的時變方面。它關注系統中物件狀態的時間變化。主要概念包括:
狀態,即物件生命週期中特定條件下的情況。
轉換,狀態的變化
事件,觸發轉換的事件
動作,由於某些事件而發生的、不間斷且原子的計算,以及
轉換的併發性。
狀態機模擬物件在其生命週期中由於某些事件以及由於事件發生的動作而穿過多個狀態時的行為。狀態機透過狀態轉換圖以圖形方式表示。
狀態和狀態轉換
狀態
狀態是由物件在特定時間段內具有的屬性值給出的抽象。它是在物件生命週期中持續有限時間段的一種情況,在此期間它滿足某些條件、執行某些活動或等待某些事件發生。在狀態轉換圖中,狀態由圓角矩形表示。
狀態的組成部分
名稱 - 字串區分一個狀態與另一個狀態。狀態可能沒有任何名稱。
進入/退出動作 - 它表示在進入和退出狀態時執行的活動。
內部轉換 - 狀態內的變化,不會導致狀態發生變化。
子狀態 - 狀態內的狀態。
初始狀態和最終狀態
物件的預設起始狀態稱為其初始狀態。最終狀態表示狀態機執行的完成。初始狀態和最終狀態是偽狀態,除了名稱外,可能沒有常規狀態的組成部分。在狀態轉換圖中,初始狀態由實心黑圓表示。最終狀態由包含在另一個未填充黑圓內的實心黑圓表示。
轉換
轉換表示物件狀態的變化。如果物件在某個狀態下發生事件,則物件可能會根據指定的條件執行某些活動並更改狀態。在這種情況下,據說發生了狀態轉換。轉換給出了第一個狀態和新狀態之間的關係。轉換以從源狀態到目標狀態的實心有向弧以圖形方式表示。
轉換的五個部分是:
源狀態 - 受轉換影響的狀態。
事件觸發器 - 發生的事件,如果滿足保護條件,則導致源狀態中的物件發生轉換。
保護條件 - 布林表示式,如果為真,則在收到事件觸發器時導致轉換。
動作 - 由於某些事件而發生在源物件上的不可中斷且原子的計算。
目標狀態 - 轉換完成後到達的目標狀態。
示例
假設一個人從 X 地點乘坐計程車到 Y 地點。該人的狀態可能是:等待(等待計程車)、乘坐(他已獲得計程車並在其中行駛)和到達(他已到達目的地)。下圖描繪了狀態轉換。
事件
事件是一些可以觸發物件或一組物件的狀態轉換的事件。事件在時間和空間上都有位置,但沒有與其關聯的時間段。事件通常與某些動作相關聯。
事件的示例包括滑鼠點選、按鍵、中斷、堆疊溢位等。
觸發轉換的事件寫在狀態圖的弧線旁邊。
示例
考慮上圖所示的示例,當這個人獲得計程車時,從等待狀態到乘坐狀態的轉換髮生。同樣,當他到達目的地時,最終狀態也隨之到達。這兩個事件可以稱為 Get_Taxi 和 Reach_Destination。下圖顯示了狀態機中的事件。
外部事件和內部事件
外部事件是從系統使用者傳遞到系統內物件的那些事件。例如,使用者滑鼠點選或按鍵是外部事件。
內部事件是系統內一個物件傳遞到另一個物件的那些事件。例如,堆疊溢位、除零錯誤等。
延遲事件
延遲事件是那些沒有被物件在當前狀態下立即處理的事件,而是排隊以便稍後在其他狀態下由物件處理。
事件類
事件類表示一組具有共同結構和行為的事件。與物件類一樣,事件類也可以組織成層次結構。事件類可能與其關聯的屬性相關聯,時間是一個隱式屬性。例如,我們可以考慮航空公司航班起飛的事件,我們可以將其歸類為以下類別:
Flight_Departs (航班號,出發城市,到達城市,航線)
動作
活動
活動是對物件狀態的操作,需要一些時間段。它們是系統中正在進行的執行,可以被打斷。活動顯示在活動圖中,這些圖描繪了從一個活動到另一個活動的流程。
動作
動作是由於某些事件而執行的原子操作。原子是指動作是不可中斷的,即,如果動作開始執行,它就會執行到完成,而不會被任何事件中斷。動作可能對觸發事件的物件或對該物件可見的其他物件進行操作。一組動作構成一個活動。
進入動作和退出動作
進入動作是在進入狀態時執行的動作,無論導致進入該狀態的轉換是什麼。
同樣,在離開狀態時執行的動作,無論導致離開該狀態的轉換是什麼,都稱為退出動作。
場景
場景是對指定動作序列的描述。它描述了物件經歷特定動作序列時的行為。主要場景描述了基本序列,次要場景描述了備選序列。
動態建模圖
動態建模主要使用兩種圖:
互動圖
互動圖描述了不同物件之間的動態行為。它包含一組物件、它們之間的關係以及物件傳送和接收的訊息。因此,互動圖模擬了一組相互關聯的物件的行為。互動圖的兩種型別是:
序列圖 - 它以表格方式表示訊息的時間順序。
協作圖 - 它表示透過頂點和弧傳送和接收訊息的物件的結構組織。
狀態轉換圖
狀態轉換圖或狀態機描述單個物件的動態行為。它說明了物件在其生命週期中經歷的狀態序列、狀態的轉換、導致轉換的事件和條件以及由於事件引起的響應。
事件併發
在一個系統中,可能存在兩種型別的併發。它們是:
系統併發
在這裡,併發是在系統級別建模的。整個系統被建模為狀態機的聚合,其中每個狀態機與其他狀態機併發執行。
物件內部併發
在這裡,一個物件可以發出併發事件。一個物件可能具有由子狀態組成的狀態,並且每個子狀態中都可能發生併發事件。
與物件內部併發相關的概念如下:
簡單狀態和複合狀態
簡單狀態沒有子結構。包含巢狀在其內部的更簡單狀態的狀態稱為複合狀態。子狀態是巢狀在另一個狀態內的狀態。它通常用於降低狀態機的複雜性。子狀態可以巢狀到任意多個級別。
複合狀態可以具有順序子狀態或併發子狀態。
順序子狀態
在順序子狀態中,執行控制依次從一個子狀態傳遞到另一個子狀態。在這些狀態機中,最多隻有一個初始狀態和一個最終狀態。
下圖說明了順序子狀態的概念。
併發子狀態
在併發子狀態中,子狀態並行執行,或者換句話說,每個狀態在其內部都有併發執行的狀態機。每個狀態機都有自己的初始狀態和最終狀態。如果一個併發子狀態在其最終狀態之前到達其最終狀態,則控制在其最終狀態等待。當所有巢狀的狀態機都到達其最終狀態時,子狀態會重新加入到單個流程中。
下圖顯示了併發子狀態的概念。
OOAD - 功能建模
功能建模提供了面向物件分析模型的過程視角以及系統應該做什麼的概述。它藉助資料流圖 (DFD) 定義了系統中內部過程的功能。它描述了資料值的函式推導,而沒有指示它們在計算時是如何推匯出來的,或者為什麼需要計算它們。
資料流圖
功能建模透過 DFD 的層次結構來表示。DFD 是一個系統的圖形表示,它顯示了系統的輸入、對輸入的處理、系統的輸出以及內部資料儲存。DFD 說明了對物件或系統執行的一系列轉換或計算,以及影響轉換的外部控制和物件。
Rumbaugh 等人將 DFD 定義為:“資料流圖是一個圖形,它顯示了資料值從物件中的源透過轉換它們的程序到其他物件上的目標的流動。”
DFD 的四個主要部分是:
- 程序,
- 資料流,
- 參與者,以及
- 資料儲存。
DFD 的其他部分是:
- 約束,以及
- 控制流。
DFD 的特徵
程序
程序是轉換資料值的計算活動。整個系統可以被視為一個高級別程序。一個程序可以進一步細分為更小的元件。最低級別的程序可能是一個簡單的函式。
在 DFD 中的表示 - 程序表示為一個橢圓,其名稱寫在其中,幷包含固定數量的輸入和輸出資料值。
示例 - 下圖顯示了一個程序 Compute_HCF_LCM,它接受兩個整數作為輸入並輸出它們的 HCF(最大公約數)和 LCM(最小公倍數)。
資料流
資料流表示兩個程序之間的資料流。它可能在參與者和程序之間,或者在資料儲存和程序之間。資料流表示計算某一點處資料項的值。此值不會因資料流而改變。
在 DFD 中的表示 - 資料流用有向弧或箭頭表示,並用其攜帶的資料項的名稱標記。
在上圖中,Integer_a 和 Integer_b 表示程序的輸入資料流,而 L.C.M. 和 H.C.F. 是輸出資料流。
資料流可能在以下情況下分叉:
輸出值傳送到多個位置,如下圖所示。這裡,輸出箭頭未標記,因為它們表示相同的值。
資料流包含聚合值,並且每個元件都發送到不同的位置,如下圖所示。這裡,每個分叉元件都已標記。
參與者
參與者是主動物件,它們透過產生資料並將其輸入到系統或使用系統產生的資料來與系統互動。換句話說,參與者充當資料的源和接收器。
在 DFD 中的表示 - 參與者用矩形表示。參與者連線到輸入和輸出,並位於 DFD 的邊界上。
示例 - 下圖顯示了參與者,即櫃檯銷售系統中的客戶和銷售員。
資料儲存
資料儲存是被動物件,充當資料儲存庫。與參與者不同,它們不能執行任何操作。它們用於儲存資料和檢索儲存的資料。它們表示資料庫中的資料結構、磁碟檔案或表格。
在 DFD 中的表示 - 資料儲存用包含資料儲存名稱的兩條平行線表示。每個資料儲存至少連線到一個程序。輸入箭頭包含修改資料儲存內容的資訊,而輸出箭頭包含從資料儲存檢索的資訊。當要檢索部分資訊時,輸出箭頭將被標記。未標記的箭頭表示完全資料檢索。雙向箭頭表示檢索和更新。
示例 - 下圖顯示了一個數據儲存 Sales_Record,它儲存所有銷售的詳細資訊。資料儲存的輸入包括銷售的詳細資訊,例如專案、計費金額、日期等。要查詢平均銷售額,該過程檢索銷售記錄並計算平均值。
約束
約束指定需要隨時間滿足的條件或限制。它們允許新增新規則或修改現有規則。約束可以出現在面向物件分析的所有三個模型中。
在物件建模中,約束定義了物件之間的關係。它們還可以定義物件在不同時間可能獲取的不同值之間的關係。
在動態建模中,約束定義了不同物件的狀態和事件之間的關係。
在功能建模中,約束定義了對轉換和計算的限制。
表示 - 約束以花括號內的字串形式呈現。
示例 - 下圖顯示了計算公司員工工資的 DFD 的一部分,該公司決定向銷售部門的所有員工提供激勵,並提高人力資源部門所有員工的工資。可以看出,約束 {Dept:Sales} 導致僅當部門為銷售時才計算激勵,並且約束 {Dept:HR} 導致僅當部門為人力資源時才計算增量。
控制流
一個程序可能與某個布林值相關聯,並且僅當該值為真時才進行評估,儘管它不是程序的直接輸入。這些布林值稱為控制流。
在 DFD 中的表示 - 控制流用從產生布爾值的程序到受其控制的程序的虛線弧表示。
示例 - 下圖表示算術除法的 DFD。除數被測試為非零。如果它不是零,則控制流 OK 的值為真,隨後除法過程計算商和餘數。
開發系統的 DFD 模型
為了開發系統的 DFD 模型,構建了 DFD 的層次結構。頂層 DFD 包含一個程序和與其互動的參與者。
在每個後續的較低級別,逐漸包含更多詳細資訊。一個程序被分解成子程序,識別子程序之間的資料流,確定控制流,並定義資料儲存。在分解程序時,程序的輸入或輸出資料流應與 DFD 下一級的輸入或輸出資料流匹配。
示例 - 讓我們考慮一個軟體系統,批發商軟體,它使批發商店的交易自動化。該商店批次銷售,其客戶包括商人以及零售商店的店主。每個客戶都被要求註冊其個人資訊,並獲得唯一的客戶程式碼 C_Code。一旦銷售完成,商店就會註冊其詳細資訊併發送貨物進行發貨。每年,商店都會向其客戶分發聖誕禮物,包括銀幣或金幣,具體取決於總銷售額和業主的決定。
批發軟體的功能模型如下所示。下圖顯示了頂層 DFD。它將軟體顯示為單個程序以及與之互動的參與者。
系統中的參與者是:
- 客戶
- 銷售人員
- 業主
在下一級 DFD 中,如下圖所示,識別了系統的主要程序,定義了資料儲存,並建立了程序與參與者以及資料儲存的互動。
在系統中,可以識別出三個程序,它們是:
- 註冊客戶
- 處理銷售
- 確定禮物
所需的資料儲存是:
- 客戶詳細資訊
- 銷售詳細資訊
- 禮品詳細資訊
下圖顯示了程序“註冊客戶”的詳細資訊。其中包含三個程序:驗證詳細資訊、生成 C_Code 和更新客戶詳細資訊。輸入客戶詳細資訊後,將對其進行驗證。如果資料正確,則生成 C_Code 並更新資料儲存“客戶詳細資訊”。
下圖顯示了程序“確定禮物”的擴充套件。其中包含兩個程序:查詢總銷售額和確定禮物幣種。查詢總銷售額程序計算每個客戶的年度總銷售額並記錄資料。以該記錄和業主的決定作為輸入,透過確定禮物幣種程序分配禮物幣。
DFD 的優缺點
| 優點 | 缺點 |
|---|---|
| DFD 描述了系統的邊界,因此有助於描繪外部物件和系統內部程序之間的關係。 | 建立 DFD 需要很長時間,這在實際應用中可能不可行。 |
| 它們幫助使用者瞭解系統。 | DFD(資料流圖)不提供任何關於時間相關行為的資訊,即它們沒有指定轉換何時完成。 |
| 圖形表示充當程式設計師開發系統的藍圖。 | 它們沒有闡明計算的頻率或計算的原因。 |
| DFD提供關於系統流程的詳細資訊。 | DFD的準備是一個複雜的過程,需要相當的專業知識。此外,非技術人員難以理解。 |
| 它們用作系統文件的一部分。 | 準備方法是主觀的,留有很大的不精確空間。 |
物件模型、動態模型和功能模型之間的關係
物件模型、動態模型和功能模型對於完整的面向物件分析是互補的。
物件建模以物件的術語開發軟體系統的靜態結構。因此,它顯示了系統中的“執行者”。
動態建模開發物件響應外部事件的時間行為。它顯示了對物件執行的操作序列。
功能模型概述了系統應該做什麼。
功能模型和物件模型
從物件模型的角度來看,功能模型的四個主要部分是:
過程 - 過程暗示了需要實現的物件的方法。
參與者 - 參與者是物件模型中的物件。
資料儲存 - 這些要麼是物件模型中的物件,要麼是物件的屬性。
資料流 - 流向或流出參與者的資料表示對物件的操作或由物件進行的操作。流向或流出資料儲存的資料表示查詢或更新。
功能模型和動態模型
動態模型說明了何時執行操作,而功能模型說明了如何執行操作以及需要哪些引數。由於參與者是活動物件,因此動態模型必須指定它何時行動。資料儲存是被動物件,它們只響應更新和查詢;因此,動態模型不需要指定它們何時行動。
物件模型和動態模型
動態模型顯示了物件的狀態以及在事件發生時對物件執行的操作以及隨後的狀態變化。物件模型顯示了由於更改而導致的物件狀態。
面向物件分析與設計 - UML分析模型
統一建模語言(UML)是一種面向物件分析與設計(OOAD)的圖形語言,它提供了一種標準的方式來編寫軟體系統的藍圖。它有助於視覺化、指定、構建和記錄面向物件系統的工件。它用於描述複雜系統中的結構和關係。
簡史
它開發於 20 世紀 90 年代,是幾種技術的融合,主要包括 Grady Booch 的 OOAD 技術、James Rumbaugh 的 OMT(物件建模技術)和 Ivar Jacobson 的 OOSE(面向物件軟體工程)。UML 試圖標準化 OOAD 的語義模型、語法符號和圖。
UML 中的系統和模型
系統 - 一組為了實現某些目標而組織在一起的元素構成一個系統。系統通常被劃分為子系統,並用一組模型來描述。
模型 - 模型是對系統的簡化、完整且一致的抽象,用於更好地理解系統。
檢視 - 檢視是從特定角度對系統模型的投影。
UML 的概念模型
UML 的概念模型包含三個主要元素:
- 基本構建塊
- 規則
- 通用機制
基本構建塊
UML 的三個構建塊是:
- 事物
- 關係
- 圖
事物
UML 中有四種事物,即:
結構事物 - 這些是 UML 模型的名詞,表示靜態元素,這些元素可以是物理的也可以是概念上的。結構事物包括類、介面、協作、用例、活動類、元件和節點。
行為事物 - 這些是 UML 模型的動詞,表示隨時間和空間變化的動態行為。兩種行為事物是互動和狀態機。
分組事物 - 它們包含 UML 模型的組織部分。只有一種分組事物,即包。
註釋事物 - 這些是 UML 模型中的解釋,表示用於描述元素的註釋。
關係
關係是事物之間的連線。UML 中可以表示的四種關係型別是:
依賴 - 這是兩個事物之間的語義關係,其中一個事物的變化會導致另一個事物的變化。前者是獨立的事物,後者是依賴的事物。
關聯 - 這是表示具有共同結構和共同行為的一組連結的結構關係。
泛化 - 這表示泛化/特化關係,其中子類從超類繼承結構和行為。
實現 - 這是兩個或多個分類器之間的語義關係,其中一個分類器規定了一個契約,其他分類器確保遵守該契約。
圖
圖是對系統的圖形表示。它包含一組元素,通常以圖的形式表示。UML 總共包括九種圖,即:
- 類圖
- 物件圖
- 用例圖
- 順序圖
- 協作圖
- 狀態圖
- 活動圖
- 元件圖
- 部署圖
規則
UML 有許多規則,以便模型在語義上自洽,並與系統中其他模型和諧地相關聯。UML 對以下內容有語義規則:
- 名稱
- 範圍
- 可見性
- 完整性
- 執行
通用機制
UML 有四種通用機制:
- 規範
- 修飾
- 通用劃分
- 擴充套件機制
規範
在 UML 中,每個圖形表示後面都有一個文字語句,表示語法和語義。這些是規範。規範提供了一個語義後平面,其中包含系統的所有部分以及不同路徑之間的關係。
修飾
UML 中的每個元素都有唯一的圖形表示法。此外,還有表示元素重要方面的符號,例如名稱、範圍、可見性等。
通用劃分
面向物件系統可以透過多種方式進行劃分。兩種常見的劃分方式是:
類和物件的劃分 - 類是一組相似物件的抽象。物件是具有系統中實際存在的具體例項。
介面和實現的劃分 - 介面定義了互動規則。實現是介面中定義規則的具體實現。
擴充套件機制
UML 是一種開放式語言。可以以受控的方式擴充套件 UML 的功能,以滿足系統的要求。擴充套件機制包括:
構造型 - 它擴充套件了 UML 的詞彙表,透過它可以從現有構建塊建立新的構建塊。
標記值 - 它擴充套件了 UML 構建塊的屬性。
約束 - 它擴充套件了 UML 構建塊的語義。
面向物件分析與設計 - UML基本符號
UML 為每個構建塊定義了特定的符號。
類
類由一個矩形表示,該矩形具有三個部分:
- 頂部部分包含類的名稱
- 中間部分包含類屬性
- 底部部分表示類操作
屬性和操作的可見性可以用以下方式表示:
公有 - 公有成員在系統的任何地方都可見。在類圖中,它以符號“+”為字首。
私有 - 私有成員僅在類內部可見。無法從類外部訪問它。私有成員以符號“−”為字首。
保護 - 保護成員在類內部以及從該類繼承的子類中可見,但在類外部不可見。它以符號“#”為字首。
抽象類的類名以斜體顯示。
示例 - 讓我們考慮前面介紹的 Circle 類。Circle 的屬性是 x-coord、y-coord 和 radius。操作是 findArea()、findCircumference() 和 scale()。假設 x-coord 和 y-coord 是私有資料成員,radius 是受保護的資料成員,並且成員函式是公有的。下圖給出了類的圖示表示。
物件
物件表示為一個具有兩個部分的矩形:
頂部部分包含物件的名稱以及它是其例項的類的名稱或包的名稱。名稱採用以下形式:
物件名 - 類名
物件名 - 類名 :: 包名
類名 - 匿名物件的情況
底部部分表示屬性的值。它採用屬性名 = 值的形式。
有時物件使用圓角矩形表示。
示例 - 讓我們考慮一個名為 c1 的 Circle 類的物件。我們假設 c1 的中心位於 (2, 3),c1 的半徑為 5。下圖描繪了該物件。
元件
元件是系統的物理且可替換的部分,它符合並提供了一組介面的實現。它表示類和介面等元素的物理打包。
符號 - 在 UML 圖中,元件表示為一個帶選項卡的矩形,如下面的圖所示。
介面
介面是類或元件的方法的集合。它指定了類或元件可能提供的服務集。
符號 - 通常,介面繪製為一個圓圈及其名稱。介面幾乎總是附加到實現它的類或元件。下圖給出了介面的符號。
包
包是一組組織好的元素。包可以在其中包含結構事物,例如類、元件和其他包。
符號 - 在圖形上,包表示為一個帶選項卡的資料夾。包通常只繪製其名稱。但是它可能包含有關包內容的更多詳細資訊。請參見下圖。
關係
不同型別關係的符號如下:
通常,關係中的元素在關係中扮演特定的角色。角色名稱表示參與特定上下文的元素的行為。
示例 - 下圖顯示了類之間不同關係的示例。第一張圖顯示了兩個類 Department 和 Employee 之間的關聯,其中一個部門可能有許多員工在其中工作。Worker 是角色名稱。Department 旁邊的“1”和 Employee 旁邊的“*”表示基數比率是一對多。第二張圖描繪了聚合關係,大學是許多部門的“整體”。
OOAD - UML 結構圖
UML 結構圖分類如下:類圖、物件圖、元件圖和部署圖。
類圖
類圖對系統的靜態檢視進行建模。它包含系統的類、介面和協作;以及它們之間的關係。
系統類圖
讓我們考慮一個簡化的銀行系統。
一個銀行有多個分支機構。在每個區域,一個分支機構被指定為區域總部,負責監督該區域的其他分支機構。每個分支機構可以有多個賬戶和貸款。賬戶可以是儲蓄賬戶或活期賬戶。客戶可以同時開立儲蓄賬戶和活期賬戶。但是,客戶不得擁有多個儲蓄賬戶或活期賬戶。客戶也可以從銀行獲得貸款。
下圖顯示了相應的類圖。
系統中的類
銀行、分支機構、賬戶、儲蓄賬戶、活期賬戶、貸款和客戶。
關係
一個銀行“擁有”多個分支機構 - 組合關係,一對多
具有區域總部角色的分支機構監督其他分支機構 - 一元關聯,一對多
一個分支機構“擁有”多個賬戶 - 聚合關係,一對多
從賬戶類中繼承了兩個類,即儲蓄賬戶和活期賬戶。
一個客戶可以擁有一個活期賬戶 - 關聯關係,一對一
一個客戶可以擁有一個儲蓄賬戶 - 關聯關係,一對一
一個分支機構“擁有”多個貸款 - 聚合關係,一對多
一個客戶可以獲得多個貸款 - 關聯關係,一對多
物件圖
物件圖對一組物件及其在某一時刻的連結進行建模。它顯示了類圖中事物的例項。物件圖是互動圖的靜態部分。
示例 - 下圖顯示了銀行系統類圖一部分的物件圖。
元件圖
元件圖顯示了一組元件之間的組織和依賴關係。
元件圖包含 -
- 元件
- 介面
- 關係
- 包和子系統(可選)
元件圖用於 -
透過正向和反向工程構建系統。
在使用面向物件程式語言開發系統時,對原始碼檔案的配置管理進行建模。
在資料庫建模中表示模式。
對動態系統的行為進行建模。
示例
下圖顯示了一個元件圖,用於對使用 C++ 開發的系統的原始碼進行建模。它顯示了四個原始碼檔案,即 myheader.h、otherheader.h、priority.cpp 和 other.cpp。顯示了 myheader.h 的兩個版本,從最新版本追溯到其祖先版本。檔案 priority.cpp 對 other.cpp 具有編譯依賴關係。檔案 other.cpp 對 otherheader.h 具有編譯依賴關係。
部署圖
部署圖重點關注執行時處理節點及其駐留在這些節點上的元件的配置。它們通常由節點和依賴關係或節點之間的關聯組成。
部署圖用於 -
對嵌入式系統中的裝置進行建模,這些裝置通常由軟體密集型硬體集合組成。
表示客戶機/伺服器系統的拓撲結構。
對完全分散式系統進行建模。
示例
下圖顯示了遵循客戶機/伺服器架構的計算機系統的拓撲結構。該圖說明了一個被構造型為伺服器的節點,該節點包含處理器。該圖表明在系統中部署了四個或更多伺服器。連線到伺服器的是客戶端節點,其中每個節點代表一個終端裝置,例如工作站、筆記型電腦、掃描器或印表機。節點使用清晰地描繪現實世界等效項的圖示來表示。
面向物件分析與設計 - UML行為圖
UML 行為圖視覺化、指定、構建和記錄系統的動態方面。行為圖分為以下幾類:用例圖、互動圖、狀態圖和活動圖。
用例模型
用例
用例描述系統執行的一系列操作,從而產生可見的結果。它顯示了系統外部的事物與系統本身的互動。用例可以應用於整個系統,也可以應用於系統的一部分。
參與者
參與者表示用例的使用者扮演的角色。參與者可以是人(例如學生、客戶)、裝置(例如工作站)或其他系統(例如銀行、機構)。
下圖顯示了名為“學生”的參與者和名為“生成績效報告”的用例的表示法。
用例圖
用例圖呈現了系統中元素行為方式的外部檢視,以及如何在上下文中使用它們。
用例圖包含 -
- 用例
- 參與者
- 關係,如依賴、泛化和關聯
用例圖用於 -
透過將系統的所有活動都包含在一個矩形中,並專注於與之互動的系統外部的參與者來對系統的上下文進行建模。
從外部視角對系統的需求進行建模。
示例
讓我們考慮一個自動化交易房屋系統。我們假設系統具有以下功能 -
交易房屋與兩種型別的客戶進行交易,即個人客戶和公司客戶。
客戶下訂單後,銷售部門會處理訂單,並向客戶提供賬單。
系統允許經理管理客戶賬戶並回復客戶提出的任何查詢。
互動圖
互動圖描述了物件及其關係的互動。它們還包括它們之間傳遞的訊息。互動圖有兩種型別 -
- 順序圖
- 協作圖
互動圖用於對以下內容進行建模 -
使用順序圖按時間順序對控制流進行建模。
使用協作圖對組織的控制流進行建模。
順序圖
順序圖是互動圖,它根據時間說明訊息的順序。
表示法 - 這些圖採用二維圖表的形式。啟動互動的物件放置在 x 軸上。這些物件傳送和接收的訊息放置在 y 軸上,按照從上到下的時間遞增順序排列。
示例 - 自動化交易房屋系統的順序圖如下所示。
協作圖
協作圖是互動圖,它說明了傳送和接收訊息的物件的結構。
表示法 - 在這些圖中,參與互動的物件使用頂點顯示。連線物件的連結用於傳送和接收訊息。訊息顯示為帶標籤的箭頭。
示例 - 自動化交易房屋系統的協作圖如下所示。
狀態圖
狀態圖顯示了一個狀態機,該狀態機描述了物件從一個狀態到另一個狀態的控制流。狀態機描繪了物件由於事件而經歷的狀態序列以及對事件的響應。
狀態圖包含 -
- 狀態:簡單或複合
- 狀態之間的轉換
- 導致轉換的事件
- 事件導致的操作
狀態圖用於對本質上具有反應性的物件進行建模。
示例
在自動化交易房屋系統中,讓我們將訂單建模為一個物件並跟蹤其序列。下圖顯示了相應的狀態圖。
活動圖
活動圖描述了活動流,活動是狀態機中正在進行的非原子操作。活動導致操作,操作是原子操作。
活動圖包含 -
- 活動狀態和動作狀態
- 轉換
- 物件
活動圖用於對以下內容進行建模 -
- 參與者與系統互動時所看到的流程。
- 使用流程圖詳細說明操作或計算。
示例
下圖顯示了自動化交易房屋系統一部分的活動圖。
面向物件分析與設計 - 面向物件設計
在分析階段之後,概念模型將使用面向物件設計 (OOD) 進一步開發成面向物件模型。在 OOD 中,分析模型中與技術無關的概念對映到實現類,識別約束並設計介面,從而生成解決方案域的模型。簡而言之,構建了詳細的描述,指定了如何在具體技術上構建系統。
面向物件設計的階段可以識別為 -
- 定義系統的上下文
- 設計系統架構
- 識別系統中的物件
- 構建設計模型
- 指定物件介面
系統設計
面向物件系統設計包括定義系統的上下文,然後設計系統的架構。
上下文 - 系統的上下文具有靜態和動態部分。系統的靜態上下文使用整個系統的簡單框圖進行設計,該框圖擴充套件為子系統的層次結構。子系統模型由 UML 包表示。動態上下文描述了系統如何與其環境互動。它使用用例圖進行建模。
系統架構 - 系統架構是在系統上下文的基礎上,根據架構設計原則以及領域知識設計的。通常,系統被劃分為多個層,並且每個層都被分解以形成子系統。
面向物件分解
分解是指根據分治原則,將一個大型複雜系統劃分為具有較低複雜性的較小子元件的層次結構。系統的每個主要元件稱為子系統。面向物件分解識別系統中各個獨立的物件以及這些物件之間的通訊。
分解的優點是 -
各個元件的複雜性較低,因此更易於理解和管理。
它能夠分配具有專業技能的勞動力。
它允許替換或修改子系統而不會影響其他子系統。
識別併發
併發允許多個物件同時接收事件,並且多個活動同時執行。併發在動態模型中識別和表示。
為了啟用併發,每個併發元素都被分配了一個單獨的控制執行緒。如果併發是在物件級別,則兩個併發物件被分配兩個不同的控制執行緒。如果單個物件的兩個操作本質上是併發的,則該物件將在不同的執行緒之間拆分。
併發與資料完整性、死鎖和飢餓問題相關聯。因此,在需要併發時需要制定明確的策略。此外,併發需要在設計階段本身被識別,而不能留到實現階段。
識別模式
在設計應用程式時,一些普遍接受的解決方案被用於某些類別的應用程式。這些是設計模式。模式可以定義為一組記錄在案的構建塊,這些構建塊可用於某些型別的應用程式開發問題。
一些常用的設計模式是 -
- 外觀模式
- 模型檢視分離模式
- 觀察者模式
- 模型檢視控制器模式
- 釋出訂閱模式
- 代理模式
控制事件
在系統設計期間,需要識別可能在系統物件中發生的事件並進行適當處理。
事件是重要事件的規範,它在時間和空間上都有位置。
可以建模四種類型的事件,即 -
訊號事件 - 由一個物件丟擲並由另一個物件捕獲的命名物件。
呼叫事件 - 表示操作排程的同步事件。
時間事件 - 表示時間流逝的事件。
更改事件 - 表示狀態更改的事件。
處理邊界條件
系統設計階段需要解決整個系統以及每個子系統的初始化和終止。記錄的不同方面如下 -
系統的啟動,即系統從非初始化狀態到穩定狀態的轉換。
系統的終止,即關閉所有正在執行的執行緒,清理資源以及要傳送的訊息。
系統的初始配置以及在需要時對系統進行重新配置。
預見系統故障或意外終止。
邊界條件使用邊界用例建模。
物件設計
在子系統層次結構開發完成後,識別系統中的物件並設計其細節。在這裡,設計人員詳細說明了在系統設計期間選擇的策略。重點從應用領域概念轉向計算機概念。分析過程中識別出的物件被詳細闡述以進行實現,目的是最大限度地減少執行時間、記憶體消耗和總體成本。
物件設計包括以下階段:
- 物件識別
- 物件表示,即設計模型的構建
- 操作分類
- 演算法設計
- 關係設計
- 外部互動控制的實現
- 將類和關聯打包到模組中
物件識別
物件設計的第一個步驟是物件識別。在面向物件分析階段識別的物件被分組到類中並進行細化,以便它們適合實際實現。
此階段的功能包括:
識別和細化每個子系統或包中的類
定義類之間連結和關聯
設計類之間的層次關聯,即泛化/特化和繼承
設計聚合
物件表示
一旦識別出類,就需要使用物件建模技術對其進行表示。此階段主要涉及構建UML圖。
需要生成兩種型別的設計模型:
靜態模型 - 使用類圖和物件圖描述系統的靜態結構。
動態模型 - 描述系統的動態結構並使用互動圖和狀態圖顯示類之間的互動。
操作分類
在此步驟中,透過組合OOA階段開發的三個模型(即物件模型、動態模型和功能模型)來定義對物件執行的操作。操作指定要做什麼,而不是如何做。
關於操作,執行以下任務:
開發系統中每個物件的狀態轉換圖。
為物件接收的事件定義操作。
識別一個事件觸發同一物件或不同物件中其他事件的情況。
識別操作中的子操作。
將主要操作擴充套件到資料流圖。
演算法設計
使用演算法定義物件中的操作。演算法是解決操作中規定的問題的逐步過程。演算法側重於如何完成。
對於給定的操作,可能存在多個演算法。一旦識別出備選演算法,就會為給定的問題域選擇最優演算法。選擇最優演算法的指標包括:
計算複雜度 - 複雜度根據計算時間和記憶體需求確定演算法的效率。
靈活性 - 靈活性確定所選演算法是否可以在各種環境中適當地實現,而不會損失適用性。
可理解性 - 這決定了所選演算法是否易於理解和實現。
關係設計
在物件設計階段需要制定實現關係的策略。要解決的主要關係包括關聯、聚合和繼承。
關於關聯,設計人員應執行以下操作:
確定關聯是單向還是雙向。
分析關聯路徑並在必要時更新它們。
在多對多關係的情況下,將關聯實現為一個單獨的物件;在一對一或一對多關係的情況下,實現為指向其他物件的連結。
關於繼承,設計人員應執行以下操作:
調整類及其關聯。
識別抽象類。
在需要時做出共享行為的規定。
控制的實現
物件設計人員可以合併狀態圖模型策略的改進。在系統設計中,制定了實現動態模型的基本策略。在物件設計期間,此策略得到適當地完善以進行適當的實現。
實現動態模型的方法包括:
將狀態表示為程式中的位置 - 這是傳統的過程驅動方法,其中控制位置定義程式狀態。有限狀態機可以實現為程式。轉換形成輸入語句,主控制路徑形成指令序列,分支形成條件,反向路徑形成迴圈或迭代。
狀態機引擎 - 此方法透過狀態機引擎類直接表示狀態機。此類透過應用程式提供的轉換和動作集執行狀態機。
控制作為併發任務 - 在這種方法中,物件在程式語言或作業系統中實現為任務。在這裡,事件實現為任務間呼叫。它保留了真實物件的固有併發性。
打包類
在任何大型專案中,將實現細緻地劃分為模組或包都很重要。在物件設計期間,類和物件被分組到包中,以使多個組能夠協作處理專案。
打包的不同方面包括:
隱藏內部資訊以防止外部檢視 - 它允許將類視為“黑盒”,並允許更改類實現,而無需任何類的客戶端修改程式碼。
元素的連貫性 - 如果元素(例如類、操作或模組)根據一致的計劃進行組織,並且其所有部分都具有內在聯絡,以便它們服務於共同的目標,則該元素是連貫的。
物理模組的構建 - 以下指南有助於構建物理模組:
模組中的類應表示相同複合物件中的類似事物或元件。
緊密連線的類應位於同一模組中。
未連線或弱連線的類應放置在單獨的模組中。
模組應具有良好的內聚性,即其元件之間的高度協作。
模組應與其他模組的耦合度低,即模組之間的互動或相互依賴性應最小。
設計最佳化
分析模型捕獲有關係統的邏輯資訊,而設計模型新增詳細資訊以支援高效的資訊訪問。在實現設計之前,應對其進行最佳化,以使實現更有效。最佳化的目標是最大限度地減少時間、空間和其他指標方面的成本。
但是,設計最佳化不應過度,因為易於實現、可維護性和可擴充套件性也是重要的考慮因素。通常會發現,經過完美最佳化的設計效率更高,但可讀性和可重用性較差。因此,設計人員必須在這兩者之間取得平衡。
可以為設計最佳化執行的各種操作包括:
- 新增冗餘關聯
- 省略不可用的關聯
- 演算法最佳化
- 儲存派生屬性以避免重新計算複雜表示式
新增冗餘關聯
在設計最佳化期間,檢查是否可以透過派生新關聯來降低訪問成本。儘管這些冗餘關聯可能不會新增任何資訊,但它們可能會提高整體模型的效率。
省略不可用的關聯
關聯過多可能會使系統難以理解,從而降低系統的整體效率。因此,在最佳化期間,會刪除所有不可用的關聯。
演算法最佳化
在面向物件的系統中,資料結構和演算法的最佳化以協作的方式進行。一旦類設計到位,就需要最佳化操作和演算法。
演算法最佳化透過以下方式獲得:
- 重新排列計算任務的順序
- 反轉迴圈的執行順序,使其與功能模型中規定的順序相反
- 刪除演算法中的死路徑
儲存和儲存派生屬性
派生屬性是指其值作為其他屬性(基本屬性)的函式計算的屬性。每次需要時重新計算派生屬性的值是一個耗時的過程。為了避免這種情況,可以計算這些值並以計算形式儲存。
但是,這可能會導致更新異常,即基本屬性值發生變化而派生屬性值沒有相應變化。為了避免這種情況,採取以下步驟:
每次更新基本屬性值時,也重新計算派生屬性。
定期以組的形式重新計算和更新所有派生屬性,而不是在每次更新後更新。
設計文件
文件是任何軟體開發過程中必不可少的一部分,它記錄了製作軟體的過程。對於任何非平凡的軟體系統,都需要記錄設計決策,以便將設計傳遞給他人。
使用領域
儘管是輔助產品,但良好的文件是必不可少的,尤其是在以下領域:
- 在設計由多個開發人員開發的軟體時
- 在迭代軟體開發策略中
- 在開發軟體專案的後續版本時
- 用於評估軟體
- 用於查詢測試條件和測試區域
- 用於維護軟體。
內容
有益的文件應主要包含以下內容:
高階系統架構 - 流程圖和模組圖。
關鍵抽象和機制 - 類圖和物件圖。
說明主要方面行為的場景 - 行為圖
特徵
良好文件的特徵包括:
簡潔且同時明確、一致和完整
可追溯到系統的需求規範
結構良好
圖解而不是描述性
面向物件分析與設計 - 實現策略
實現面向物件的設計通常涉及使用標準的面向物件程式語言 (OOPL) 或將物件設計對映到資料庫。在大多數情況下,它涉及兩者。
使用程式語言實現
通常,將物件設計轉換為程式碼的任務是一個簡單的過程。任何面向物件程式語言,如 C++、Java、Smalltalk、C# 和 Python,都包含表示類的規定。在本章中,我們將使用 C++ 對該概念進行舉例說明。
下圖顯示了使用 C++ 表示 Circle 類。
實現關聯
大多數程式語言不提供直接實現關聯的構造。因此,實現關聯的任務需要仔細考慮。
關聯可以是單向的或雙向的。此外,每個關聯可以是一對一、一對多或多對多。
單向關聯
為了實現單向關聯,應注意維護單向性。不同多重性的實現如下:
可選關聯 - 在這裡,參與物件之間可能存在或可能不存在連結。例如,在下圖中客戶與活期賬戶之間的關聯中,客戶可能擁有或可能不擁有活期賬戶。
為了實現,將活期賬戶的物件作為客戶中的屬性包含在內,該屬性可能為 NULL。使用 C++ 實現:
class Customer {
private:
// attributes
Current_Account c; //an object of Current_Account as attribute
public:
Customer() {
c = NULL;
} // assign c as NULL
Current_Account getCurrAc() {
return c;
}
void setCurrAc( Current_Account myacc) {
c = myacc;
}
void removeAcc() {
c = NULL;
}
};
一對一關聯 - 在這裡,一個類的例項與關聯類的正好一個例項相關聯。例如,部門和經理之間存在一對一關聯,如下面的圖所示。
這是透過在Department中包含一個Manager物件來實現的,該物件不應為NULL。使用C++的實現 -
class Department {
private:
// attributes
Manager mgr; //an object of Manager as attribute
public:
Department (/*parameters*/, Manager m) { //m is not NULL
// assign parameters to variables
mgr = m;
}
Manager getMgr() {
return mgr;
}
};
一對多關聯 - 在這裡,一個類的例項與關聯類的多個例項相關聯。例如,考慮下圖中Employee和Dependent之間的關聯。
這是透過在Employee類中包含一個Dependents列表來實現的。使用C++ STL list容器的實現 -
class Employee {
private:
char * deptName;
list <Dependent> dep; //a list of Dependents as attribute
public:
void addDependent ( Dependent d) {
dep.push_back(d);
} // adds an employee to the department
void removeDeoendent( Dependent d) {
int index = find ( d, dep );
// find() function returns the index of d in list dep
dep.erase(index);
}
};
雙向關聯
要實現雙向關聯,需要維護兩個方向的連結。
可選或一對一關聯 - 考慮Project和Project Manager之間的一對一雙向關聯關係,如下圖所示。
使用C++的實現 -
Class Project {
private:
// attributes
Project_Manager pmgr;
public:
void setManager ( Project_Manager pm);
Project_Manager changeManager();
};
class Project_Manager {
private:
// attributes
Project pj;
public:
void setProject(Project p);
Project removeProject();
};
一對多關聯 - 考慮Department和Employee之間的一對多關聯關係,如下圖所示。
使用C++ STL list容器的實現
class Department {
private:
char * deptName;
list <Employee> emp; //a list of Employees as attribute
public:
void addEmployee ( Employee e) {
emp.push_back(e);
} // adds an employee to the department
void removeEmployee( Employee e) {
int index = find ( e, emp );
// find function returns the index of e in list emp
emp.erase(index);
}
};
class Employee {
private:
//attributes
Department d;
public:
void addDept();
void removeDept();
};
將關聯作為類實現
如果關聯有一些關聯的屬性,則應使用單獨的類來實現。例如,考慮下圖中Employee和Project之間的一對一關聯。
使用C++實現WorksOn
class WorksOn {
private:
Employee e;
Project p;
Hours h;
char * date;
public:
// class methods
};
實現約束
類中的約束限制了屬性可能取的值的範圍和型別。為了實現約束,在從類例項化物件時,將為屬性分配一個有效的預設值。每當在執行時更改值時,都會檢查該值是否有效。無效值可以透過異常處理例程或其他方法來處理。
示例
考慮一個Employee類,其中age是一個屬性,其值範圍為18到60。以下C++程式碼包含了它 -
class Employee {
private: char * name;
int age;
// other attributes
public:
Employee() { // default constructor
strcpy(name, "");
age = 18; // default value
}
class AgeError {}; // Exception class
void changeAge( int a) { // method that changes age
if ( a < 18 || a > 60 ) // check for invalid condition
throw AgeError(); // throw exception
age = a;
}
};
實現狀態圖
有兩種替代的實現策略來在狀態圖中實現狀態。
類中的列舉
在這種方法中,狀態由資料成員(或一組資料成員)的不同值表示。這些值由類中的列舉明確定義。轉換由更改相關資料成員值的成員函式表示。
在泛化層次結構中排列類
在這種方法中,狀態以一種可以由公共指標變數引用的方式排列在泛化層次結構中。下圖顯示了從狀態圖到泛化層次結構的轉換。
物件對映到資料庫系統
物件的永續性
開發面向物件系統的一個重要方面是資料的永續性。透過永續性,物件的生命週期比建立它的程式更長。永續性資料儲存在輔助儲存介質上,在需要時可以從那裡重新載入。
RDBMS概述
資料庫是相關資料的有序集合。
資料庫管理系統(DBMS)是一組軟體,用於促進定義、建立、儲存、操作、檢索、共享和刪除資料庫中的資料。
在關係資料庫管理系統(RDBMS)中,資料儲存為關係或表,其中每一列或欄位表示一個屬性,每一行或元組表示一個例項的記錄。
每一行都由一組選定的最小屬性唯一標識,稱為主鍵。
外部索引鍵是作為相關表主鍵的屬性。
在RDBMS中將類表示為表
要將類對映到資料庫表,每個屬性都表示為表中的一個欄位。將現有屬性(或屬性)分配為主鍵,或新增一個單獨的ID欄位作為主鍵。可以根據需要水平或垂直地劃分類。
例如,Circle類可以轉換為如下圖所示的表。
Schema for Circle Table: CIRCLE(CID, X_COORD, Y_COORD, RADIUS, COLOR) Creating a Table Circle using SQL command: CREATE TABLE CIRCLE ( CID VARCHAR2(4) PRIMARY KEY, X_COORD INTEGER NOT NULL, Y_COORD INTEGER NOT NULL, Z_COORD INTEGER NOT NULL, COLOR );
將關聯對映到資料庫表
一對一關聯
要實現1:1關聯,任何一個表的primaryKey都會被分配為另一個表的foreignKey。例如,考慮Department和Manager之間的關聯 -
建立表的SQL命令
CREATE TABLE DEPARTMENT ( DEPT_ID INTEGER PRIMARY KEY, DNAME VARCHAR2(30) NOT NULL, LOCATION VARCHAR2(20), EMPID INTEGER REFERENCES MANAGER ); CREATE TABLE MANAGER ( EMPID INTEGER PRIMARY KEY, ENAME VARCHAR2(50) NOT NULL, ADDRESS VARCHAR2(70), );
一對多關聯
要實現1:N關聯,關聯1側的表的primaryKey將被分配為關聯N側的表的foreignKey。例如,考慮Department和Employee之間的關聯 -
建立表的SQL命令
CREATE TABLE DEPARTMENT ( DEPT_ID INTEGER PRIMARY KEY, DNAME VARCHAR2(30) NOT NULL, LOCATION VARCHAR2(20), ); CREATE TABLE EMPLOYEE ( EMPID INTEGER PRIMARY KEY, ENAME VARCHAR2(50) NOT NULL, ADDRESS VARCHAR2(70), D_ID INTEGER REFERENCES DEPARTMENT );
多對多關聯
要實現M:N關聯,將建立一個新關係來表示關聯。例如,考慮Employee和Project之間的以下關聯 -
Works_On表的模式 - WORKS_ON (EMPID, PID, HOURS, START_DATE)
建立Works_On關聯的SQL命令 - CREATE TABLE WORKS_ON
( EMPID INTEGER, PID INTEGER, HOURS INTEGER, START_DATE DATE, PRIMARY KEY (EMPID, PID), FOREIGN KEY (EMPID) REFERENCES EMPLOYEE, FOREIGN KEY (PID) REFERENCES PROJECT );
將繼承對映到表
要對映繼承,基表的主鍵將被分配為派生表的主鍵以及外部索引鍵。
示例
面向物件分析與設計 - 測試與質量保證
一旦程式程式碼編寫完成,就必須對其進行測試以檢測並隨後處理其中的所有錯誤。為了測試目的,使用多種方案。
另一個重要方面是程式的目的適用性,它確定程式是否實現了其目標。適用性定義了軟體質量。
測試面向物件系統
測試是在軟體開發過程中的一項持續活動。在面向物件系統中,測試包括三個級別,即單元測試、子系統測試和系統測試。
單元測試
在單元測試中,測試各個類。檢視類的屬性是否按設計實現,以及方法和介面是否沒有錯誤。單元測試是實現結構的應用程式工程師的責任。
子系統測試
這涉及測試特定的模組或子系統,是子系統負責人負責的。它涉及測試子系統內的關聯以及子系統與外部的互動。子系統測試可用作每個新發布的子系統版本的迴歸測試。
系統測試
系統測試涉及將系統作為一個整體進行測試,是質量保證團隊的責任。當組裝新版本時,團隊通常會將系統測試用作迴歸測試。
面向物件測試技術
灰盒測試
可以為測試面向物件程式而設計的不同型別的測試用例稱為灰盒測試用例。一些重要的灰盒測試型別包括 -
基於狀態模型的測試 - 這包括狀態覆蓋、狀態轉換覆蓋和狀態轉換路徑覆蓋。
基於用例的測試 - 測試每個用例中的每個場景。
基於類圖的測試 - 測試每個類、派生類、關聯和聚合。
基於序列圖的測試 - 測試序列圖中訊息中的方法。
子系統測試技術
子系統測試的兩種主要方法是 -
基於執行緒的測試 - 整合並測試實現子系統中單個用例所需的所有類。
基於使用的測試 - 測試每個層次結構級別上的模組的介面和服務。測試從單個類到包含類的較小模組開始,逐漸到較大的模組,最後到所有主要子系統。
系統測試類別
Alpha測試 - 由開發軟體的組織內的測試團隊執行。
Beta測試 - 由選定的合作客戶組執行。
驗收測試 - 客戶在接受交付成果之前執行。
軟體質量保證
軟體質量
Schulmeyer和McManus將軟體質量定義為“整個軟體產品的適用性”。高質量的軟體完全按照其預期執行,並根據使用者制定的需求規範的滿意度進行解釋。
質量保證
軟體質量保證是一種確定軟體產品在多大程度上適合使用的 методология。確定軟體質量包含的活動包括 -
- 審計
- 制定標準和指南
- 生成報告
- 審查質量體系
質量因素
正確性 - 正確性確定軟體需求是否得到適當滿足。
可用性 - 可用性確定軟體是否可以被不同類別的使用者(初學者、非技術人員和專家)使用。
可移植性 - 可移植性確定軟體是否可以在具有不同硬體裝置的不同平臺上執行。
可維護性 - 可維護性確定糾正錯誤和更新模組的難易程度。
可重用性 - 可重用性確定模組和類是否可以重用於開發其他軟體產品。
面向物件度量
度量可以廣泛地分為三類:專案度量、產品度量和過程度量。
專案度量
專案度量使軟體專案經理能夠評估正在進行的專案的狀況和績效。以下度量適用於面向物件軟體專案 -
- 場景指令碼數量
- 關鍵類數量
- 支援類數量
- 子系統數量
產品度量
產品度量衡量已開發軟體產品的特性。適用於面向物件系統的產品度量包括 -
每個類的Method數量 - 它確定類的複雜性。如果假設一個類中的所有方法都同樣複雜,那麼具有更多方法的類更復雜,因此更容易出錯。
繼承結構 - 具有多個小型繼承格子的系統比具有單個大型繼承格子的系統結構更好。作為經驗法則,繼承樹的層數不應超過7(±2),並且樹應保持平衡。
耦合和內聚 - 耦合低且內聚高的模組被認為設計得更好,因為它們允許更大的可重用性和可維護性。
類的響應 - 它衡量類例項呼叫的方法的效率。
過程度量
過程度量有助於衡量流程的執行情況。它們在所有專案中長期收集。它們用作長期軟體流程改進的指標。一些過程度量包括 -
- KLOC(千行程式碼)數量
- 缺陷去除效率
- 測試期間檢測到的平均故障次數
- 每個KLOC的潛在缺陷數量