AndroidDocker一致架构设计(2)

-- 包装<跨集装箱>的通信协议(Protocol)

 

By 高焕堂 (台灣Docker論壇 主席)

2015/02/27  misoo.tw@qq.com

 

高煥堂的相關文章:

  A01、从「集装箱」思考Docker风潮:Docker潮流下的赢家策略

  A02、Docker:从容<器>到集装箱设计之<道>

  B01、Android和Docker的一致架构设计(1):追求今天决策的未来性

  B03、Android和Docker的一致架构设计(3):建立企业主的<核心集装箱> 

  B04、Android和Docker的一致架构设计(4):<分合自如>的设计模式

 

前言

     Android是基于Linux操作系统而开发的,也是基于Linux进程(Process)的沙盒隔离策略的。同样的,Docker集装箱也是基于Linux进程的沙盒隔离机制的。因此,我们从「集装箱」来思考Android和Docker的<整合>架构设计时,可以发现两端(Android终端与Docker云端)的架构思维里,蕴含了一致性。随着Docker集装箱潮流的力量,云平台的集装箱思维将普及到其他操作系统(如Windows、iOS等)。逐渐地,集装箱设计思维,很可能将成为互联网&大数据时代里的主流软件架构设计思维。

  集装箱设计思维,就意味着,大家不仅仅去学会使用Docker集装箱而已,人人都将设计各式各样比Docker集装箱大的、或比它小的集装箱,就像女士们的LV皮包里还有形形色色、出奇斗艳的化妆品盒子等。

      

也像西方餐桌上,也有形形色色的、百花齐放的酒杯、餐盘等大大小小的<集装箱>。 

   

       更重要的是,这些<集装箱>的设计、制造、开发、测试、营销、品牌等,逐渐成为一个新兴产业。甚至出现像LV一样的品牌,集装箱本身价值可能比内容(如化妆品)还要高好几倍呢! 

   于是,本文就来展示一下如何发挥<集装箱思维>,亲自设计一些小集装箱(观摩Android架构设计)来包装Docker的跨集装箱通信协议。一方面提升Docker集装箱内App的跨(Docker)平台能力;另一方面也促进Android终端与Docker云端的一致性架构设计,创造和谐的整体。 

 

1Docker集装箱的通信协议是善变的

     试想,有两个Docker集装箱:一个是<智能家庭(F)>服务的集装箱,另一个是<交通车联网(V)>服务的集装箱,而且两者之间通过网络通信机制来互通。

     

  此时一般人会先去寻找标准的通信机制(如HTTP或REST等协议),然后才开发F和V服务。这就是预测未来(通信途径)了,会让软件架构失去未来性,所以不是有效的软件架构设计思维。因为两个集装箱里的App必须对通信协议进行解析,其代码会写在集装箱的App软件里。

     

  然而,大家都知道,底层通信协议是善变的,会导致App软件里的解析代码的改变,常常引起牵一发动全身的涟漪效应,大幅提高App软件的维护成本。

     

   那么,其解决之道是甚么呢?很简单,只要设计个东西来包容通信协议的未来变化,就行了。这个东西是Docker集装箱里的小容器,用来包装和隔离善变的底层通信协议,消除牵一发动全身的涟漪效应。 

 

2观摩Android框架设计

2.1 基本架构

   在开发Android应用程序时,大家最孰悉的两个模块就是:Activity和Service。

     

  如果Activity或Service模块的开发者直接使用底层通信协议的话,就会将协议的解析代码写在模块内。

     

  一样的,大家都知道,底层通信协议是善变的,会导致模块(如myService)软件里的解析代码的改变,常常引起牵一发动全身的涟漪效应,大幅提高软件模块的维护成本。

     

    其解决之道就是:设计个东西来包容通信协议的未来变化,就行了。于是,Android设计了Binder基类(Superclass)和IBinder接口来实践封装(Encapsulate)底层通信协议的任务,其架构如下图:

     

 于是,通信协议的随时改变,将不会导致myService模块里的代码变动了。 

2.2  Android的具体架构

     Android的具体架构如下图:

     

  当myActivity跨进程启动了myService时,这myService调用了myBinder()构造函数去诞生对象。然后,将IBinder接口回传给myActivity模块。于是,myActivity就能调用IBinder接口的transact函数,进而调用myBinder子类的onTransact()函数来发送信息给myService的线程,由该线程去播放mp3音乐。 

  

  待会儿,从下一小节的代码中,你可以看到IBinder接口和Binder基类确实将Android的跨进程通信(IPC)协议包装起来了。

2.3 Android的应用程序代码

  兹建立Android开发项目:

    

  此程序的执行画面如下:

      

  请你看看这Android App的源代码:

   ==> 源代码(Source Code)

    当您仔细观察上述Android应用程序代码,只看到应用层的IBinder接口的transact()函数和Binder基类的onTransact()抽象函数而已,底层通信协议已经不见了,实践了完美的封装任务。 

 

3一致的架构:应用于Docker集装箱

   刚才已经提到了,无论Docker采取何种底层通信协议,对App开发而言都是善变的。所以,当你想到两个Docker集装箱之间的通信时,就会联想到此通信协议的解析代码,也会随着协议的变动而变了。所以,不宜将通信协议解析代码直接写在App软件里。

 

 于是,可以从Android引用一致的架构设计理念。

 

   值得留意的是,在这图里,V集装箱里的基类和接口通常是由<强龙>角色的团队所定义与开发的。最典型的是,粉红色模块(就是基类和接口)是由第三方(即组合者)强龙团队所开发的。因此,从开发者(Developer)视角来看,这是由三种开发者互相<分工>的结果,如下图:

 

   反之,从维运者(Operator)视角来看,这是由两个Docker集装箱所<组合>而成的。

