浅谈客户端模块化

回忆

大学那会喜欢跟着老师在实验室折腾,感觉每天大脑中都有新知识鱼贯而入。

当我被告知要做一个最小单片机系统的时候,兴奋而又紧张!

最小单片机系统示意图:

从画 PCB 到制板、洗板,再到选择元器件,最后组装调试和写代码,我花费了两个多月的时间,当板子上面的跑马灯亮起来的那一刻,我激动的无法言语。

大家可以看到这个最小单片机系统上面有很多组件组成,有电阻、电容、电阻、二极管和卡槽等,当然还有最核心的组件就是单片机,当时用的是51单片机。

各个元器件就好比组件,功能单一,职责明显,组件之间遵循协议构成模块,最终组合成为(最小单片机)系统。

上面的回忆是为了引出今天的分享,分享的主要内容是客户端开发中常用的模块化组件化插件化以及热更新等技术辞藻,并没有涉及到具体的技术问题。

模块化和组件化

从程序设计的角度出发,无论是模块化还是组件化,都是指软件架构的范畴,是一种设计思想。两者并没有严格意义上面的区分,二者的目的一致,就是将工程结构化,达到可复用可伸缩的能力,最终提供工作效率。

在说模块化和组件化之前,先解释一下什么是高内聚低耦合。

高内聚:组件内尽可能独立完成自己的功能,坚持单一职责的原则 SRP,不依赖于其他组件的代码。

低耦合:模块与模块之间尽量不要互相引用,模块之间联系越复杂耦合度越高,修改的成本就越高。

组件更加强调可替换可复用的特性,职责和功能比较单一、独立,与其他组件之间没有耦合性。

模块更加强调组合特性,更加偏重于业务,比如一个社区项目,登录注册、论坛和个人中心都是模块,这些业务模块又是有很多个组件组合而成。

下图展示的是一个简易的论坛系统示例图,如下:

可以看出,各个组件可以单独使用到其他模块当中,各个模块之间相对独立,只要定义好模块之间的通信协议,就可以做到并行开发,各个模块甚至可以复用到其他系统之中。

通信机制

这里说的通信机制并不是指 HTTP 或 TCP 的通信方式,而是指组件与组件之间,模块和模块之间的交互方式。

正常情况下,写业务功能的代码,在不同组件之间需要相互调用,这样就需要 import 其他组件,无形之中就增加了组件之间的耦合度。

有开发经验的同学,可能会用到类似 java 的反射机制,或者一些动态语言的运行时机制如 Objective-C Runtime,对它们不进行 import,而是动态的解析代码,达到组件之间或者是类之间相互调用的目的。

现在提倡也是比较热门的技术是通过路由通信机制,来进行组件之间的通信。这里举一个实际使用场景。

用户安装了我们的 APP,运营同事在某个节日来临之际做一个促活跃的活动,期望用户点在打开推送通知的时候,打开 APP 后可以直接跳转到对应的活动详情页面。大致流程如下:

这是一个再常规不过的需求了,相信经历过产品开发的朋友都见过这种需求。

很显然,我们可以使用路由的通信机制来完成这个需求,开发的流程图大致如下:

这里关键的核心得益于 iOS 和 Android 平台的 scheme 机制,对于 scheme,通俗的讲就是一种可以跨进程或者进程内的通信协议,例如可以在 APP 中打开某个应用商店。

例如下面的 URL:

1
bbs://page/activity/activity_detail?id=8978&user_id=67890432

其中,bbs 就是 scheme,可以看到该 URL 完全可以被各自平台来解析。

iOS 和 Android 平台各有很多开源的路由方案,实现手法各有差异,但是思想是一样的,建议大家去了解和学习。

不过,现在你只要知道,路由的通信机制大大降低了组件之间的耦合性就够了。

插件化

插件这个词,大家应该很熟悉,例如 Chrome 浏览器中可以安装各种小工具,这些小工具就是插件,还有各种开发使用的 IDE 也支持插件安装,便于提高我们的工作效率。Chrome 和 IDE 被称之为宿主,插件寄生于他们。

支付宝和微信里面的小程序也可以看成是一个个插件,但是他们不能脱离支付宝和微信独立运行。

可以发现这些插件即使被卸载或者被删除,并不会让 Chrome 或者 IDE 受到影响,换句话说,插件让宿主锦上添花。

这种插件思想当然可以运用到 APP 中来,试想一下,如果某个 APP 在线上经过动态下载就具有了一个强大或者好用的功能,岂不美哉?!

插件化,将 APP 拆分成很多模块,这些模块包括一个宿主和多个插件,宿主提供插件的管理和通信协议及规范,每个模块都是一个的库或者功能包。

插件化是一种编程和解决问题的思想,没有统一的定义。在 Android 上面运用比较多,iOS 上面很少,并不是 iOS 没有这样的技术,主要是因为苹果审核等各方面的限制。在 iOS8 上的 App Extension 功能,也可以看做是插件化了。

在 Android 平台中,插件化已经不是很新鲜的技术了,VirtualAPK、Atlas、Replugin 等框架相继开源,插件化技术已经进入了比较成熟的阶段了。

插件化的编程思想和实现,在不同的平台有所差异,即使在同一个平台上面都会有不同的实现手段,建议选择一个开源方案去了解其原理,然后试着动手去实现一个,千里之行始于足下!

热更新

“不好了,昨天有很多用户反馈我们的 APP 出现闪退。“ 小王一大早的开始撕喊,坐在他旁边的开发大神们顿时微笑凝固,马上去后台看上报的崩溃日志,紧接着开始复现和解决问题,最终得出结论,需要重新提审 APP,并周知渠道部门做好更新准备。

试想一下,如果一个游戏几G的大小,你让用户为了你的一个小失误来整包更新游戏,用户和你估计都要疯了。

最近几年,随着业务发展的需求,热更新技术也是得到了突飞猛进的发展。类似于上面的场景,能在用户神不知鬼不觉的情况下使用热更新的技术解决崩溃的问题,岂不是两全其美。

Android 的热更新技术如火如荼的发展着,而苹果这边严厉禁止热更新,一旦检查到立即会责令你修改或者下架 APP。我们还是从技术的角度来看这个问题,学习和了解一下对应的技术总归没有错,这里 有 iOS 上面的热更新方案,另外 Android热修复方案比较 介绍了很多 Android 热更新的开源的方案,可以了解学习一下。

站在跨平台的角度,我个人比较推荐使用 Lua 实现热更新,Lua 不仅简单高效,而且可以很好的和 C/C++ 结合在一起,而 Android 上面通过 JNI 又能与 C/C++ 通信,iOS 上面就更加不用说了。这只是我个人的一点看法,不喜勿喷。


扫码关注,你我就各多一个朋友~

坚持原创技术分享!