• 沒有找到結果。

生成原始程式碼

2.  背景知識

2.4  NetBeans 內部設計

2.4.2  生成原始程式碼

NetBeans UML 提供了將 UML diagram 轉變成程式碼的功能。使用者在設計 完UML 之後,可以選擇將 UML diagram 產生成框架程式碼,框架程式碼是一份 只有架構的程式碼,程式中的邏輯和方法都尚未實做。接著NetBeans IDE 會將程 式碼產生在使用者所選擇的專案當中。

使用者選擇了產生程式碼的選項後,NetBeans 會呼叫 code generate 模組的程 序。在這個程序當中會以UML 中的 class,interface 和 enumeration 為一個檔案單 位,產生相對應的Java 檔案。產生程式碼的過程中,code generate 的程序會讀取 UML diagram 的內容,也就是 XML 文件,將一個 class(或者是 interface、enumeration) 的資訊進行整合,然後產生一個ClassInfo 的物件。ClassInfo 是一個用於描述 Java 類別的資料類別(metaclass),ClassInfo 主要功能在於傳遞 NetBeans 的模組之間所 需要的類別資訊。ClassInfo 的成員由的類別內容可以得知,此類別描述與紀錄 UML

14

當中一個 class 的完整資訊。

ClassInfo 物件除了用於紀錄類別資訊,UML 中的 operation、attribute 等其他 相關元件都有相關的類別來紀錄它們的資訊,如 MethodInfo 類別和 MemberInfo 類別。而這些類別的物件都會被ClassInfo 物件所參照。

ClassInfo 物件雖然記錄了 Java 檔案的大部分內容,但 Java 檔案的內容並不 是由ClassInfo 所產生。code generate 程序在完成了 ClassInfo 物件之後,會將物件 傳給樣板引擎:FreeMarker([13])。FreeMarker 是一個會根據樣板產生文件的工具,

而FreeMarker 所引用的樣板文件(表 2-4)可從 NetBeans 的 templete tool 中編輯。

FreeMarker 利用樣板文件和 ClassInfo 物件的資訊產生相對應的 Java 檔案。

<#--

NormalClassDeclaration -->

<#import "DeclLib.ftl" as lib />

<#macro NormalClassDeclaration classInfo nestingLevel

>

<@lib.TypeDeclarationComment classInfo nestingLevel />

<@lib.ident nestingLevel /><@lib.compress single_line=true >

<@lib.TypeDeclarationModifiers classInfo /> class ${classInfo.getShortClassName()}

<@lib.TypeDeclarationTypeParameters classInfo /> <@lib.NormalClassExtends classInfo />

<@lib.ClassImplements classInfo /></@lib.compress> {

<@lib.ClassBodyDeclaration classInfo nestingLevel+1 />

<@lib.ident nestingLevel />}

</#macro>

表 2-4 : class 樣板文件內容

3.

的state patt 使用State 的

GOF state patte

時,可以引

儲存與

gn pattern 的 段就要進行資 入design patt

用此儲存de

用Java annot 錄。在這個章

16

在UML 當中運用 state pattern 的概念。程式開發者雖然應用 design pattern 的概念,

但是在類別與方法的命名上,還是取決於程式開發者設計上的想法,因此UML 設

計完成後我們很難從它的名稱和架構來判斷它所使用的 design pattern。圖 3-2 是 命名過後的 state pattern,除了 interface 的名稱有 state 的文字以外,其它的 GOF 命名都不存在於設計中。

圖 3-2 : 經過命名後的 state pattern

我們所希望保存的design pattern 資訊,便是引用 design pattern 時各個元件所 代表design pattern 的角色。以圖 3-2 的案例來說,類別 Door 是原先 state pattern 的類別Context、interface DoorState 是原先 state pattern 的 abstrct 類別 State 而類別 OPEN 和 CLOSE 則是原先 state pattern 的類別 ConcreteState;同樣的方法(method) 亦可類推。

我們將在後續介紹如何在NetBeans UML 中儲存 design pattern 資訊。我們所 要保存的資料是能夠讓程式到產品化階段仍能夠判別出interface DoorState 是 state pattern 設計中的 abstrct 類別 State。

3.2 Design Pattern 資訊儲存

NetBeans UML 的內部資料結構是一個 XML 文件,根據 design pattern 的設計,

17

每個interfaces、classes、methods 和 variables 都可能在 design pattern 中扮演一個角 色。因此在XML 文件當中每個描述 interfaces、classes、methods 和 variables 的 xml node 都要能夠追加描述 design pattern 資訊的欄位。我們選擇利用 NetBeans 現有的 XML element <UML:TaggedValue>,然後利用這個 node 來紀錄 design pattern 的資 訊。按照2.4.1 的介紹,element <UML:TaggedValue>是 element <UML:Element.

ownedElement>的一個 sub element。

