生意上門了,霹靂車股份有限公司(當然沒這間公司)希望我們設計一套能夠控制機車組裝生產線的程式,讓控制人員能夠經由控制面版控制生產線組裝。
目前霹靂車公司有兩個生產工廠,分別是北工廠以及南工廠,各有一條組裝線,他們希望我們能夠設計出一個框架來,讓兩間工廠都使用遵循這個框架下設計出來的控制程式。此外,生產線會隨著產品設計部門的計畫調整生產的產品,因此要能夠彈性調整生產線的控制程式,以應付不同的產品需求。
經過幾天的訪談之後,我們整理出了下面的使用案例。
主要參與者:生產線控制人員
關係人利益:
資訊部門:
組裝線自動控制程式必須遵循同一套系統框架,日後若是有新的產品要上生產線時,霹靂車的工程師要能夠自行設計符合該框架的組裝線設定程式,而不需要更動到控制端的程式。
生產線工程師:
要能夠即時反應狀況,若是有材料不足時,要立即停止生產線的動作。
倉儲單位:
要能夠即時將組裝數量更新至庫存系統。
事先條件:
輸送帶電源必須開啟(電源控制系統),各種材料數量必須充足(材料區控制系統)。
事後條件:
完成組裝後,必須增加數量至庫存系統(庫存控制系統)
Basic Flow:
1. 控制人員啟動組裝程式。
2. 放置骨架
3. 安裝輪子
4. 安裝把手
5. 安裝車殼
6. 安裝座椅
7. 送進倉庫,更新庫存系統
Alternate Flow:
2-5a.生產線傳輸帶發生故障。
1. 停止控制程式。
2b.輪子數量不足
1. 停止控制程式。
2. 通知料件區控制程式補充料件。
3b.把手數量不足
1. 停止控制程式。
2. 通知料件區控制程式補充料件
4b車殼數量不足
1. 停止控制程式。
2. 通知料件區控制程式補充料件
5b.座椅數量不足
1. 停止控制程式。
2. 通知料件區控制程式補充料件
6b.庫存系統發生錯誤
1. 庫存系統沒有反應
1a.使用本地端替用元件暫存資料
特殊需求:
為了日後生產線調整的需求,必須設計出一個一般化的框架,能夠讓霹靂車公司的資訊人員自行設計生產線的控制程式,但是不能因此更動到控制端的組裝流程。控制程式只能微調每個組裝步驟的內容,例如安裝把手時,高度或者料材的不同選擇。
關於使用案例
Basic Flow
主要情節,也可以稱作Happy Path,也就是一條能夠貫穿整個使用案例的成功路徑,並描述每個步驟的細節,過程中不會發生任何意外與分支,最終順利達成該使用案例的目的。
Alternate Flow
擴充情節,依據Basic Flow裡的每個步驟中會遭遇到的例外狀況來撰寫,如果再次遭遇到分支時,則以巢狀方式延伸下去。
撰寫使用案例的情節時,盡量避免描述到介面的操作,例如,輸入商品代碼要比用條碼機輸入商品代碼好。這是由於需求的分析重點在於釐清目的 (做什麼),而非實做的解決方案 (如何做)。
基本上本篇文章主要的目的還是為了示範Design Patterns如何應用在實際的案例上,然而現實生活中專案執行前原本就會有需求確認的工作需要先行,為的是將系統的範圍盡量先確認出來,需求的確認是軟體專案成功的基礎,畢竟軟體物件並不是天上掉下來的禮物,總是其來有自的。此外,也可藉由需求訪談的過程中明白系統(需求)的目的與願景何在。理論上,與專案目標相抵觸的功能或者需求是盡量要避免的。
此外,使用案例的寫法並沒有所謂的標準,但是基本上符合其主要的精神,就是要藉由使用案例的探討釐清需求的內容與目標,在這其中,步驟的描述文字是最重要的一環。至於UML中的使用案例圖形基本上可以幫助我們釐清系統的大範圍以及藉由圖形的展示來加速理解系統的需求方向。但那並不一定是使用案例必須的組成要素。
領域分析
由上面的使用案例中我們可以得知,組裝線控制程式會是這個系統的主軸,當然也可能會牽涉到操控者的權限,授權系統等。此外,組裝的過程中會跟若干外部系統溝通,例如料材的控制系統,產品的庫存系統等。不過為了避免耗費太多篇幅在描述這些關係,我們關注的焦點主要還是會落在組裝線控制程式上。

