[Architecture Design] 跨平台架构设计

跨越平台

Productivity Future Vision 2011

在开始谈跨平台架构设计之前,请大家先看看上面这段影片,影片内容是微软在2011年所描绘的未来生活蓝图。在观看的过程中,请大家以「软件开发人员」的角度来思考,想想软件开发人员在其中扮演甚么样的角色。

「Productivity Future Vision 2011」 这段影片里面所描绘未来产品,把时间轴拉到现在来看,其实有许多概念已经悄悄融入我们的生活之中。像是影片中出租车车窗上显示预计到达时间这样的功能,现今许多的车款都已经配备抬头显示器,用来在车窗上显示目前油量、前进速度、轮胎胎压...等等信息。另外像是影片中透过手机汇款给演奏老人的功能,目前生活中也可以透过NFC小额付款机制,来提供电子付款。回过头仔细检视一下影片内容、并且对照现在的现实生活,其实会很有感触的发现:「随着时间的流逝、现在就是过去的未来」。

但在感叹着科技进步的同时,将关注点拉回到「软件开发人员」这个工作冈位上。会发现不管未来的科技多进步,总是离不开软件开发人员的努力:抬头显示器需要软件搜集信息、NFC小额付款需要软件发起交易、智能型手机需要软件提供APP...等等,在未来科技发展的过程中,软件都扮演了举足轻重的地位。甚至我们可以大胆的预测,未来是属于软件开发人员的舞台,软件在生活中将会无所不在。

而「软件在生活中将会无所不在」,这句话背后的意思,也就是说开发人员势必要能在:云端平台、移动平台、嵌入平台...等等异质平台上,具备跨平台开发应用程序的能力,才有机会在未来舞台上拥有一席之地。

Windows Everywhere

接着,将视野拉回软件开发人员每天的工作冈位上。一直以来我的工作都是以C#做为主要的开发语言,在早期,以C#所开发出来的应用程序只能执行在PC平台上,随着Windows Phone的诞生让.NET开发人员可以跨足到行动平台开发、接着XBOX的诞生让.NET开发人员可以跨足到游戏平台开发。.NET开发人员站在微软这个巨人的肩膀上,随着微软的脚步前进,慢慢扩展自己的开发版图。

而后续紧随着Windows 10的出现,将所有PC平台、行动平台、游戏平台...等等平台整合封装为单一平台,减少跨平台开发应用程序时所需要越过的学习门坎,更进一步加快.NET开发人员扩展开发版图的脚步。

Software Everywhere

当然,软件业界很大,微软也只是其中的一员。近年软件业界的潮流,随着智能型手机的普及,让Android、iPhone等行动平台,深入到每个人的生活之中。而物联网概念的风行,也让Arduino、Raspberry Pi等嵌入平台,默默的被人们所关注。但因为这些平台,没有微软这样的公司整合开发底层系统来减少不同平台之间的差异,所以造成不同平台有不同的开发语言、不同平台有各自需要越过的学习门坎。这些不同平台之间的差异,对于想要跨平台开发应用程序的开发人员来说,会是一股沉重的学习负担,毕竟人的智慧、精力是有上限的,没有人能够熟知所有的开发语言规则、了解所有的开发技术细节。

Development Everywhere

为了减少开发人员跨平台开发应用程序时的困扰,微软这个巨人迈出了它的一小步,为每个异质平台建立一层抽象的执行环境:CoreCLR。这个CoreCLR的解决方案,主要封装各种平台底层,提供开发人员统一的函式库、一致的执行环境,让开发人员能够使用同一种语言,来跨平台开发应用程序。另外,微软也透过策略伙伴所建置的Xamarin这个解决方案,提供开发人员能够使用同一种语言,来跨平台开发应用程序的用户接口。(Arduino、Raspberry Pi的CoreCLR尚未获得官方证实)

微软透过提供CoreCLR、Xamarin这两个整合性的解决方案,减少跨平台开发应用程序时所需要越过的学习门坎,更进一步加快.NET开发人员扩展开发版图的脚步。至此,也真正的让.NET开发人员能够跨出微软的生态圈,开发任意平台之上的应用程序。从这个角度去看,我想这会是影响.NET开发人员职业生涯很重要的一大步。

Application Everywhere

微软为开发人员,铺平了跨平台开发应用程序的最后一哩路,让开发人员能够使用同一种语言,开发任意平台上的应用程序。接着就轮到开发人员接棒,要开始思考如何让应用程序能够跨平台执行。

