架构是系统的顶层结构。
架构设计的主要目的是为了解决软件系统复杂度带来的问题。
架构设计需要遵循三个主要原则:合适原则、简单原则、演化原则。
架构设计首先要掌握业界已经成熟的各种架构模式,然后再进行优化、调整、创新。
早期的应用程序(App)和许多尝试性业务采用了一种被称为“包壳架构”的设计。这个架构的核心理念是在Web业务的基础上包装一个App的壳,业务逻辑依然通过Web实现,而App的壳主要完成安装的功能。表面上看,用户像是在使用App,但实际上这与使用浏览器访问PC网站区别不大。
在大约2010年前后,移动互联网虽然发展迅速,但依然受到用户设备性能和移动网络速度的限制,PC互联网仍是主流。移动互联网作为一种新兴事物,未来的发展前景和趋势并不明朗。许多企业,包括淘宝,直到2013年才决定全面转向移动互联网。当时的业务重心仍然在PC互联网,移动互联网更多是处于尝试阶段。
由于移动互联网处于尝试阶段,企业需要快速低成本地验证市场需求和用户反馈。尽管当时Android和iOS已经具备开发原生App的功能,但开发成本较高。因此,Web App的包壳架构成为首选。其主要优势在于:
快速开发:利用现有的Web技术,可以迅速地将PC网站的功能移植到移动端,而无需重新开发复杂的原生应用。
低成本:避免了高昂的原生应用开发和维护成本,只需开发一个Web版本,并通过一个简单的壳包装成App。
在业务初期,采用简单且合适的架构是关键。包壳架构正好符合这个原则:
合适原则:在不确定未来需求和趋势的情况下,采用能够快速响应市场变化的架构是明智的选择。
简单原则:避免复杂的原生开发,选择一种简单的方式实现核心功能,降低开发和维护的复杂度。
尽管Web App解决了“快速开发”和“低成本”这两个复杂度问题,但随着业务的发展,Web App的劣势逐渐显现,并成为主要的复杂度问题,主要体现在以下几个方面:
移动设备的发展速度远远超过Web技术的发展速度,这导致Web App的用户体验与原生App的体验差距越来越大。
移动互联网迅猛发展,趋势越来越明显,App承载的业务逻辑也越来越复杂,进一步加剧了Web App在体验上的不足。
移动设备在用户体验方面有很多优化和改进,只有原生App能够充分利用这些技术优势,而Web App无法做到这一点。
因此,随着业务发展和技术进步,移动开发的复杂度重心从“快速开发”和“低成本”转向了“用户体验”。为了保证良好的用户体验,采用原生App架构是最合适的选择。这种架构设计遵循了“演化原则”。
原生App解决了用户体验的问题,大约在2013年前后开始迅速发展。当时,Android和iOS工程师非常抢手,就像现在的人工智能工程师一样。许多从事后端开发的工程师在那时转行到App开发领域。
原生App很好地解决了用户体验的问题,但随着业务和技术的不断发展,移动互联网已经成为明确的大趋势。团队需要考虑的不再是是否转向移动互联网,而是如何在移动互联网环境中变得更具竞争力。因此,基于移动互联网特点的各种功能和体验方式不断被创造出来,竞争的焦点变成了谁能更快地抓住用户需求和痛点。
在这一阶段,移动开发的复杂度又回到了“快速开发”的问题。然而,原生App开发的一个显著痛点是由于Android、iOS和Windows Phone(当时的三个主流平台)的原生开发完全不兼容,同样的功能需要在三个平台上重复开发,每个平台还有一些差异,这导致开发速度自然提不起来。
为了再次解决“快速开发”的复杂度问题,大家自然又想到利用Web的方式。但Web的用户体验依然无法与原生App相比,如何解决这个问题呢?
虽然没有一种完美的解决方案,但可以根据不同的业务需求选取不同的实现方案。例如,对于体验要求高的业务可以采用原生App实现,而对于体验要求不高的业务可以采用Web方式实现。这种思路形成了Hybrid App架构的核心设计思想,主要遵循架构设计的“合适原则”。
Hybrid App结合了原生App和Web App的优点,通过在一个原生的容器中运行Web内容,实现了以下几点:
快速开发:利用Web技术,可以快速开发和部署,减少重复开发的工作量。
成本效益:减少了开发和维护多个平台的成本。
灵活性:可以根据业务需求在原生和Web之间灵活选择,实现最佳的用户体验和开发效率。
Hybrid App 能够较好的平衡“用户体验”和“快速开发”两个复杂度问题(注意是“平衡”,不是“同时解决”),但对于一些超级 App 来说,随着业务规模越来越大、业务越来越复杂,虽然在用户看来可能是一个 App,但事实上承载了几十上百个业务。
以手机淘宝为例,阿里确认“All in 无线”战略后,手机淘宝定位为阿里集团移动端的“航空母舰”,上面承载了非常多的子业务,下图是淘宝的首页第一屏,相关的子业务初步估计就有 10 个以上。

再以微信为例,作为腾讯在移动互联网的“航空母舰”,其业务也是非常的多,如下图,“发现”tab 页就有 7 个子业务。

在一个App中集中了众多业务,并且每个业务都在不断扩展,新业务也可能不断引入的情况下,可扩展性成了一个新的复杂度问题。每个业务由独立的团队负责开发,这进一步增加了复杂性。
可扩展性的基本思想就是“拆分”。但当这个思想应用到App和后端系统时,具体的做法显然不同。App和后端系统的本质区别在于,App是面向用户的,而后端系统不是。因此,不管怎么拆分,App对用户还是要呈现为一个整体,不可能将一个App拆分为几十个独立的App。而后端系统则不同,采用微服务架构后,可以拆分为几百上千个子服务,各个子服务之间独立运行,没有问题。
App的业务再怎么拆分,技术栈也是统一的,否则无法集成在一个App里。而后端系统则不受此限制,不同的微服务可以使用不同的技术栈来开发。
在这种业务背景下,组件化和容器化架构应运而生。其基本思想是将超级App拆分为众多组件,这些组件遵循预先制定好的规范,独立开发、独立测试、独立上线。如果某个组件依赖其他组件,组件之间通过消息系统进行通信。通过这种方式实现组件隔离,避免团队之间的互相依赖和影响,从而提升开发效率和系统的可扩展性。这种架构设计遵循了“演化原则”,通常在业务复杂度发展到一定规模后才适用。因此,大厂应用这种架构的比较多,而中小公司的App业务相对简单,并不一定需要采用组件化和容器化架构。
组件化和容器化并没有非常严格的定义,我理解两者在规范、拆分、团队协作方面是相同的,区别在于发布方式:
组件化:采用静态发布,即所有组件独立开发测试,然后跟随App的某个版本统一上线。
容器化:采用动态发布,即容器可以动态加载组件,组件准备好后直接发布,容器会动态更新组件,无需等待某个版本上线。
除了Web App之外,前面提到的其他App架构都面临一个共同的问题:跨平台开发需要重复工作。相同的功能和业务需要在Android和iOS平台上分别开发,这会导致人力投入的增加,这实际上违背了架构设计中的“简单原则”。从企业的角度来看,当然希望能够减少人力投入成本(虽然从程序员的角度来说,这并不是理想的情况)。因此,近年来出现了各种跨平台方案,比较知名的包括Facebook的React Native、阿里的Weex和Google的Flutter。
尽管有许多公司尝试使用这些跨平台方案,但目前它们还不够成熟,而且在用户体验方面与原生App仍有一定差距。例如,Airbnb就曾宣布放弃使用React Native,回归使用原生技术。
原文作者:二进制跳动;如有侵权,请联系管理员删除。