點選上圖可以檢視原始大小
由上面的領域圖可以知道,主要會有一個工廠的物件BikePlant以及組裝線物件BikeAssemblyLine。請注意,在這裡我們假設一個組裝工廠只會有一條組裝線,這與合理與否無關,純粹是根據現實需求中的條件來決定的,在本案例中霹靂車公司裡的一個工廠只會有一個組裝線(當然這可能也與我們偷懶有關係)。
領域分析裡的物件通常是直接引伸自現實世界中的抽象物件,所以請不要在領域物件中放入軟體物件的思維,例如資料庫物件之類的。
系統設計
在進一步的思考後,領域圖形會變換成軟體設計圖形,我們可能會決定由BikePlant擔任控制者(Controller)的角色,他會負責操控組裝線物件的動作,包括放置骨架、裝上輪子、裝上椅子…等。請注意,操控這些動作並不一定是由BikePlant來負責,只是因為在本案例中,BikePlant本身並沒有其他特殊的工作,因此讓它擔任控制者不會讓造成系統太差的內聚力。延伸來討論的話,如果BikePlant還有其他的工作,或許在BikePlant與BikeAssemblyLine之間還會多一個AssemblyController物件也不一定。

點選上圖可以檢視原始大小
上面的圖形是初步的一個成果,BikeAssemblyLine類別負責進行機車各個部位的組裝工作,而BikePlant則負責建立BikeAssemblyLine物件,以及去呼叫BikeAssemblyLine來進行組裝。

點選上圖可以檢視原始大小
不過,相信大家都還記得我們的客戶霹靂車公司的一個需求。
為了日後生產線調整的需求,必須設計出一個一般化的框架,能夠讓霹靂車公司的資訊人員自行設計生產線的控制程式,但是不能因此更動到控制端的組裝流程。控制程式只能微調每個組裝步驟的內容,例如安裝把手時,高度或者料材的不同選擇。
也就是說,在實際操控組裝線物件的BikePlant中需要定義好組裝的流程,然後從此不再更動(這樣講好像太過嚴重,有朝一日霹靂車公司還是有可能改變組裝流程的。),而資訊人員只能在這既定的流程框架下設計組裝線的物件,而不能更動到BikePlant中的控制流程。因次,我們把上圖稍微改造了一下。

點選上圖可以檢視原始大小
這張圖看起來實在很難理解,沒關係,我們來解釋一下。
我們把BikePlant變成了一個抽象類別,然後在BikePlant中去定義組裝線物件操控的流程,最後讓子類別去繼承它。

點選上圖可以檢視原始大小
如同上面程式所描述的,StartFabricate函式內定義了組裝的流程,而且繼承BikePlant的子類別將無法覆寫它,就因此達成了子類別必須依循父類別所制訂的框架的需求。
此外,BikePlant中還有一個抽象方法GetAssemblyLine,該方法的作用是選擇真正負責組裝的組裝線物件,然後傳回給StartFabricate函示使用,這樣的作法將易於變動的部分(更換組裝線設定)抽離,讓系統不會因為更換組裝線而影響到了既定的程式。另外,將GetAssemblyLine抽象化的目的是由於,客戶的兩個工廠分別負責不同的車型組裝,要選擇的組裝線也不相同,因此我們無法在父類別中決定要使用那個組裝線。此外,這樣也可以在日後霹靂車公司擴廠時,直接增加一個繼承BikePlant的子類別即可。
接下來,我們繼續看BikeAssemblyLine類別。
同樣的,我們也將BikeAssemblyLine轉換為一個抽象類別,在BikeAssemblyLine中我們定義了組裝線應該要負責的工作,並且強制子類別一定都要實作他們。

點選上圖可以檢視原始大小
我們來看北工廠要如何實作BikePlant類別。

點選上圖可以檢視原始大小
再來是南工廠的實作部分。

點選上圖可以檢視原始大小
由上面的兩個實作我們就可以看出來,子類別只需要實作選擇生產線物件的方法即可,事實上,就算子類別想要覆寫控制流程的方法也沒辦法。
當然,最重要的還是那些個生產線物件了,我們來看速克達一號的生產線程式該怎麼設計吧。

點選上圖可以檢視原始大小
當然,我們的目的是為了展示真的依照流程來執行這些組裝的動作,真正的工廠裡就是要去控制機器手臂來實際進行組裝的工作囉。
完成了所有程式之後,控制人員只要在面版上選擇北工廠或者南工廠要組裝哪一款的車子,就可以進行組裝了。

點選上圖可以檢視原始大小
由面版的結果顯示可以看出,速克達一號的確是按照抽象類別BikePlant中所設定的流程來組裝車子的。
延伸思考
各位朋友如果要把這樣的程式應用在實際工廠裡時,最有可能面臨的問題是什麼呢?當然,就是遠端控制了,我們實際上還需要設計一個能夠操控遠端元件的解決方案才能夠讓這個系統正式上線喔。至於要怎麼去設計這個架構,各位不妨腦力激盪一下!
結論
這樣的架構其實在Design Patterns中有個名堂,就叫做Factory Method Pattern,工廠方法樣式,也就是本案例中負責產生生產線物件的GetAssemblyLine方法。它的角色其實就是工廠方法。
順帶一提的,在父類別制訂流程框架的部分,我們也有個名堂可以稱呼,就叫做Template Pattern,模版樣式。也就是在BikePlant抽象類別中StartFabricate方法所負責的工作
2008/6/26 21:13|
閱讀數 : 272
|
我要推薦
|
|
文章分類:
實務應用
訂閱