[Architecture] 跨平台架構設計

摘要:[Architecture] 跨平台架構設計

[Architecture] 跨平台架構設計

跨越平台

Productivity Future Vision 2011

在開始談跨平台架構設計之前,請大家先看看上面這段影片,影片內容是微軟在2011年所描繪的未來生活藍圖。在觀看的過程中,請大家以「軟體開發人員」的角度來思考,想想軟體開發人員在其中扮演甚麼樣的角色。

跨越平台01

「Productivity Future Vision 2011」 這段影片裡面所描繪未來產品,把時間軸拉到現在來看,其實有許多概念已經悄悄融入我們的生活之中。像是影片中計程車車窗上顯示預計到達時間這樣的功能,現今許多的車款都已經配備抬頭顯示器,用來在車窗上顯示目前油量、前進速度、輪胎胎壓...等等資訊。另外像是影片中透過手機匯款給演奏老人的功能,目前生活中也可以透過NFC小額付款機制,來提供電子付款。回過頭仔細檢視一下影片內容、並且對照現在的現實生活,其實會很有感觸的發現:「隨著時間的流逝、現在就是過去的未來」。

但在感嘆著科技進步的同時,將關注點拉回到「軟體開發人員」這個工作岡位上。會發現不管未來的科技多進步,總是離不開軟體開發人員的努力:抬頭顯示器需要軟體蒐集資訊、NFC小額付款需要軟體發起交易、智慧型手機需要軟體提供APP...等等,在未來科技發展的過程中,軟體都扮演了舉足輕重的地位。甚至我們可以大膽的預測,未來是屬於軟體開發人員的舞台,軟體在生活中將會無所不在。

而「軟體在生活中將會無所不在」,這句話背後的意思,也就是說開發人員勢必要能在:雲端平台、移動平台、嵌入平台...等等異質平台上,具備跨平台開發應用程式的能力,才有機會在未來舞台上擁有一席之地。

Windows Everywhere

跨越平台02

接著,將視野拉回軟體開發人員每天的工作岡位上。一直以來我的工作都是以C#做為主要的開發語言,在早期,以C#所開發出來的應用程式只能執行在PC平台上,隨著Windows Phone的誕生讓.NET開發人員可以跨足到行動平台開發、接著XBOX的誕生讓.NET開發人員可以跨足到遊戲平台開發。.NET開發人員站在微軟這個巨人的肩膀上,隨著微軟的腳步前進,慢慢擴展自己的開發版圖。

而後續緊隨著Windows 10的出現,將所有PC平台、行動平台、遊戲平台...等等平台整合封裝為單一平台,減少跨平台開發應用程式時所需要越過的學習門檻,更進一步加快.NET開發人員擴展開發版圖的腳步。

Software Everywhere

跨越平台03

當然,軟體業界很大,微軟也只是其中的一員。近年軟體業界的潮流,隨著智慧型手機的普及,讓Android、iPhone等行動平台,深入到每個人的生活之中。而物聯網概念的風行,也讓Arduino、Raspberry Pi等嵌入平台,默默的被人們所關注。但因為這些平台,沒有微軟這樣的公司整合開發底層系統來減少不同平台之間的差異,所以造成不同平台有不同的開發語言、不同平台有各自需要越過的學習門檻。這些不同平台之間的差異,對於想要跨平台開發應用程式的開發人員來說,會是一股沉重的學習負擔,畢竟人的智慧、精力是有上限的,沒有人能夠熟知所有的開發語言規則、了解所有的開發技術細節。

Development Everywhere

跨越平台04

為了減少開發人員跨平台開發應用程式時的困擾,微軟這個巨人邁出了它的一小步,為每個異質平台建立一層抽象的執行環境:CoreCLR。這個CoreCLR的解決方案,主要封裝各種平台底層,提供開發人員統一的函式庫、一致的執行環境,讓開發人員能夠使用同一種語言,來跨平台開發應用程式。另外,微軟也透過策略夥伴所建置的Xamarin這個解決方案,提供開發人員能夠使用同一種語言,來跨平台開發應用程式的使用者介面。(Arduino、Raspberry Pi的CoreCLR尚未獲得官方證實)