以CoreCLR这个封装各种平台底层、提供一致执行环境的跨平台解决方案来说,因为种种硬件限制、平台特性的考虑,微软采用的设计方式是将原本完整的CLR,拆解出必要部分来做为CoreCLR的核心模块、其余部分则依平台特性来提供功能模块。这样做的好处,除了能够降低CoreCLR封装平台底层时的复杂度之外,也精简CoreCLR所占的内存大小,让CoreCLR能够适应于更多硬件等级不高的异质平台。但是,随之而来的坏处也很明显:哪些没有被纳入核心的功能模块不是所有平台都能使用。例如:提供剖析XML格式的函式库,可能被纳入功能模块,然后只有PC平台提供该模块,而嵌入平台不提供。这样在我们的程序使用剖析XML这个函式库的开发情景中,就会发生在嵌入平台上,因为没有提供对应的功能模块,所以造成应用程序无法执行的困境。

像这样被排除在CoreCLR核心模块之外的功能模块还有很多,开发人员可以从软件架构设计的层面切入,在规划软件架构的时候就切割与功能模块的相依性,让应用程序单单只依赖必要的核心模块。而在需要使用功能模块的功能时,则是套用依赖注入的模式,依照平台特性来注入平台所支持的功能模块,这样就能避免直接引用功能模块所带来的困扰。

接下来的内容,会以上述相同内容的角度来做说明,探讨如何从软件架构设计的层面切入,一步一步处理应用程序跨平台执行时,常会遇到的几个问题挑战、以及对应问题的解决方案。

架构设计

分层架构

一个跨平台执行的应用程序,可以选用3-Layer架构设计,做为应用程序的分层架构。3-Layer架构设计有着简洁、清晰、易懂...等优点,以此架构为核心延伸扩展去处理跨平台执行时所会遇到的各种问题挑战,这样可以大幅降低开发人员学习门坎,快速让团队里的每个开发人员都能发挥出实质战力。在3-Layer架构设计中将软件开发所产出的程序代码,依照不同用途归类为:系统表示层、领域逻辑层、数据存取层。其中:

  • 系统表示层 (Presentation Layer),用来归类「提供操作接口」的相关程序代码。例如:提供Textbox接受用户输入地址数据、透过MessageBox通知用户处理结果、甚至是提供Web API给远程系统使用,这些程序代码都会被归类在表示层之中。

  • 领域逻辑层 (Domain Layer),用来归类「封装系统逻辑」的相关程序代码。例如:商城系统的商品数据、购物车、对账单,或者是出勤系统的上下班记录、员工数据…等等,这些程序代码都会被归类在领域逻辑层 之中。

  • 资料存取层 (Access Layer),用来归类「实作数据存取」的相关程序代码。例如:将数据存放到SQL Server、或者是从远程WebService取得数据…等等,这些程序代码都会被归赖在存取层之中。

透过套用这样的3-Layer架构设计,在开发过程中能够减少需要思考的设计内容,让开发人员一次只需要思考某个面向的设计内容。而在后续的维护过程中,也让开发人员能够分门别类的去理解既有的程序内容。

但是光只有3-Layer架构设计,并不足以提供应用程序跨平台执行的能力,因为每个平台所支持的执行档格式不尽相同:在PC平台上会以EXE档做为执行档、在Android需要将软件内容包装为APK文件才能交付客户使用,在Raspberry Pi中则是需要透过刻录Binary档的方式才能执行。而在3-Layer架构设计中只定义了:使用接口、领域逻辑、数据存取...等等程序代码,如何归类至不同的层级,并没有定义该如何将应用程序封装为不同平台的执行档。

为了解决要依平台来编译执行档才能执行的问题,开发人员可以在分层架构中,加入额外的一层Hosts Layer(程序执行层)。加入Host层后,所有可以被编译成为执行档的执行档项目,都会被归类在Host层之中,其余的系统表示层、领域逻辑层、数据存取层则是被归类为一般的函式库项目,而其中执行文件项目用来组合各种函式库项目,建立出不同平台的应用程序。透过这样切割执行档项目、函式库项目的方式,后续只要想在哪个平台上执行应用程序,就在Host层中加入一个对应平台的执行文件项目,接着组合函式库项目来进行编译、产生执行档,就能够提供该平台版本的应用程序,这也就提供了应用程序跨平台执行的能力。

Database跨平台解决方案

每个平台所能支持使用的数据储存设备不尽相同:在移动平台上可以会选用SQLite作为储存设备、在云端平台上可能会选用Azure SQL做为储存设备、在嵌入平台上则可能选择EEPROM做为储存设备。当应用程序跨平台执行时,第一个会遇到的问题挑战就是:数据储存模块无法跨平台。