关于这个<强龙/地头蛇>分工模式,及其架构设计理念,如果您有兴趣,可以阅读我的书籍:《思考软件、创新设计:A段架构师的思考技术》(电子工业出版社)。

     

   此外,也可以观看我的线上视频课程,其中有一个视频课程(免费),名称是:“新一代架构师:掌握接口,才有话语权”。在这视频中,我详细地阐述了强龙的架构与接口设计思维。观看网頁:http://www.cnblogs.com/smartADT

 

4<小集装箱>的设计思维与演练

4.1 基本架构

  大家都知道,在船运集装箱里面,往往可看到还有各式各样的盒子,这些盒子也是集装箱(或称为容器)。如下(左)圖:

 

  再如,女士们的LV皮包里,也常有各式各样的化妆品包装盒,也都是小集装箱,如上(右)图。因此,我们除了使用Docker集装箱之外,还可以尽力发挥我们的创意和想象力,设计出各式各样的小集装箱。同样的,在软件系统开发上,也是如此。例如,在智慧城市领域里,<智慧家庭>与<交通车联网>两大业务领域的系统模块。

           

   前面已经提到了,许多人会先去寻找标准的通信机制(如HTTP或SOAP等协议),然后才去开发这两个模块。这让软件架构失去未来性,并不是好的软件架构。于是,开始想象去设计集装箱,用它来把善变的通信协议包装起来。这小集装箱的设计,是因人而异的,人人都可以发挥想象力去创造。例如,我擅用我提出的EIT造形来做为小集装箱,如下圖: 

   

   我们可以想象EIT造形就是<基类/子类>的结构,<E>是基类(Superclass),<T>是子类(Subclass),而<I>则实现为基类里的抽象函数(Abstract Function)。于是,架构师设计一个明确的架构,利用两个<E>的联合来包容通信协议内涵,如下图所示。

     

接着,拿来较大的Docker集装箱来把它们分别包装起来。

     

    于是,当通信协议有所改变时,并不会牵动<智 慧家庭>和<交通车联网>两个模块里的代码,实践了完美的包装。

 

4.2 集裝箱實踐范例:Socket接口来包容TCP/IP协议

   于此,将拿两个EIT造形当作集装箱,并利用两个<E&I>来包容未来TCP/IP通信协议的快速演变。包装起来之后,提供较高阶的软件Socket接口,让通信协议和硬件机制都可以弹性抽换,架构设计具有未来性。这个Socket软件接口和TCP/IP实体通信协议,如下图所示。

     

于是,两个EIT造形的角色,如下图所示。

    

   我们可以想象EIT造形就是“基类/子类”的结构,<E>是基类,<T>是子类,而<I>则实现为基类里的抽象函数(Abstract function)。于是,设计出两个<I>接口,如图下图所示。

    

     最后,请看EIT集裝箱提供Socket接口的范例代码。本范例代码摘自网页:

http://bbs.51cto.com/thread-1085282-1.html;于此,将之改为EIT造形架构。

  • 服务(Server)端的范例代码

   ==> 源代码(Source Code)

 

  • 客户(Client)端的范例代码

     ==> 源代码(Source Code)

 

5、結語

   虽然本文里,我常常用EIT造形来做为集装箱,但是集装箱只是一种概念或思维模式,只要能实现「序中有乱」的东西都可能是一个好用的集装箱。这里的<乱>是指复杂多变的意思。繁杂多变往往是一个事物的生命力的来源,是非常珍贵的,我们应该珍惜它、喜爱它。所以我们会想去拿个(集装箱)盒子来把它包装起来,而呈现出简单有序,在人们心中就会觉得它变得楚楚动人、挺可爱的。未来的变化和复杂性是本质性(Essential)的,也是生命力的泉源。人们也往往无法删除它。于是想办法提升人们管理复杂的能力。著名软件专家Fred Brooks(“人月神话”一书作者)在40年前就说道: 

   “软件的复杂性是本质性的,并非表象而已。”(The complexity of software is an essential property, not an accidental one.)

    于是,也必须想办法提升人们面对软件复杂性的能力。此时,集装箱的「序中有乱」特质,正好派上用场,赋予人们将复杂变成简单的能力。被尊称为“史上最伟大的平面设计师”的保罗·兰德(P. Rand)也说,我们会从最复杂的部分开始着手,最后的成品却具有<简单性>。这个减法过程本身是复杂的,然而一旦达到简单了,就能发挥杠杆作用,让人们能面对变化、掌握复杂。苹果公司的乔布斯(Jobs)也曾说到:

“简单比复杂更难,因为必须努力让你的想法变得清晰明了,让它变得简单。但终究是值得的,因为只要你获得了其<简单性>,就能搬动大山了。”(Simple can be harder than complex:you have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains.)

   Docker设计师运用其创意,设计出集装箱,让人们用来包容复杂性而得到简单性,然后再从简单组合出复杂。最后,让用户获得从简单中叫出复杂的满足感,实践好的用户体验。如果,众人也能像Docker设计师一样,擅用自己天赋的创意,设计出更多、更新颖的集装箱,人们的生活将更精彩、更完美了。 

 

高煥堂的相關文章: 

  A01、从「集装箱」思考Docker风潮:Docker潮流下的赢家策略 

    A02、Docker:从容<器>到集装箱设计之<道>

  B01、Android和Docker的一致架构设计(1):追求今天决策的未来性 

  B03、Android和Docker的一致架构设计(3):建立企业主的<核心集装箱>

  B04、Android和Docker的一致架构设计(4):<分合自如>的设计模式

 ~ End ~