在二十世紀六十年代以前,軟件系統都是較小且相對簡單的;所用的編程語言都是十分簡單(Fortran,Cobol等 );時興個人英雄注意,即崇尚程序員的個人技能 ;代碼是面條式的,特別是代碼中含有GOTO語句。當時系統設計時常用的方法有功能分解法和數據流法。
以系統需要提供的功能為中心來組織系統。首先定義各種功能,然后把功能分解為子功能,同時定義功能之間的接口。對較大的子功能進一步分解,直到可給出明確的定義。根據功能/子功能的需要設計數據結構和算法。其優缺點如下:
優點:
缺點:
又稱作結構化分析。基本策略是跟蹤數據流,即研究問題域中數據如何流動以及在各個環節上進行何種處理,從而發現數據流和加工。問題域被映射為數據流圖(DFD),并用處理說明和數據字典進行詳細說明。其優缺點如下:
優點:
缺點:
上述的功能分解法和數據流發已經開發了很多軟件系統。對于功能穩定的應用領域,如某些科學計算,上述方法是適用的。
對于眾多的領域而言,其功能是易變的,如企業管理和商業管理領域就是如此。因為隨著市場的變化,要對這些領域的管理模式不斷地進行調整。對于較為復雜的系統,用上述方法進行軟件開發,容易導致模塊的低內聚和模塊間的高耦合,從而使得系統缺乏靈活性和可維護性。
特別是由于當時團隊的開發與管理方法的不足,使得在20世紀70年代的軟件危機情況更加嚴重。
為了解決軟件危機,人們對開發技術進行了一定的改進,對編程語言也進行了革新,如產生了用于軟件開發的4GL、CASE工具、原型技術和代碼生成器。這些努力取得了一定的成就,但沒有從根本上解決問題。
面向對象方法的解決問題的思路是從現實世界中的客觀對象(如人和事物)入手,盡量運用人類的自然思維方式來構造軟件系統,這與傳統的結構化方法從功能入手和信息工程化方法從信息入手是不一樣的。在面向對象方法中,把一切都看成是對象。
從程序設計方法的角度看,面向對象是一種新的程序設計范型(paradigm),其基本思想是使用對象、類、繼承、封裝、聚合、關聯、消息、多態性等基本概念來進行程序設計。是一種運用對象、類、繼承、封裝、聚合、關聯、消息、多態性等概念來構造系統的軟件開發方法。
過程抽象:任何一個完成確定功能的操作序列,其使用者都可把它看作一個單一的實體,盡管實際上它可能是由一系列更低級的操作完成的。
數據抽象:根據施加于數據之上的操作來定義數據類型,并限定數據的值只能由這些操作來修改和觀察。
客觀事物->對象->類->一般類
不同開發階段需要進行不同程度的抽象,便于實現模塊的可替換性
把對象的屬性和操作結合成一個獨立的系統單位,并盡可能隱蔽對象的內部細節。只是向外部提供接口,降低了對象間的耦合度。
封裝的意義:
封裝機制保證:數據不能被對象的使用者直接訪問。只允許通過由對象提供的方法或代碼訪問數據。
借助消息傳遞,工作可從一個對象(客戶)傳遞到另一個對象(代理),因為從客戶的觀點,代理具有客戶所需要的操作。工作連續地傳遞,直到到達了既有數據又有方法(代碼)能完成這項工作的對象。
注意:委托是執行任務的權利,而不是責任。
把具有共同性質的事物劃分為一類,得出一個抽象的概念。分類幫助我們組織我們所生活的復雜世界。我們可以對在一個特殊分類中的對象做一些假設。如果一個對象是分類(類)的一個實例,它將符合該分類的總體模式。所有的對象都是類的實例。實例能夠在運行時被產生(初始化)或銷毀(刪除)。對象怎樣提供操作,由該對象為其實例的類所決定。這樣,同一個類的所有對象在響應特定的操作請求(功能調用)時使用相同的方法
無多態性的泛化:類可以由層次繼承結構所組織。在該結構中,子類將從位于層次結構高層的父類中繼承屬性、操作和關系。抽象的父類是指僅用來定義子類的超類。這樣,抽象類就沒有直接的實例。
有多態的泛化:可以使用層次繼承結構組織類,子類可以繼承位于層次結構的高層的父類的屬性、操作和關系。然而,子類可以定義它自己的操作來代替其任何超類的同名操作。
即要求對象之間只能通過消息進行通訊。消息傳遞機制與函數調用機制的區別 :
關系機制為我們提供了用同等(關聯、依賴)和層次(一般化/特殊化和聚合)結構組織類/對象的方法。很多面向對象的專家把模型的這部分結構稱作靜態模型。我們使用James Martin和James Odell的術語,將其稱為結構分析。然而,一個應用/系統有了結構分析并不充分,還需要進行行為分析。行為分析是我們用來考察一個對象(類)是怎樣提供它的操作的過程。 從分析的視點,有兩種類型的行為:
靜態的:在靜態行為中,實現操作的代碼不被任何外部或內部的事件(動作)所影響。
動態的:在行為中發生這些變化的原因可能是由于對象存在很多不同的狀態。隨后,對象根據它的狀態做出反映。使用命令式編程技術不能很好地處理這種類型的行為。使用另外的一種稱為有限狀態機的機制會更好地捕獲這樣的方法。
引入包(package) 的概念,使模型具有大小不同的粒度層次,以利于控制復雜性。 如把分析和設計階段的模型分別用包進行組織。
說明:書上=》抽象、分類、封裝、消息通信、多態性、行為分析、復雜性控制
對象
對象是系統中用來描述客觀事物的一個實體,它是構成系統的一個基本單位。一個對象由一組屬性和對這組屬性進行操作的一組操作構成。
對象標識
對象標識就是對象的名字,有“外部標識”和“內部標識”之分。
類
類是具有相同屬性和操作的一組對象的集合,它為屬于該類的全部對象提供了統一的抽象描述,其內部包括屬性和操作務兩個主要部分。類的作用是用來創建對象,對象是類的一個實例。
抽象
抽象(化)忽略事物的非本質特征,只注意那些與當前目標有關的本質特征,從而找出事物的共性。
分類
把具有共同性質的事物劃分為一類,得出一個抽象的概念,叫做分類。
繼承
特殊類擁有其一般類的全部屬性與操作,稱作特殊類對一般類的繼承。繼承意味著自動地擁有,或曰隱含地復制子類從父類中繼承屬性和操作,根據需要添加自己的屬性和方法。繼承簡化了人們對事物的認識和描述,非常有益于軟件復用,是OO技術提高軟件開發效率的重要原因之一。一般類與特殊類之間的關系叫泛化關系(繼承關系),簡稱泛化。例:
多態
多態是指同一個命名可具有不同的語義。OO方法中,常指在一般類中定義的屬性或操作被特殊類繼承之后,可以具有不同的數據類型或表現出不同的行為。
消息
對象通過它對外提供的操作在系統中發揮作用。當系統中的其他對象或其他系統成分(在不要求完全對象化的語言中,允許有不屬于任何對象的成分,例如C++程序中的main函數),請求這個對象執行某個操作時,該對象就響應這個請求,完成該操作。在OO方法中,把向對象發出的操作請求稱為消息。目前在大部分面向對象的編程語言中,消息其實就是函數(或過程)調用。但是,函數調用只是實現消息的方式之一,上述理解只適合于順序系統。
聚合
一個(較復雜的)對象由其他若干(較簡單的)對象作為其構成部分,稱較復雜的對象為聚集,稱較簡單的對象為成分,稱這種關系為聚合。如:
UML表示舉例:
關聯
類之間的靜態聯系稱作關聯。在實例化后,由類產生對象,由關聯產生連接對象的鏈。
鏈是關聯的實例。 關聯的表示符號也稱作實例連接:
與傳統方法相比,面向對象方法的主要優點:
一是保證了對象行為的可靠性;
二是對它們的修改并不會影響其他的對象,有利于維護,對需求變化有較強的適應性。
把對象的屬性和操作捆綁在一起,提高了對象(作為模塊)的內聚性,減少了與其他對象的耦合,這為復用對象提供了可能性和方便性。在繼承結構中,特殊類對一般類的繼承,本身就是對一般類的屬性和操作的復用。
面向對象的分析(Object Oriented Analysis, OOA),就是運用面向對象方法進行系統分析。其基本任務即運用面向對象方法,對問題域和系統責任進行分析和理解,找出描述問題域及系統責任所需的對象,定義對象的屬性、操作以及它們之間的關系。其目標是建立一個符合問題域、滿足用戶需求的OOA模型。
OOA是分析,是軟件生命周期的一個階段,具有一般分析方法共同具有的內容、目標及策略;強調運用面向對象方法進行分析,用面向對象的概念和表示法表達分析結果。
問題域(problem domain):被開發系統的應用領域,即在現實世界中由這個系統進行處理的業務范圍。
系統責任(system responsibilities):所開發的系統應該具備的職能。
從OOA到OOD不是轉換,是調整和增補。使OOA作為OOD模型的問題域部分;增補其它四個部分,成為完整的OOD模型。
有不同的側重點和不同的策略
OOA主要針對問題域,識別有關的對象以及它們之間的關系,產生一個映射問題域,滿足用戶需求,獨立于實現的OOA模型。
OOD主要解決與實現有關的問題,基于OOA模型,針對具體的軟、硬件條件(如機器、網絡、OS、GUI、DBMS等)產生一個可實現的OOD模型。
人機交互、人機互動(Human–Computer Interaction或Human–Machine Interaction,簡稱HCI或HMI),是一門研究系統與用戶之間的交互關系的是科學學科 。把人機交互部分作為系統中一個獨立的組成部分,進行分析和設計,有利于隔離界面支持系統的變化對問題域部分的影響。人機交互使用的設備主要有鍵盤顯示、鼠標、各種模式識別設備……
對使用系統的人進行分析
——以便設計出適合其特點的交互方式和界面表現形式;
對人和機器的交互過程進行分析
——核心問題是人如何命令系統,以及系統如何向人提交信息。
1.分析與系統交互的人——人員參與者
人對界面的需求,不僅在于人機交互的內容,而且在于他們對界面表現形式、風格等方面的愛好。前者是客觀需求,對誰都一樣;后者是主觀需求,因人而異。
(1)列舉所有的人員參與者
(2)調查研究
(3)區分人員類型
(4)統計(或估算)各類人員的比例
(5)了解使用者的主觀需求
(6) 按照一定的準則進行折中與均衡
2.從use case分析人機交互
use case的構成
參與者的行為和系統行為按時序交替出現,左右分明。形成交叉排列的段落。
每個段落至少含有一個輸入語句或輸出語句;
有若干純屬參與者自身或系統自身的行為陳述;
可能包含一些控制語句或括號。
抽取方法:
刪除所有與輸入、輸出無關的語句和不再包含任何內容的控制語句與括號,
剩下的就是對一個參與者(人)使用一項系統功能時的人機交互描述。
人機界面的設計準則:
1.命令的組織
不受歡迎的命令組織方式:
(1)一條命令含有大量的參數和任選項
(2)系統有大量命令,不加任何組織和引導
基本命令:使用一項獨立的系統功能的命令。(提取后的用況)
命令步:在執行一條基本命令的交互過程中所包含的具體輸入步驟。
高層命令:如果一條命令是在另一條命令的引導下被選用的,則后者稱作前者的高層命令。
命令的組織措施——分解與組合
(1)分解:將一條含有許多參數和選項的命令分解為若干命令步
(2)組合:將基本命令組織成高層命令,從高層命令引向基本命令
基本命令及其命令步的結構
高層命令及其結構
按功能組織:如文件下有:創建、打開、關閉、打印、刪除等。
按子系統組織:如文本編輯子系統、編譯自系統。
兩層命令之間的輸出信息結構
在建立命令樹時,應遵循如下策略:
控制流是進程(process)或線程(thread)的別稱。有多個任務(控制流)并發執行的系統,稱作多任務系統或并發系統。為了描述問題域固有的并發行為,表達實現所需的設計決策,需要在OOD部分對控制驅動部分進行建模。控制流驅動部分,用于定義和表示并發系統中的每個控制流。用主動對象表示每個控制流(進程、線程),所有的主動類構成控制流驅動部分。
在面向對象中,用一個主動對象表示一個獨立的控制流,該對象驅動進程或線程,也即每個控制流都以一個表示獨立的進程或線程的主動對象為根。 對控制驅動部分建模,通常,
1)OOA定義的主動對象,這是由業務邏輯所決定的
2)系統的并發需求所要求的多控制流,若要求多項工作同時進行,則每一項工作就是一個控制流。例如,銷售與統計。
3)系統分布方案所要求的多控制流,每一個分布站點至少有一個控制流
4)根據任務的緊急程度設置控制流,高優先控制流,低優先控制流,緊急控制流;
5)為實現方便設立的控制流,例如:負責處理機之間通訊的控制流
6)對異常事件的處理,由于異常事件的發生,不能在程序的某個可預知的控制點進行處理,應該設立一個專門的控制流進行處理異常事件。
每個控制流應該有以上列舉的理由之一,除非由明確的其他理由。
一個控制流中的對象調用另一個控制流中的對象的操作,是通過發送了一條同步消息來實現的。具體的執行步驟為:
(1)調用者調用操作
(2)調用者等待接收者接收這個調用
(3)接收者的操作被喚醒
(4)計算結果返回給調用者
(5)調用者繼續它的執行。
一個控制流的對象異步地向另一個控制流中的對象發送一個信號。具體的執行步驟為:
(1)請求者發送信號,然后就繼續它自己的執行;
(2)接收者只有在準備好時或在適當的時候,才到指定的郵箱去接收信號并進行處理,完成后可能向請求者發信號來回傳處理結果,接著向下執行。
這樣的郵箱機制也可以是同步的,但收發信號的雙方事先要做好約定。
兩個或幾個控制流中的對象利用一塊公共的存儲器,作為通信區域。
通常傳輸具有較復雜和較大的數據結構的數據時,才使用共享存儲器方式。
使用此方式,要注意同步問題。
用于在不同計算機中的并發進程:
(1)調用進程標示它想要請求的一個對象的操作,然后把它放在遠程過程調用庫中;
(2)遠程過程調用機制在網絡上尋找目標對象,找到后將請求打包發送給目標對象;
(3)目標方接到后將請求轉換成本地格式,執行所請求的操作;執行完畢后,將結果以上述同樣的方式返回給發送方。
數據管理部分是負責在特定的數據管理系統中存儲和檢索對象的組成部分。其目的是,存儲問題域的持久對象、封裝這些對象的查找和存儲機制,以及為了隔離數據管理方案的影響。為了隔離數據管理系統對其它部分的影響,使得選用不同的數據管理系統時,問題域部分基本相同。
面向對象的數據庫系統是OO設計和編程的之間擴展,是為了存儲對象并與面向對象程序設計語言交互而專門設計的。它是按對象存儲數據的數據庫管理系統。面向對象數據庫系統有兩方面的特征:
(1)是面向對象的,應支持對象、類、操作、屬性、繼承、聚合、關聯等面向對象的概念;
(2)另一方面它具有數據庫系統所應具有的特定和功能。
當前的一種主流的做法是在面向對象的系統設計階段的后期,考慮如何對系統的構件進行描述、構造和組織,以及構件如何在節點上進行分布。
1) 一個構件是系統的一個模塊部分,而且是一個自包含的單元,它封裝了其內部成分。
2) 構件通過它的提供接口和請求接口展現行為。
3) 構件是可替換的單元,在設計時和運行時依據接口的兼容性,若一個構件能提供與另一個構件所具有的功能,則前者可替換后者。
4) 構件起類型的作用,這意味著構件是可實例化的。
構件的表示法
接口(interface)接口由一組操作組成,它指定了一個契約,這個契約必須由實現和使用這個接口的構件的所遵循。除非用來表示常量,否則不需要屬性。可以按各種約束(如前置和后置條件)的形式把一個接口與一個職責相關聯,可以對通過這個接口的交互規定次序。接口分提供接口和請求接口。
把構件實現的接口稱為提供接口,這意味著構件的提供接口是給其它構件提供服務的。實現接口的構件支持由該接口所擁有的特征,包括接口擁有的約束。
構件使用的接口被稱為請求接口,即構件向其它構件請求服務時要遵循的接口。即構件向其它構件請求服務時要遵循的接口 。
一個構件可以實現多個接口,一個構件可以請求多個接口,一個接口可以由多個不同的構件實現。
接口對聲明一個構件的總的行為來說是有用的,構件的實現僅需保證要實現在全部的提供接口中的操作。使用端口是為了能進一步控制這種實現。作為構件的一個部件,端口描述了在構件與它的環境之間以及在構件與它的內部部件之間的一個顯式的交互點。也即,端口是一個封裝構件的顯式的對外窗口,所有進出構件的交互都要通過端口。這明確地指出,構件可以擁有內部結構和形式化其交互點的一組端口。構件的外部可見行為恰好是它端口的總和。
如果一個端口提供一個特定的接口而另一個端口需要這個接口,且接口是兼容的,那么這兩個端口便是可連接的。連接件就是通過端口或接口用于構件實例間通訊的部件。
為了連接構件或把端口與構件內的部件相連,UML定義了兩種連接件:委托連接件和裝配連接件。
1. 裝配連接件
是兩個構件實例間的連接件,它定義一個構件實例提供服務,另一個構件實例使用這些服務。裝配連接件用于把一個請求接口或端口與一個提供接口或端口的連接起來。在執行時,消息起源于一個請求端口,沿著連接件傳遞,被交付到一個提供端口
2.委托連接件
把外部對構件端口的請求分發到構件內部的部件實例進行處理,或者通過構件端口把構件內部部件實例向構件外部的請求分發出去。
委托有這樣的含義:
具體的消息流將發生在所連接的端口之間,可能要跨越多個層次,最終到達要對消息進行處理的最終部件實例。這樣,使用委托連接件可對構件行為的層次分解建模。