紀錄design pattern 資訊的 XML element 如表 3-1 定義之,其中的黑體字是我 們要填入的資訊。PatternType 可以被使用者編輯,但它的內容在後續規定,Pattern- Info 則任由使用者編輯,它的內容將會是 design pattern 的資訊。

-<UML:TaggedValue xmi.id="idformIDE" owner=" idformIDE " name="PatternType">

<UML:TaggedValue.dataValue>PatternInfo</UML:TaggedValue.dataValue>

</UML:TaggedValue>

表 3-1 : 紀錄 design pattern 資訊的 XML element

PatternType 所表達的 UML 元件 PatternType 的內容

Interface、Class or Enumeration patternClass

Operation patternOperation

Attribute pattern Attribute

表 3-2 : 對應 UML 元件類型的 PatternType 內容

xmi.id 和 owner 將由 NetBeans 自行創建,並且內容由 NetBeans 負責管理,

而name 這個 attribute 用來紀錄 PatternType,PatternType 是此 XML element 所描述 的元件類型,PatternType 的內容如表 3-2 的方式定義。PatternInfo 是 node 的內容,

用來紀錄此元件的 design pattern 資訊。以圖 3-2 的類別 OPEN 為例子,它的 PatternType 的 內 容 將 會 是 “patternClass” , 而 PatternInfo 的 內 容 則 為

“ConcreteState”。PatternType 的內容取決於此 element 所描述的元件類型,由表 3-2

18

定義;而PatternInfo 的內容將表達此元件在 design pattern 中扮演的角色,按照圖 3-1 與圖 3-2 的對應,PatternInfo 的內容為”ConcreteState”,因為類別 OPEN 代表 的是 ConcreteState,它必須實做 abstrct 類別 State。表 3-3 將描述類別 OPEN 在 UML 中所帶有的 design pattern 資訊,這是利用<UML:TaggedValue>來記錄資訊。

-<UML:TaggedValue xmi.id="idformIDE" owner=" idformIDE " name=" patternClass ">

<UML:TaggedValue.dataValue> ConcreteState </UML:TaggedValue.dataValue>

</UML:TaggedValue>

表 3-3 : 類別 OPEN 的 design pattern 資訊

利 用 <UML:TaggedValue> 紀 錄 design pattern 資 訊 的 主 要 原 因 是

<UML:TaggedValue>這個 node 是 NetBeans 本身提供給使用者編輯的欄位。使用

<UML:TaggedValue>紀錄 design pattern 資訊的好處是使用者可以利用 NetBeans 現 有的介面直接進行編輯,而省去我們修改NetBeans UI 的麻煩。另一個好處是因為

<UML:TaggedValue>可以有兩個以上,依照程式開發者設計的不同,同樣的 UML 元件可能同時扮演著design pattern 中的兩個角色;另一個重要的原因是,UML 在 生成source code 時,我們將利用 java annotation 來記錄此資訊,同樣的兩個以上的 java annotation 可以同時描述於一個類別(或其他元件)。根據 UML 設計上的要求與 java annotation 的特性,<UML:TaggedValue>符合我們的需求,因此利用它來記錄 design pattern 資訊。

上述是利用 element <UML:TaggedValue>來記錄 design pattern 資訊。因為

<UML:TaggedValue>是一個可以編輯的欄位,為了避免使用者的錯誤編輯,我們另 外設計了一個XML attribute 來記錄 design pattern 資訊,而這個 node 將無法被使用 者所編輯。

紀錄annotation 的 XML attribute 如表 3-4 定義之,其中的黑體字是我們要填 入的內容,但使用者並不能編輯。

19

<UML:(UML 元件) xmi.id=" idformIDE " name="editByUser" isAbstract=" editByUser "

owner="idformIDE" PatternType =" PatternInfo ">

表 3-4 : 紀錄 design pattern 資訊的 XML attribute

PatternType 與 PatternInfo 的內容與 element(表 3-1)的定義相同,差別在於 PatternType 將轉為 attribute 的名稱,PatternInfo 將會是 attribute 的內容。同樣的對 照於圖 3-1 與圖 3-2,我們挑選 OPEN 類別的方法 beTouched 做為例子,它的 XML node 內容將會如表 3-5。PatternType 為“PatternOperation”用來代表這是一個 opera- tion,接著 PatternInfo 為 “Handle”用來記錄它所扮演的角色。

<UML:Opration xmi.id=" idformIDE " name="beTouched" isAbstract="no" owner="idformIDE"

PatternOperation =" Handle ">

表 3-5 : 方法 beTouched 的 XML 內容與 design pattern 資訊

在往後的章節,不論是利用XML element 或是 XML attribute,都將用來記錄 design pattern 的資訊,因此我們稱這些 node 為 pattern node。

20

3.3 將 Design Pattern 加入 NetBeans

