在軟體開發的過程中,為了降低不必要的複雜度,開發者通常會採用設計與實作分離的開發原則。也就是在設計時,會針對使用者的需求來設計界面,讓設計並不涉及實作細節。直到了實作以後,才讓依設計的界面規格、以及實際軟體性能的考量來實作軟體系統。
不過,在使用者界面程式與應用服務元件不在同一個運行空間的情況下,彼此之間就會產生遠端界面呼叫的藩離。使用者界面程式如何穿透層層障礙與空間隔閡才能把呼叫要求傳送到應用服務元件呢?同樣的道理,應用服務元件又要如何才能把執行服務的結果傳送給使用者界面程式呢?
一般而言,遠端程序呼叫(RPC,remote procedure call)的協定是用來解決遠端呼叫的問題。在呼叫端發送呼叫請求訊息給遠端伺服器,然後根據呼叫端所傳送的參數將呼叫結果回傳給呼叫端。然而,對於各種不同的 RPC 的實作技術有著不同的調用協議,而且它們往往不能彼此相容。
可是這樣一來,在遠端呼叫的情況下,設計與實作就很難分離了。因為呼叫端的程式必須知道 RPC 的呼叫方式,它相依了 RPC 的實作細節。不同 RPC 的技術實作,會讓呼叫端必須更改呼叫的程式碼,因而產生了沒有必要的複雜度。
怎麼辦呢?同人在此分享個人的設計心得供大家參考,請參考下圖。
我們希望不管遠端呼叫的技術實作方式如何改變,只要呼叫界面不改變,就不會更動呼叫端的程式碼。其實只要在呼叫端與遠端應用服務元件之間設計通用的遠端呼叫界面,讓所採用之 RPC 技術可以依據通用呼叫界面實作遠端呼叫,就可以達到目的。如此,不管呼叫界面怎麼變化,都不會因此影响到 RPC 的呼叫界面。
透過通用遠端呼叫界面,RPC 技術實作負責將服務、作業、參數傳送到遠端伺服器,再由遠端伺服器依服務作業界面呼叫服務,並將執行結果依通用呼叫界面回傳,最後再將結果依呼叫端之呼叫界面傳回呼叫端,就可以順利完成服務操作的呼叫了。
基於以上的設計概念,我們只要設計一個通用的遠端呼叫界面,然後再想辦法讓呼叫端與遠端應用服務元件所要傳送的資訊轉換成這種通用界面來傳送,問題就解決了。所以我們定義了 ServiceProcessor 的通用呼叫界面,它只有一個操作 processService,可根據所傳送的服務名稱、操作名稱、以及呼叫服務操作所傳的參數,並可回傳服務操作執行結果。
服務與操作名稱無疑都可用字串來傳送,但參數及回傳值要怎麼辦呢?在物件導向的世界中,所有參數都可視做物件,物件無法直接在網路上傳輸,但我們只要將物件轉成字串格式就可以了,至於多參數的呼叫,我們所傳的則是一個陣列物件的字串格式。同理,回傳值也是物件的字串格式。
但物件如何與字串格式互轉呢?我們使用訊息格式的抽象概念來做轉換,我們定義了 BizObjectFormat 的界面,提供商業領域物件與字串格式相互轉換的實作規格。
至此,我們有了 ServiceProcessor 與 BizObjectFormat 兩個界面,接下來的問題就是呼叫端如何取得實作它們的實例,來完成服務作業的呼叫。這正可用 abstract factory 來組態設定,於是定義了 BizDelegateConfiguration 的界面,讓實作此界面的組態設定可以依實際情況取得適當的 ServiceProcessor 及 BizObjectFormat。
然而,呼叫端要如何呼叫 ServiceProcessor 呢?我們利用動態代理機制建立實作 BizService 的代理物件。在動態代理的 InvocationHandler 的實作中以 Java 為例。,會根據組態設定取得 ServiceProcessor 及 BizObjectFormat,以進行呼叫參數的格式轉換及傳送遠端服務作業的呼叫。
首先透過 BizObjectFormat 將呼叫參數從物件轉換成字串格式,再將格式轉換結果當參數透過 ServiceProcessor 呼叫服務作業,最後再將服務執行結果以 BizObjectFormat 轉換成物件後回傳呼叫端。
通常,為了減輕實作的負擔,以增加開發效率。許多開發環境多會提供自動產生 RPC 的呼叫端代理程式,而我們可將自動產生的程式設定在組態設定中。如此,呼叫端就不會與 RPC 的實作技術相依,而且當使用的 RPC 技術改變時,只要更改組態設定就可輕易地改變 RPC 的協定了。
此外,為了要正確還原物件參數及回傳值的資料型態或類別、以及可正確回傳服務作業的異常,必須對參數物件及回傳值再做一次封裝,以確保呼叫服務作業資訊的完整性。這在實作上並不困難,同時限於篇幅,此處就不再多做介紹了。
此設計已在服務導向架構中被確實的實作出來了,在呼叫訊息格式轉換中,同人是運用 XStream 來做 POJOs 與 Xml 格式的相互轉換,而我們也用 WSDL2Java 產生 web service 協定的代理程式。這個設計其實和 business delegate 樣式的相通的,雖然,當初再設計時並不是直接套用此設計樣式,而是以問題當成設計出發點的。然而,這又是「天下事一致而百慮,殊途而同歸」的再一次明證呀。
Powered by ScribeFire.
自動引用通知: 同人的生活派對 » Blog Archive » Java 泛型複雜嗎?