微軟透過提供CoreCLR、Xamarin這兩個整合性的解決方案,減少跨平台開發應用程式時所需要越過的學習門檻,更進一步加快.NET開發人員擴展開發版圖的腳步。至此,也真正的讓.NET開發人員能夠跨出微軟的生態圈,開發任意平台之上的應用程式。從這個角度去看,我想這會是影響.NET開發人員職業生涯很重要的一大步。

Application Everywhere

跨越平台05

微軟為開發人員,鋪平了跨平台開發應用程式的最後一哩路,讓開發人員能夠使用同一種語言,開發任意平台上的應用程式。接著就輪到開發人員接棒,要開始思考如何讓應用程式能夠跨平台執行。

以CoreCLR這個封裝各種平台底層、提供一致執行環境的跨平台解決方案來說,因為種種硬體限制、平台特性的考量,微軟採用的設計方式是將原本完整的CLR,拆解出必要部分來做為CoreCLR的核心模組、其餘部分則依平台特性來提供功能模組。這樣做的好處,除了能夠降低CoreCLR封裝平台底層時的複雜度之外,也精簡CoreCLR所佔的記憶體大小,讓CoreCLR能夠適應於更多硬體等級不高的異質平台。但是,隨之而來的壞處也很明顯:哪些沒有被納入核心的功能模組不是所有平台都能使用。例如:提供剖析XML格式的函式庫,可能被納入功能模組,然後只有PC平台提供該模組,而嵌入平台不提供。這樣在我們的程式使用剖析XML這個函式庫的開發情景中,就會發生在嵌入平台上,因為沒有提供對應的功能模組,所以造成應用程式無法執行的困境。

像這樣被排除在CoreCLR核心模組之外的功能模組還有很多,開發人員可以從軟體架構設計的層面切入,在規劃軟體架構的時候就切割與功能模組的相依性,讓應用程式單單只依賴必要的核心模組。而在需要使用功能模組的功能時,則是套用依賴注入的模式,依照平台特性來注入平台所支援的功能模組,這樣就能避免直接引用功能模組所帶來的困擾。

接下來的內容,會以上述相同內容的角度來做說明,探討如何從軟體架構設計的層面切入,一步一步處理應用程式跨平台執行時,常會遇到的幾個問題挑戰、以及對應問題的解決方案。

架構設計

分層架構

架構設計01

一個跨平台執行的應用程式,可以選用3-Layer架構設計,做為應用程式的分層架構。3-Layer架構設計有著簡潔、清晰、易懂...等優點,以此架構為核心延伸擴展去處理跨平台執行時所會遇到的各種問題挑戰,這樣可以大幅降低開發人員學習門檻,快速讓團隊裡的每個開發人員都能發揮出實質戰力。在3-Layer架構設計中將軟體開發所產出的程式碼,依照不同用途歸類為:系統展示層、領域邏輯層、資料存取層。其中:

系統展示層 (Presentation Layer),用來歸類「提供操作介面」的相關程式碼。例如:提供Textbox接受使用者輸入地址資料、透過MessageBox通知使用者處理結果、甚至是提供Web API給遠端系統使用,這些程式碼都會被歸類在展示層之中。

領域邏輯層 (Domain Layer),用來歸類「封裝系統邏輯」的相關程式碼。例如:商城系統的商品資料、購物車、對帳單,或者是出勤系統的上下班記錄、員工資料…等等,這些程式碼都會被歸類在領域邏輯層 之中。

資料存取層 (Access Layer),用來歸類「實作資料存取」的相關程式碼。例如:將資料存放到SQL Server、或者是從遠端WebService取得資料…等等,這些程式碼都會被歸賴在存取層之中。

透過套用這樣的3-Layer架構設計,在開發過程中能夠減少需要思考的設計內容,讓開發人員一次只需要思考某個面向的設計內容。而在後續的維護過程中,也讓開發人員能夠分門別類的去理解既有的程式內容。

架構設計02