在定義完成Netbeans UML 如何紀錄 design pattern 資訊之後,我們必須將使 用者引入design pattern 的 UML 加入 pattern node 並且按照 GOF design pattern 的 名稱去定義他。雖然引入design pattern UML 是藉由外部的 XML 檔案。但我們不 傾向修改外部檔案,原因是加入pattern node 的行為實際上非常簡便,而且加入的 資訊可從XML 的檔案中獲取,因此沒有必要修改大量的外部檔案。

圖 3-3 : 剛引入的 design pattern UML( state pattern )

圖 3-3 為一個新引入的 design pattern UML,由圖可知它的 Classes、methods、

variables 名稱都是取自於 GOF design pattern 的設計。而我們打算加入的 design pattern 資訊正是 GOF design pattern 最原始的名稱。因此我們輪巡所有元件,加上 pattern node,而 pattern node 的內容則取自該元件的名稱,因為這些名稱正是 design pattern 資訊。引用 design pattern 是使用者本身的動作,因此我們認定引入的 UML diagram 將會是 design pattern 的元件。我們將會利用 attribute 的方式來記錄 design pattern 資訊,避免使用者不慎的修改。

UML 中的元件是否具有 pattern node 是決定使用者是否使用 design pattern 的

21

唯一依據。使用者為 UML 建構 pattern node 的方式有兩種,其一是引入 design pattern,我們的修改自動的為 UML 加入 pattern node,其二是使用者自行藉由 taggedValue 加入 pattern node。假設 UML 當中不存在任何的 pattern node,那我們 將認定此UML 不使用 design pattern 來進行設計,往後的編輯也不會詢問使用者是 否要加入pattern node。即使使用者自行仿造 GOF design pattern 繪製 UML 也是一 樣,之後的編輯和產生框架程式碼將不會連帶產生表示 design pattern 資訊的 annotation, design pattern 的資訊亦不會保留。

3.4 NetBeans UML 編輯的修改

我們將 design pattern 的概念加入 design pattern UML 當中,使用者運用 NetBeans UML 來引用 design pattern 時,我們將為之加入 patern node,而後續使用 者的編輯動作也與design pattern 相關。NetBeans 本身的 UML 編輯設計功能十分 完善,因此我們對所有編輯功能做了以下修改:針對具有pattern node 的元件進行 編輯,會進行是否加入design pattern 資訊的詢問。詢問的內容是選擇 design pattern 資訊的名稱,使用者必須選擇適當的名稱,來表示使用者加入的元件將會扮演 design pattern 中的角色。

例如design pattern 中的 state pattern,使用者可能會增加一個方法來操作 state

的操控,這個方法必須藉由使用者在UML 當中新增,而新增的過程會有選項給予

使用者選擇的design pattern 角色。為了特殊化進行的正確性,使用者必須選擇正 確的design pattern 角色,來表達這個新增的方法在 design pattern 當中代表的涵義。

根據特殊化的要求越多,特殊化所需的資訊也會增加,加上使用者可能有獨 特的程式設計模式,因此GOF design pattern 基本的資訊可能不夠達到特殊化的要

22

求。UML 設計階段所要加入的 design pattern 資訊將不僅止於 GOF design pattern 所介紹的,因此額外的design pattern 資訊是必要的。為了提升 design pattern 資訊 的名稱擴充性,我們將design pattern 資訊的內容利用外部檔案定義。以 state pattern 為例,外部檔案的定義的格式如表 3-6。

Name State Interface State Method

Handle

Field

Declaration

Class

Context

Method

request

Class

ConcreteState

Method

Handle

表 3-6 : 外部定義的 design pattern 資訊

表 3-6 是從外部檔案中擷取的 state pattern 部分,Name 欄位記錄著此 design pattern 的名稱,之後每個欄位根據元件類型的不同而具有後述 design pattern 資訊。

如要在一個state pattern 的 state interface 的 UML 圖形之中加入一個 method 的欄位,

則會有 “handle” 這個 design pattern 角色可以選擇。同理打算在 ConcreteState 的 類別當中加入method 亦會有 “handle”這個 design pattern 角色。表格的內容是以樹 狀結構解析,因此表格實質上可看作如表 3-7 的樹狀結構。

23

Name State

+ Interface State

+

Method

handle +

Field

Declaration

+ Class

Context

+

Method

request

+ Class

ConcreteState

+

Method

handle

表 3-7 : 以樹狀結構表現的 annotation 選項

在state interface 的 UML 圖形底下新增 method 可選擇 “handle”的角色,新增 field 可選擇 “Declaration”的角色,而在 ConcreteState Class 的 UML 圖形底下新增

在state interface 的 UML 圖形底下新增 method 可選擇 “handle”的角色,新增 field 可選擇 “Declaration”的角色,而在 ConcreteState Class 的 UML 圖形底下新增