軟件需求包括三個不同的層次:業(yè)務(wù)需求,用戶需求和功能需求(也包括非功能需求)。售前人員用PowerPoint和Word編寫客戶的業(yè)務(wù)需求,為客戶編寫藍(lán)圖;項目經(jīng)理則用Word編寫用戶需求規(guī)格說明書;而系統(tǒng)架構(gòu)師又會采用UML 等另外一套建模技術(shù)對用戶需求進(jìn)行系統(tǒng)分析和設(shè)計。
除此之外,出于種種原因,客戶的需求幾乎肯定是要頻繁發(fā)生變化的,哪怕是簽了板上釘釘?shù)暮贤?,實施一個軟件項目不可能總是陷入到PPT或者是Word文檔的修改當(dāng)中。如果有一個建模工具,能夠由這幾類人員統(tǒng)一使用,而且隨著客戶需求變化,多個模型之間也可以相互轉(zhuǎn)化,再加上結(jié)合MDA/MDD 思想,這個工具能夠自動生成一些能夠減少程序員重復(fù)勞動的代碼,那將能夠極大提高軟件開發(fā)企業(yè)的開發(fā)效率,使得應(yīng)用軟件做到真正“隨需應(yīng)變”。這恐怕也是軟件公司夢寐以求的“銀彈”。
但是,即使是UML創(chuàng)始人之一的James Rumbaugh 也說UML在對業(yè)務(wù)的描述上確實是有缺陷的,這些缺陷源于它并非為描述業(yè)務(wù)而設(shè)計。但是,通過引UML的擴(kuò)展機(jī)制和UML2變化最大的Activity Modeling,還是為業(yè)務(wù)建模和多種模型之間的相互轉(zhuǎn)化帶來了一絲曙光。
本文重點在于講述如何用UML2和GEF/EMF實現(xiàn)這個捕獲企業(yè)需求的建模工具上,而不是講述如何用UML2進(jìn)行企業(yè)建模,所以本文的重點將放在UML2元模型和GEF/EMF具體技術(shù)上,用UML2作為理論依據(jù)把企業(yè)業(yè)務(wù)需求和他們整合在一起,以實現(xiàn)模型驅(qū)動思想的開發(fā)。我們用UML2的Activity Model作為我們例子的元模型,EMF作為具體實現(xiàn)模型,GEF作為我們的表示層,這就是UML2、EMF和GEF三者之間的關(guān)系。
這是一個很簡單的采購審批流程,采購員提出采購申請,錄入采購申請單(輸出采購申請單),采購部門處長、部長或者具有采購審批權(quán)限的審批人,對采購申請單進(jìn)行審批(輸出是采購訂單)。審批通過,則采購申請單自動生成采購訂單,審批不通過,則退回采購員,采購員修改原采購申請單,重新提交。
下面采用UML2和GEF/EMF實現(xiàn)這個業(yè)務(wù)建模工具(而不是一個用來畫工作流的工具)。
企業(yè)建模有很多建模方法,如:ARIS 、IDEF 和 UML。為了使業(yè)務(wù)模型能夠更好的轉(zhuǎn)化為信息系統(tǒng)分析模型,所以我們采用面向?qū)ο骍ML技術(shù)來描述一個業(yè)務(wù)。
下面將結(jié)合UML2的Activity Model來解釋上述業(yè)務(wù)建模流程?;顒訄D是UML所有圖中變化最大的一種。UML 1.5 版本從早期版本中繼承了狀態(tài)機(jī)的概念,并將其改進(jìn)為流程圖,稱之為活動圖。令人遺憾的是 ,狀態(tài)機(jī)的潛在含義限制了其明確意圖,這使得用戶感到很困惑。特別是那些沒有面向?qū)ο蟾拍畹挠脩舾鼘ML 1.x 的活動模型無所適從。類似的情形還涉及到UML 1.5 中包含的那些控制流和數(shù)據(jù)流模型。基于以上這些經(jīng)驗,UML2重新定義了Activity Model,并且和UML1.5的Action Model整合在一起?;顒訄D的目的也發(fā)生了相當(dāng)大的變化,它本來用于描述工作流程,現(xiàn)在它也包含一些必須的新特性使得它可以支持工作流程的自動化(automation)。原來的活動概念(Activities),改稱動作(Action)。活動成了一個更高層次的概念,它包含一個動作序列。因此一個活動圖展現(xiàn)了一系列的動作,這些動作一起組成了活動。
從圖3中我們可以看到,Basic Activities的繼承分支有兩個方向,主要的一個是Structured Activities,用于軟件建模(對應(yīng)的類名是Action),另外的一個分支(Intermediate and Complete Activities)則用于一般過程建模。
UML2 活動(Activity)中包含有由邊連接起來的組成完整流程圖的節(jié)點(Node)。一個Activity可以包含多個Action。Activity的結(jié)點(Node)分為三大類:動作結(jié)點(Action Node)、控制結(jié)點(Control Node) 和 對象結(jié)點(Object Node)。動作結(jié)點主要是處理它接收到的控制流和數(shù)據(jù)值,或者提供這些動作和數(shù)據(jù)給其他動作;控制結(jié)點主要是路由控制流和數(shù)據(jù)值(比如判斷框);對象結(jié)點主要用于存儲臨時數(shù)據(jù),在編程方面,就是一個方法的參數(shù)對象。
我們再來看看采購訂單流程業(yè)務(wù)模型中所涉及到的幾個概念:
1、業(yè)務(wù)員/采購審批人員:在業(yè)務(wù)建模中我們稱為業(yè)務(wù)角色(business worker)。業(yè)務(wù)角色是在業(yè)務(wù)中發(fā)揮作用的人的抽象,完成特定的工作,操縱業(yè)務(wù)實體,和其他業(yè)務(wù)角色交互。
2、采購申請單/采購訂單:在業(yè)務(wù)建模中我們稱之為業(yè)務(wù)實體(Business Entity)。在業(yè)務(wù)模型中,業(yè)務(wù)實體代表業(yè)務(wù)角色處理或使用的“事物”(A business entity represents a "thing" handled or used by business workers.)。航空公司今天打折,明天又不打,還有明折、暗折??墒菣C(jī)票從來沒見有什么大的變化,從來也只有那幾樣屬性:價格、航班、出發(fā)地、目的地。所以業(yè)務(wù)實體是比較穩(wěn)定的。一般而言,一個好的業(yè)務(wù)實體不包含關(guān)于其使用主體和使用方法的信息(RUP)。在UML2中,它與Activity Model的Object Node相對應(yīng)。在實際軟件建模的時候,Business Entity對應(yīng)著域模型(Domain Model)。
3、輸入采購申請單/審批采購申請單:對應(yīng)UML2 Activity Model中的Action;
4、判斷框:對應(yīng)UML2 Activity Model中Control Node之一的Decision;
5、控制流和信息流:對應(yīng)UML2的Control Flow和Information Flow。
整個一個采購流程則對應(yīng)UML2一個Activity。
我們利用Eclipse插件eclipseuml (http://www.omondo.com/download/index.html)對上述業(yè)務(wù)模型所涉及到的business worker 、Action、Business Entity、Decision、Control Flow和Information Flow等元素進(jìn)行EMF建模。
我們用Element作為Business Worker 、Action、Business Entity、Decision的基類。抽出這些元素在圖形中所共有的height、name、caption、width、x坐標(biāo)、y坐標(biāo)等基本信息。其中,Condition類表示Decision,Activity類 表示Action, Business Worker 類表示業(yè)務(wù)模型中的Business Worker,Business Entity類表示表示業(yè)務(wù)模型中的Business Entity,。對于Connection、Node、Diagram、Point、Dimension等類,它們是由于創(chuàng)建GEF應(yīng)用程序所需要的輔助類。由于我們是在探討如何對業(yè)務(wù)模型、軟件模型統(tǒng)一建模,采用UML2作為我們的建模理論基礎(chǔ),如果要完善這個系統(tǒng),這將是一個非常浩大的工作,所以我們并未嚴(yán)格按照UML2的Action的定義來對Action建模,比如在UML2中,Action有輸入、輸出,叫Pin,輸入叫InputPin, 輸出叫OutputPin。Pin 是一種 object node,在流中用于存儲臨時數(shù)據(jù).
當(dāng)我們用eclipseuml,創(chuàng)建EMF Class Diagram的時候,eclipseuml會為我們自動生成.ecd 、model.ecore和 .genmodel 三個文件。我們建好自己的EMF模型以后,就可以用.genmodel自動生成Model對應(yīng)的Java代碼了。
有了EMF模型,我們既可以利用EMF的代碼生成工具得到一個可用編輯器(有興趣的可以參照Merlin開源項目 http://sourceforge.net/projects/merlingenerator/ ),也可以自己編寫一個GEF編輯器,讓GEF利用EMF構(gòu)造的模型。GEF的設(shè)計沒有對模型部分做任何限制,也就是說,我們可以任意構(gòu)造自己的模型,唯一須要保證的就是模型具有某種消息機(jī)制,以便在發(fā)生變化時能夠通知GEF(通過EditPart)。這里我們用后一種方法作為自己的例子。
步驟一:生成我們自己的業(yè)務(wù)建模視圖:
我們在plugin.xml文件里面加入:
<extension point="org.eclipse.ui.perspectives">
<perspective name="業(yè)務(wù)建模" class="org.bizsolution.jetblue.ui.perspective.ui.BusinessModelingPerspective"
id="org.bizsolution.jetblue.ui.perspective.BusinessModelPerspective"
icon="icons/bus_lvl_model_pers.gif">
</perspective>
<perspective
name="設(shè)計建模"
class="org.bizsolution.jetblue.perspective.ui.DesignModelingPerspective"
id="org.bizsolution.jetblue.perspective.ui.DesignModelPerspective"
icon="icons/bus_lvl_model_pers.gif">
</perspective>
</extension>
步驟二:生成自己的TreeView:
<extension point="org.eclipse.ui.views">
<view name="業(yè)務(wù)建模" icon="icons/buslvlmodelnav.gif" class="org.bizsolution.jetblue.ui.views.businessmodeling.view.NavigationTreeEditorView"
id="org.bizsolution.jetblue.ui.views.businessmodeling.view.NavigationTreeEditorView" />
</extension>
步驟三:生成自己的GEF編輯器:
<extension point="org.eclipse.ui.editors">
<editor class="org.bizsolution.jetblue.ui.BlueBirtEditor"
contributorClass="org.bizsolution.jetblue.ui.JetBlueEditorActionBarContributor"
default="true"
extensions="jbm"
icon="icons/shapes.gif"
id="org.bizsolution.jetblue.ui.BlueBirtEditor"
name="Business Model"/>
</extension>
步驟四:當(dāng)模型用EMF實現(xiàn),EditPart應(yīng)實現(xiàn)org.eclipse.emf.common.notify.Adapter接口,因為EMF的每個模型對象都是Notifier,它維護(hù)了一個Adapter列表,可以把Adapter作為監(jiān)聽器加入到模型的這個列表中。
public void notifyChanged(Notification notification) {
int type = notification.getEventType();
int featureId = notification.getFeatureID(ModelPackage.class);
if (type == Notification.SET) {
switch (featureId) {
case ModelPackage.JET_BLUE_ELEMENT__X:
case ModelPackage.JET_BLUE_ELEMENT__Y:
case ModelPackage.JET_BLUE_ELEMENT__WIDTH:
case ModelPackage.JET_BLUE_ELEMENT__HEIGHT:
case ModelPackage.JET_BLUE_ACTIVITY__NAME:
case ModelPackage.JET_BLUE_ELEMENT__CAPTION:
refreshVisuals();
break;
}
} else if (type == Notification.ADD || type == Notification.REMOVE) {
switch (featureId) {
case ModelPackage.JET_BLUE_ELEMENT__SOURCE_CONNECTIONS:
refreshSourceConnections();
break;
case ModelPackage.JET_BLUE_ELEMENT__TARGET_CONNECTIONS:
refreshTargetConnections();
break;
}
}
}
步驟五:初始化我們的Palette , 加入Business Worker 、Action、Business Entity、Decision等元素。
PaletteDrawer businessProcessDrawer = new PaletteDrawer("Business Process");
CombinedTemplateCreationEntry component = new CombinedTemplateCreationEntry ("Business Worker", "Create an Business Worker", BusinessWorker.class, new CreationFactory() {
public Object getNewObject() {
return ModelFactory.eINSTANCE.createJetBusinessWorker();
}
public Object getObjectType() {
return null;
}
},BlueBirtPlugin.getImageDescriptor("icons/swimminglanec16.gif"), BlueBirtPlugin.getImageDescriptor("icons/businessworker.gif"));
businessProcessDrawer.add(component);
….
….
這樣,我們就用GEF/EMF建立了一個企業(yè)業(yè)務(wù)需求捕獲模型的工具。
讓我們走的更遠(yuǎn)
我們用GEF/EMF建立了一個業(yè)務(wù)需求捕獲模型工具,但是有了這個工具,距離我們的理想目標(biāo)“軟件建模和業(yè)務(wù)建?;ハ噢D(zhuǎn)化”差距還是很遠(yuǎn)的。我們可以繼續(xù)完善這個工具,繼續(xù)基于UML2的理論,創(chuàng)建類圖,序列圖和用例圖等等。事實上,Eclipse組織也有一個開源實現(xiàn)UML2的項目。有興趣的可以關(guān)注它。
客戶的需求總是在不斷的發(fā)生變化,使我們不得不考慮新一代的基于模型驅(qū)動開發(fā)的一些方法和技術(shù),使得軟件的生命周期更長一些,更客戶化一些,更可以定制一些。本文摸索性的從技術(shù)上提出業(yè)務(wù)建模和軟件建模相互轉(zhuǎn)化的一些話題,希望能夠得到大家的批評和指正。
參考資料
1、 UML 2.0 Superstructure Specification05-07-04
2、 China UML--軟件和需求的實踐(4-1)業(yè)務(wù)建模時期
聲明:該文章已發(fā)表于《程序員》2006年第五期,如要引用請注明出處。