为了解决数据储存模块无法跨平台的问题,开发人员可以在架构设计的层级,套用IoC模式来切割应用程序与数据储存模块的之间相依性。套用IoC模式之后,应用程序就只相依于自己定义的数据存取接口,不再相依于特定平台的数据存取模块。接着只要在应用程序启动时,注入依照平台特性所实作的数据存取接口,就可以建立动态更换数据储存模块的功能,进而提供应用程序跨平台执行的能力。

以一个计算BMI数值的应用程序来说,需要将使用者输入的身高体重的储存起来,提供下次使用者查询使用。当开发人员依照解决方案建立应用程序后,应用程序执行时,会先依照执行平台建立储存设备相关类别来提供应用程序使用。执行在移动平台会使用SQLite做为储存设备、执行在嵌入平台上则是会使用EEPROM做为储存设备,透过这样的方式让应用程序跨平台执行时依然可以正常的将资料存放到储存设备之中。

参考数据:

DI Framework跨平台解决方案

使用面向对象技术开发的应用程序,常常会搭配依赖注入模块用来在应用程序之外透过配置的方式,来动态更换应用程序所使用的功能模块。但因为目前CoreCLR还算是在发展中的技术,所以在这个时间点会很尴尬的发现,常见的MEF、Unity、Spring...等等依赖注入模块,还没有跟上这波的改变来更新版本,所以目前无法跨平台来使用。

为了解决依赖注入模块无法跨平台的问题,开发人员可以在架构设计的层级,选择套用Factory模式来取代依赖注入模块所提供的功能。套用Factory模式之后,应用程序就只相依于自己定义的功能模块工厂,不再相依于无法跨平台执行的依赖注入模块。虽然Factory模式只能生成加入项目参考的已知功能模块,但是一般的项目其实都还没有到达需要动态挂载功能模块的规模。所以透过Factory模式来生成注入对象,已经能够满足大部分项目的需求,并且提供应用程序跨平台执行的能力。

以一个加密User密码的应用程序来说,需要将用户输入的密码加密后传输到远程验证。当开发人员依照解决方案建立应用程序后,应用程序不需要引用外部的依赖注入模块,而只需要使用内建的加密模块工厂,生成系统所使用的加密规则模块,就可以让应用程序正常的提供软件功能。

参考数据:

UI Framework跨平台解决方案

每个平台所使用的用户界面框架不尽相同:在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跨平台解决方案

一个应用程序的开发,Log是一个不可或缺的功能。不管是做问题的追查、或是状态的分析,有了Log的辅助,让开发人员再发生问题的时候有迹可循。而这些提供Log功能的讯息纪录模块,开发人员可以选用.NET内建的EventLog、或者是第三方的Log4net...等等来使用。但是同样因为目前CoreCLR还算是在发展中的技术,所以上述这些常见的讯息纪录模块,还没有跟上这波的改变来更新版本,所以目前无法跨平台来使用。

为了解决讯息纪录模块无法跨平台的问题,开发人员可以在架构设计的层级,套用IoC模式来切割应用程序与讯息纪录模块的之间相依性,让应用程序只相依于自己定义的讯息纪录接口,并且为这个讯息纪录接口套用Service Locator模式来建立全局通用的对象参考。接着只要在应用程序启动时,生成依照平台特性所实作的讯息纪录接口,并且注入到全局通用的对象参考中,就可以完成动态更换讯息纪录模块的功能,进而提供应用程序跨平台纪录Log的能力。

参考数据:

放眼未来

Microsoft HoloLens

讨论了几个应用程序跨平台执行时,常会遇到的问题挑战、以及对应的解决方案后,相信开发人员对于如何开发跨平台应用程序有个一定程度的了解。接着,请大家再看看上面这段影片,影片内容是微软预计要推出的产品:Microsoft HoloLens。在观看的过程中,同样请大家以「软件开发人员」的角度来思考,想想软件开发人员在其中能扮演甚么样的角色。

第一次看这段影片的时候,微软这个主打3D扩增实境的产品:Microsoft HoloLens,马上深深震撼了我的心。透过3D显示、加上扩增实境的功能组合,让现实与虚拟的界线变得模糊,开发人员完全能够在扩增实境中虚拟出各种输入输出设备,来提供使用者使用。这无形中,就打破了现今硬件输入输出方式固定、开发成本过高的限制,让软件的各种概念、发想不再被硬件所局限,只要你想得出来就能够实现。虽然我们还没有使用过Microsoft HoloLens的实际成品,但是想象这个技术成熟的那一天,低头问问自己:「当硬件不再成为捆绑,软件你敢飞得多远」,相信每个人都能看到一个不同的世界。

最后,期许大家能够打破心的限制,设计出更多推动人类进步的软件。谢谢。

[Architecture Design] 跨平台架构设计的更多相关文章

  1. [Architecture Design] 3-Layer基础架构

    [Architecture Design] 3-Layer基础架构 三层式体系结构 只要是软件从业人员,不管是不是本科系出身的,相信对于三层式体系结构一定都不陌生.在三层式体系结构中,将软件开发所产出 ...

  2. [开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计

    [DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 为什么要造轮子 同学们可以去各大招聘网站查看一下爬虫工程师的要求,大多是招JA ...

  3. [翻译][架构设计]The Clean Architecture

    原文地址:The Clean Architecture The Clean Architecture Over the last several years we've seen a whole ra ...

  4. [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计

    [DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 为什么要造轮子 同学们可以去各大招聘网站查看一下爬虫工程师 ...

  5. NVIDIA Turing Architecture架构设计(下)

    NVIDIA Turing Architecture架构设计(下) GDDR6 内存子系统 随着显示分辨率不断提高,着色器功能和渲染技术变得更加复杂,内存带宽和大小在 GPU 性能中扮演着更大的角色. ...

  6. NVIDIA Turing Architecture架构设计(上)

    NVIDIA Turing Architecture架构设计(上) 在游戏市场持续增长和对更好的 3D 图形的永不满足的需求的推动下, NVIDIA 已经将 GPU 发展成为许多计算密集型应用的世界领 ...

  7. [Architecture Design] 累进式Domain Layer

    [Architecture Design] 累进式Domain Layer 前言 本篇的内容大幅度的简化了分析设计.面向对象等等相关知识,用以传达累进式Domain Layer的核心概念.实际开发软件 ...

  8. [Architecture Design] CLK Architecture

    CLK.Prototype.Architecture 最近找数据,看到了博客园在不久之前,办了一个架构分享的活动:.Net项目分层与文件夹结构大全.看完之后觉得获益良多,接着也忍不住手痒,开始整理属于 ...

  9. .net架构设计读书笔记--第二章 设计体系结构

    第五节 探索领域架构 一.领域驱动设计的价值与意义 最初在java中使用,.net要晚些才引入.领域驱动设计出现之初的争议.一个向导,少走弯路   1. 我们真的需要DDD吗? DDD并不适用于每个软 ...

随机推荐

  1. WPF国际化(多语言)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...

  2. Eclipse中如何修改SVN的地址

    在SVN服务端的IP更改后,客户端SVN的连接地址可以在Eclipse中进行修改,方法如下: 首先:在Eclipse中选择Windows-> Show View->others 就会出现[ ...

  3. Java分布式应用技术架构介绍

    分布式架构的演进 系统架构演化历程-初始阶段架构

  4. Jquery实现ready()的源码

    function bindReady(){ if ( readyBound ) return; readyBound = true; // Mozilla, Opera and webkit nigh ...

  5. Form personization(Form 个性化)报无权限

    总部的同事利用form personization对工单的一些Form做了个性化,发现可能设的有问题,造成用户无法关工单.想要看一下她是怎么设的,可报没权限.经过研究发现,把个人Profile 的 U ...

  6. Linux高级编程--09.线程互斥与同步

    多个线程同时访问共享数据时可能会冲突,比如两个线程都要把某个全局变量增加1,这个操作在某平台需要三条指令完成: 从内存读变量值到寄存器 寄存器的值加1 将寄存器的值写回内存 假设两个线程在多处理器平台 ...

  7. C#中,接口不能被实例化,但存在特例

    看一个例子: interface IFoo { string Message { get; } } 则, IFoo obj = new IFoo("abd"); 将会报错:接口不能 ...

  8. 斜堆(二)之 C++的实现

    概要 上一章介绍了斜堆的基本概念,并通过C语言实现了斜堆.本章是斜堆的C++实现. 目录1. 斜堆的介绍2. 斜堆的基本操作3. 斜堆的C++实现(完整源码)4. 斜堆的C++测试程序 转载请注明出处 ...

  9. 二、中间件(middleware)

    1.      中间件(middleware) Django中的中间件主要实现一些附加功能,在request被用户handler处理前,以及用户handler处理后生存的response进行处理.因此 ...

  10. PowerDesigner的安装和数据库创建(转载)

    此文描述详细,特此转载,仅复制了大部分内容,可参考原文CodeSmith和PowerDesigner的安装和数据库创建(原创) 请大家不要用于商业用途哈,要支持正版,大家都是做软件的,知道开发一套软件 ...