浅谈客户端模块化
回忆
大学那会喜欢跟着老师在实验室折腾,感觉每天大脑中都有新知识鱼贯而入。
当我被告知要做一个最小单片机系统的时候,兴奋而又紧张!
最小单片机系统示意图:
从画 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 上面就更加不用说了。这只是我个人的一点看法,不喜勿喷。
扫码关注,你我就各多一个朋友~