但是光只有3-Layer架構設計,並不足以提供應用程式跨平台執行的能力,因為每個平台所支援的執行檔格式不盡相同:在PC平台上會以EXE檔做為執行檔、在Android需要將軟體內容包裝為APK檔才能交付客戶使用,在Raspberry Pi中則是需要透過燒錄Binary檔的方式才能執行。而在3-Layer架構設計中只定義了:使用介面、領域邏輯、資料存取...等等程式碼,如何歸類至不同的層級,並沒有定義該如何將應用程式封裝為不同平台的執行檔。

為了解決要依平台來編譯執行檔才能執行的問題,開發人員可以在分層架構中,加入額外的一層Hosts Layer(程式執行層)。加入Host層後,所有可以被編譯成為執行檔的執行檔專案,都會被歸類在Host層之中,其餘的系統展示層、領域邏輯層、資料存取層則是被歸類為一般的函式庫專案,而其中執行檔專案用來組合各種函式庫專案,建立出不同平台的應用程式。透過這樣切割執行檔專案、函式庫專案的方式,後續只要想在哪個平台上執行應用程式,就在Host層中加入一個對應平台的執行檔專案,接著組合函式庫專案來進行編譯、產生執行檔,就能夠提供該平台版本的應用程式,這也就提供了應用程式跨平台執行的能力。

Database跨平台解決方案

架構設計03

每個平台所能支援使用的資料儲存設備不盡相同:在移動平台上可以會選用SQLite作為儲存設備、在雲端平台上可能會選用Azure SQL做為儲存設備、在嵌入平台上則可能選擇EEPROM做為儲存設備。當應用程式跨平台執行時,第一個會遇到的問題挑戰就是:資料儲存模組無法跨平台。

為了解決資料儲存模組無法跨平台的問題,開發人員可以在架構設計的層級,套用IoC模式來切割應用程式與資料儲存模組的之間相依性。套用IoC模式之後,應用程式就只相依於自己定義的資料存取介面,不再相依於特定平台的資料存取模組。接著只要在應用程式啟動時,注入依照平台特性所實作的資料存取介面,就可以建立動態更換資料儲存模組的功能,進而提供應用程式跨平台執行的能力。

以一個計算BMI數值的應用程式來說,需要將使用者輸入的身高體重的儲存起來,提供下次使用者查詢使用。當開發人員依照解決方案建立應用程式後,應用程式執行時,會先依照執行平台建立儲存設備相關類別來提供應用程式使用。執行在移動平台會使用SQLite做為儲存設備、執行在嵌入平台上則是會使用EEPROM做為儲存設備,透過這樣的方式讓應用程式跨平台執行時依然可以正常的將資料存放到儲存設備之中。

參考資料:

[Object-oriented] 控制反轉 - 昏睡領域

[Architecture Pattern] Repository - 昏睡領域

DI Framework跨平台解決方案

架構設計04

使用物件導向技術開發的應用程式,常常會搭配依賴注入模組用來在應用程式之外透過配置的方式,來動態更換應用程式所使用的功能模組。但因為目前CoreCLR還算是在發展中的技術,所以在這個時間點會很尷尬的發現,常見的MEF、Unity、Spring...等等依賴注入模組,還沒有跟上這波的改變來更新版本,所以目前無法跨平台來使用。

為了解決依賴注入模組無法跨平台的問題,開發人員可以在架構設計的層級,選擇套用Factory模式來取代依賴注入模組所提供的功能。套用Factory模式之後,應用程式就只相依於自己定義的功能模組工廠,不再相依於無法跨平台執行的依賴注入模組。雖然Factory模式只能生成加入專案參考的已知功能模組,但是一般的專案其實都還沒有到達需要動態掛載功能模組的規模。所以透過Factory模式來生成注入物件,已經能夠滿足大部分專案的需求,並且提供應用程式跨平台執行的能力。

以一個加密User密碼的應用程式來說,需要將使用者輸入的密碼加密後傳輸到遠端驗證。當開發人員依照解決方案建立應用程式後,應用程式不需要引用外部的依賴注入模組,而只需要使用內建的加密模組工廠,生成系統所使用的加密規則模組,就可以讓應用程式正常的提供軟體功能。

參考資料:

UI Framework跨平台解決方案

架構設計05

每個平台所使用的使用者介面框架不盡相同:在Windows Phone中可以使用XAML來定義使用者介面、在Android中使用XML來定義頁面排版、在iPhone中則是使用StoryBoard來描述頁面流程。當開發需要使用者介面的跨平台應用程式時,最大的一個問題挑戰就是:每個平台的使用者介面框架都不同,應用程式無法跨平台執行。

為了解決使用者介面框架無法跨平台的問題,開發人員可以在架構設計的階段,直接選用Xamarin.Forms來做為Presentation Layer的使用者介面框架。使用Xamarin.Forms做為使用者介面框架之後,開發人員只需要依照Xamarin.Forms所定義的編碼規則來撰寫XAML檔案。在應用程式執行的階段,Xamarin.Form所內建Render Engine就會將XAML檔案內容渲染成為執行平台所能呈現的使用者介面,直接提供應用程式跨平台執行的能力。

以一個計算房貸利息的應用程式來說,需要在使用者介面上顯示輸入貸款金額、利息成數這兩個文字對話框,提供使用者輸入相關資料。當開發人員依照解決方案,使用Xamarin.Forms建立應用程式後,應用程式執行在Windows Phone,就會使用Windows Phone的控制項來呈現畫面;而應用程式執行在iPhone,則是會使用iPhone的控制項來呈現畫面。

參考資料:

Log Framework跨平台解決方案

架構設計06

一個應用程式的開發,Log是一個不可或缺的功能。不管是做問題的追查、或是狀態的分析,有了Log的輔助,讓開發人員再發生問題的時候有跡可循。而這些提供Log功能的訊息紀錄模組,開發人員可以選用.NET內建的EventLog、或者是第三方的Log4net...等等來使用。但是同樣因為目前CoreCLR還算是在發展中的技術,所以上述這些常見的訊息紀錄模組,還沒有跟上這波的改變來更新版本,所以目前無法跨平台來使用。

為了解決訊息紀錄模組無法跨平台的問題,開發人員可以在架構設計的層級,套用IoC模式來切割應用程式與訊息紀錄模組的之間相依性,讓應用程式只相依於自己定義的訊息紀錄介面,並且為這個訊息紀錄介面套用Service Locator模式來建立全域通用的物件參考。接著只要在應用程式啟動時,生成依照平台特性所實作的訊息紀錄介面,並且注入到全域通用的物件參考中,就可以完成動態更換訊息紀錄模組的功能,進而提供應用程式跨平台紀錄Log的能力。

參考資料:

[Object-oriented] 控制反轉 - 昏睡領域

[Architecture Pattern] Service Locator - 昏睡領域

[Architecture Pattern] Inversion of Logging - 昏睡領域

放眼未來

Microsoft HoloLens

討論了幾個應用程式跨平台執行時,常會遇到的問題挑戰、以及對應的解決方案後,相信開發人員對於如何開發跨平台應用程式有個一定程度的了解。接著,請大家再看看上面這段影片,影片內容是微軟預計要推出的產品:Microsoft HoloLens。在觀看的過程中,同樣請大家以「軟體開發人員」的角度來思考,想想軟體開發人員在其中能扮演甚麼樣的角色。

放眼未來01

第一次看這段影片的時候,微軟這個主打3D擴增實境的產品:Microsoft HoloLens,馬上深深震撼了我的心。透過3D顯示、加上擴增實境的功能組合,讓現實與虛擬的界線變得模糊,開發人員完全能夠在擴增實境中虛擬出各種輸入輸出設備,來提供使用者使用。這無形中,就打破了現今硬體輸入輸出方式固定、開發成本過高的限制,讓軟體的各種概念、發想不再被硬體所侷限,只要你想得出來就能夠實現。雖然我們還沒有使用過Microsoft HoloLens的實際成品,但是想像這個技術成熟的那一天,低頭問問自己:「當硬體不再成為綑綁,軟體你敢飛得多遠」,相信每個人都能看到一個不同的世界。

最後,期許大家能夠打破心的限制,設計出更多推動人類進步的軟體。謝謝。

期許自己
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。