?
????軟件需求包括三個不同的層次:業務需求,用戶需求和功能需求(也包括非功能需求)。售前人員用PowerPoint和Word編寫客戶的業務需求,為客戶編寫藍圖;項目經理則用Word編寫用戶需求規格說明書;而系統架構師又會采用UML 等另外一套建模技術對用戶需求進行系統分析和設計。
除此之外,出于種種原因,客戶的需求幾乎肯定是要頻繁發生變化的,哪怕是簽了板上釘釘的合同,實施一個軟件項目不可能總是陷入到PPT或者是Word文檔的修改當中。如果有一個建模工具,能夠由這幾類人員統一使用,而且隨著客戶需求變化,多個模型之間也可以相互轉化,再加上結合MDA/MDD 思想,這個工具能夠自動生成一些能夠減少程序員重復勞動的代碼,那將能夠極大提高軟件開發企業的開發效率,使得應用軟件做到真正“隨需應變”。這恐怕也是軟件公司夢寐以求的“銀彈”。
但是,即使是UML創始人之一的James Rumbaugh 也說UML在對業務的描述上確實是有缺陷的,這些缺陷源于它并非為描述業務而設計。但是,通過引UML的擴展機制和UML2變化最大的Activity Modeling,還是為業務建模和多種模型之間的相互轉化帶來了一絲曙光。
本文重點在于講述如何用UML2和GEF/EMF實現這個捕獲企業需求的建模工具上,而不是講述如何用UML2進行企業建模,所以本文的重點將放在UML2元模型和GEF/EMF具體技術上,用UML2作為理論依據把企業業務需求和他們整合在一起,以實現模型驅動思想的開發。我們用UML2的Activity Model作為我們例子的元模型,EMF作為具體實現模型,GEF作為我們的表示層,這就是UML2、EMF和GEF三者之間的關系。
????這是一個很簡單的采購審批流程,采購員提出采購申請,錄入采購申請單(輸出采購申請單),采購部門處長、部長或者具有采購審批權限的審批人,對采購申請單進行審批(輸出是采購訂單)。審批通過,則采購申請單自動生成采購訂單,審批不通過,則退回采購員,采購員修改原采購申請單,重新提交。
下面采用UML2和GEF/EMF實現這個業務建模工具(而不是一個用來畫工作流的工具)。
????企業建模有很多建模方法,如:ARIS 、IDEF 和 UML。為了使業務模型能夠更好的轉化為信息系統分析模型,所以我們采用面向對象UML技術來描述一個業務。
下面將結合UML2的Activity Model來解釋上述業務建模流程。活動圖是UML所有圖中變化最大的一種。UML 1.5 版本從早期版本中繼承了狀態機的概念,并將其改進為流程圖,稱之為活動圖。令人遺憾的是 ,狀態機的潛在含義限制了其明確意圖,這使得用戶感到很困惑。特別是那些沒有面向對象概念的用戶更對UML 1.x 的活動模型無所適從。類似的情形還涉及到UML 1.5 中包含的那些控制流和數據流模型。基于以上這些經驗,UML2重新定義了Activity Model,并且和UML1.5的Action Model整合在一起。活動圖的目的也發生了相當大的變化,它本來用于描述工作流程,現在它也包含一些必須的新特性使得它可以支持工作流程的自動化(automation)。原來的活動概念(Activities),改稱動作(Action)。活動成了一個更高層次的概念,它包含一個動作序列。因此一個活動圖展現了一系列的動作,這些動作一起組成了活動。
????從圖3中我們可以看到,Basic Activities的繼承分支有兩個方向,主要的一個是Structured Activities,用于軟件建模(對應的類名是Action),另外的一個分支(Intermediate and Complete Activities)則用于一般過程建模。
UML2 活動(Activity)中包含有由邊連接起來的組成完整流程圖的節點(Node)。一個Activity可以包含多個Action。Activity的結點(Node)分為三大類:動作結點(Action Node)、控制結點(Control Node) 和 對象結點(Object Node)。動作結點主要是處理它接收到的控制流和數據值,或者提供這些動作和數據給其他動作;控制結點主要是路由控制流和數據值(比如判斷框);對象結點主要用于存儲臨時數據,在編程方面,就是一個方法的參數對象。
????我們再來看看采購訂單流程業務模型中所涉及到的幾個概念:
????1、業務員/采購審批人員:在業務建模中我們稱為業務角色(business worker)。業務角色是在業務中發揮作用的人的抽象,完成特定的工作,操縱業務實體,和其他業務角色交互。
????2、采購申請單/采購訂單:在業務建模中我們稱之為業務實體(Business Entity)。在業務模型中,業務實體代表業務角色處理或使用的“事物”(A business entity represents a "thing" handled or used by business workers.)。航空公司今天打折,明天又不打,還有明折、暗折。可是機票從來沒見有什么大的變化,從來也只有那幾樣屬性:價格、航班、出發地、目的地。所以業務實體是比較穩定的。一般而言,一個好的業務實體不包含關于其使用主體和使用方法的信息(RUP)。在UML2中,它與Activity Model的Object Node相對應。在實際軟件建模的時候,Business Entity對應著域模型(Domain Model)。
????3、輸入采購申請單/審批采購申請單:對應UML2 Activity Model中的Action;
????4、判斷框:對應UML2 Activity Model中Control Node之一的Decision;
????5、控制流和信息流:對應UML2的Control Flow和Information Flow。
整個一個采購流程則對應UML2一個Activity。
????我們利用Eclipse插件eclipseuml (http://www.omondo.com/download/index.html)對上述業務模型所涉及到的business worker 、Action、Business Entity、Decision、Control Flow和Information Flow等元素進行EMF建模。
????
????我們用Element作為Business Worker 、Action、Business Entity、Decision的基類。抽出這些元素在圖形中所共有的height、name、caption、width、x坐標、y坐標等基本信息。其中,Condition類表示Decision,Activity類 表示Action, Business Worker 類表示業務模型中的Business Worker,Business Entity類表示表示業務模型中的Business Entity,。對于Connection、Node、Diagram、Point、Dimension等類,它們是由于創建GEF應用程序所需要的輔助類。由于我們是在探討如何對業務模型、軟件模型統一建模,采用UML2作為我們的建模理論基礎,如果要完善這個系統,這將是一個非常浩大的工作,所以我們并未嚴格按照UML2的Action的定義來對Action建模,比如在UML2中,Action有輸入、輸出,叫Pin,輸入叫InputPin, 輸出叫OutputPin。Pin 是一種 object node,在流中用于存儲臨時數據.
??當我們用eclipseuml,創建EMF Class Diagram的時候,eclipseuml會為我們自動生成.ecd 、model.ecore和 .genmodel 三個文件。我們建好自己的EMF模型以后,就可以用.genmodel自動生成Model對應的Java代碼了。
????有了EMF模型,我們既可以利用EMF的代碼生成工具得到一個可用編輯器(有興趣的可以參照Merlin開源項目 http://sourceforge.net/projects/merlingenerator/ ),也可以自己編寫一個GEF編輯器,讓GEF利用EMF構造的模型。GEF的設計沒有對模型部分做任何限制,也就是說,我們可以任意構造自己的模型,唯一須要保證的就是模型具有某種消息機制,以便在發生變化時能夠通知GEF(通過EditPart)。這里我們用后一種方法作為自己的例子。
步驟一:生成我們自己的業務建模視圖:
我們在plugin.xml文件里面加入:
<extension point="org.eclipse.ui.perspectives">
<perspective??name="業務建模" ???????? 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="設計建模"
???????? 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="業務建模" 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>
步驟四:當模型用EMF實現,EditPart應實現org.eclipse.emf.common.notify.Adapter接口,因為EMF的每個模型對象都是Notifier,它維護了一個Adapter列表,可以把Adapter作為監聽器加入到模型的這個列表中。
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建立了一個企業業務需求捕獲模型的工具。
讓我們走的更遠
我們用GEF/EMF建立了一個業務需求捕獲模型工具,但是有了這個工具,距離我們的理想目標“軟件建模和業務建模互相轉化”差距還是很遠的。我們可以繼續完善這個工具,繼續基于UML2的理論,創建類圖,序列圖和用例圖等等。事實上,Eclipse組織也有一個開源實現UML2的項目。有興趣的可以關注它。
客戶的需求總是在不斷的發生變化,使我們不得不考慮新一代的基于模型驅動開發的一些方法和技術,使得軟件的生命周期更長一些,更客戶化一些,更可以定制一些。本文摸索性的從技術上提出業務建模和軟件建模相互轉化的一些話題,希望能夠得到大家的批評和指正。
參考資料
1、 UML 2.0 Superstructure Specification05-07-04
2、 China UML--軟件和需求的實踐(4-1)業務建模時期
聲明:該文章已發表于《程序員》2006年第五期,如要引用請注明出處。