l

2012年8月9日 星期四

軟體架構也可逐步成長(3):往下展開實例

August 08 17:35~18:53

這系列寫到第三集,相信很多鄉民越來越不了解Teddy在胡說八道些什麼。今天稍微用一個比較具體一點的例子來說明一下。請參考圖一,假設鄉民們要開發一個保全監控軟體,當客戶端發生異常時,可以把異常結果傳回監控中心。平常這個監控系統也可以把客戶端的影像或是環境資料(例如溫度、濕度)傳回監控中心。由於客戶端可被監控的類型很多(例如,窗戶是否被打開、溫度是否異常、監視器是否拍到可疑入侵畫面),因此下圖中以Client Type A、B、C、D來表示。不同的Client Type可能連接到後端不同的硬體設備(Device A、B、C、D等,實際受監控的裝置)。

螢幕快照 2012-08-08 下午5.46.12

圖一:初始軟體架構

 

在監控中心會有一個Server(軟體),負責記錄與保存Client端所回傳的資料,並將這些資料存放在Database中。最後系統會透過UI子系統讓使用者可以查詢監控資料,或是在遠端執行控制命令(例如命令遠端設備發出警報聲)。

這樣的系統架構要如何設計?

以最初略的角度來看,圖一就是這個系統的系統架構

鄉民甲:什麼,這樣隨便畫幾個方塊,拉幾條線,就是系統架構?

Teddy:對啊。

鄉民甲:那你告訴我,這裡面用到什麼architecture pattern?

Teddy:就最常見的client-server這個architecture pattern啊。請參考圖二,當兩個不同的模組(或子系統)互動時,其中一個模組扮演client角色,另一個扮演server角色。Client與Server可以存在不同的電腦中,此種架構就形成典型的分散式運算架構。

螢幕快照 2012-08-08 下午6.06.54

圖二:標示出Client-Server角色

鄉民甲:但是這樣還是太抽象了啊,例如,圖二中的Server面對著這麼多種的Client(Type A、B、C、D),彼此之間要怎麼溝通?而且萬一有一天世界上又出現了一種新的Device Z,導致於需要一個新的Client Type Z,那麼不是要去修改Server的程式碼,才可以和這種新的Client Type Z溝通嗎?

Teddy:所以你面對到的是一個怎樣的問題?

鄉民甲:算是擴充性的問題嗎?

Teddy:對,而且未來要擴充的對象還無法預測。

鄉民甲:那怎麼辦?

Teddy:想一下有哪些物件導向設計原則可以解決這種擴充性的問題?或是有沒有什麼architecture pattern可以使用?

鄉民甲:就是不知道我才會是「鄉民甲」啊,我如果知道的話就變成「某大大」了XD。

Teddy:這裡可以嘗試套用一下Plug-in這個architecture pattern。

螢幕快照 2012-08-08 下午6.17.02

圖三:套用Plug-In

 

Teddy:你有沒有觀察到,還有一個地方也可以繼續套用Plug-in?

鄉民甲:ㄟ,你是說…Client Type A、B、C、D這些和後面的各種不同Device之間嗎?

Teddy:沒錯,因為Server與Client Type A、B、C、D之間的關係,和Client Type A、B、C、D與後端各種不同Device之間的關係非常像。既然剛剛套用了一次Plug-in,現在可以繼續套用一次。

螢幕快照 2012-08-08 下午6.21.55

圖四:再次套用Plug-In

 

鄉民甲:那Server與Database之間呢?

Teddy:這個系統需要支援多種不同的資料庫嗎?

鄉民甲:現在這個需求不是很明確,但是如果可以支援不同的資料庫,應該會比較好推銷這個產品。

Teddy:這樣的話在Server與Database之間,以及UI與Database之間,就可以套用OR-Mapping的架構來做為資料存取的方法。

 

螢幕快照 2012-08-08 下午6.26.38

圖五:套用OR-Mapping

***

鄉民甲:那如果細部看下去,Server的架構設計問題。在Server端針對每一個Client Type都需要紀錄他們目前的狀態,如果狀態改變之後,需要依據是先定義的規則觸發不同的行為。例如,假設某個Client的狀態由OK變成Critical(例如Client端偵測到窗戶被打開),此時Server要自動發出簡訊給派駐在外的保全人員。這個問題要如何處理?

Teddy:你有學過GoF的design pattern嗎?

鄉民甲:沒有耶。

Teddy:難怪你不知道,你剛剛敘述的問題,可以套用State、Observer、與Command這幾個design pattern。

鄉民甲:喔,這樣啊!

鄉民甲:那如果Server需要…

Teddy:等一下,不要再如果下去了。時間到了,Teddy要下班了 微笑

***

鄉民們還記得Teddy在這系列第一集裡面提到的「整體先於部分,然後透過差異化的過程將整體逐步展開」的這個觀念嗎?

上面的例子就是一種逐步展開的過程。當然鄉民們可能會說,實際上專案沒那麼簡單啦,還有很多細節需要決定。例如,採用哪種框架、選用那些元件等等。沒錯,這些都是在「逐步展開的過程中」會遭遇到的技術問題。在某些情況之下,如果選錯了技術框架或是軟體元件,替換的成本是很高的。但是也有很多時候,可以透過良好的物件導向設計方法(最簡單的就是把握programming to an interface, not an implementation著個原則),把替換各種不同實作元件對於系統架構所造成的副作用降到可以接受與控制的程度

請鄉民們再讀一次昨天的這段話,看看是不是會有不同的體驗。

Somehow, the combination of tacit, culture-defined agreements, and traditional approaches to well-known problems, insured that even when people were working separately, they were still working together, sharing the same principles.

***

友藏內心獨白:技術能力提升,才有可能變得敏捷。

1 則留言: