前置知识
- 已入门 Android
- 了解过一些设计原则
- 有 Android 项目经历
前言
在 Android 需要哪些架构手段一文中,我们讲述了一些我们需要了解学习的架构手段,我们已经学习到了一些常用的手段。那么对于一个项目、一个软件产品来说,我们的架构是如何跟随软件的生命周期来演进的呢?
本文将带大家了解一下,一个架构是如何跟随软件的生命周期来演进的。
一个架构如何基本成型的
当业务处于试点孕育阶段的时候,假如我们的功能很简单,只需要一个滑动的且可点击的列表。那么我们事实上并不需要多么复杂的架构,只需要一个单体的架构即可。何为单体架构呢?就是东西都塞一块,无需做模块分离。
当过了试验阶段的孕育期,我们的产品功能开始变多了,我们开始需要加入账号体系,需要支持图文混排,需要对咨询内容可以点赞、收藏,需要引入多板块的内容,开始往咨询浏览产品的方向发展。这时我们便是进入了婴儿期。
这个时候,我们不能再用单体架构了,我们需要开始使用分层的思想,将界面交互、业务逻辑和数据存储分离开来,让他们各自行驶自己的职责。同时,众多的业务需要多次使用网络和利用多线程,我们就需要封装抽离出网络模块和多线程处理功能。这时候,我们需要用到的就是分离架构了,上文中我们讲到的 MVX(MVC、MVP、MVVM) 就属于典型的分离结构。有兴趣的同学可以查看 带你封装MVP架构(上) 一文。
而当使用场景变得更多的时候,例如出现要加入视频流业务、加入课程业务的需求,那么我们需要将不同的业务场景拆离出来,使其成为独立的架构体系,每个架构体系之间再进行通信使其连接成一个 APP。这个阶段其实是处于学步期了,我们需要把各个业务模块化或者组件化,拆分出来成为独立的业务。而这里的模块化或者组件化自然就不是只针对业务的,还有很多中间层,中台之类的代码需要抽离出来,所以我们需要做好一套分层的架构,才能更好的降低耦合,实现业务。
这里简单给大家讲一下何为分层架构:分层架构是一套运用很广泛的架构模式,其最基础、最经典的设计包括如下几层:
- 展示层:接收输入,呈现界面
- 业务层:处理业务数据,进行数据流转
- 持久层:连接下层数据,向上提供数据的增删查改
- 数据层:存储数据
分层之后可以将各层之间隔离,每层之间只关注和实现自身的的需求即可,这样子可以很好的让有各自擅长点的人员分配去他们擅长的层级,且一般不会有层级的耦合。所以其优点是:结构清晰、利与管控,同时也方便人员分工。
分层架构由于结构分层明显,是很容易向里面不断加入层级的,加入层级又往往能解决出现的问题。这也就导致了会出现很多中间层级,同时很多时候加入层级就是因为我们原本的分层规定很严格,所以需要加入新的层级解决问题。由此,我们知道了其缺点是:层级管控严格造成灵活性低,从而使得会不断出现很多中间层,让架构层级很多。
我们了解了分层架构的思想,那么在 Android 中是如何体现的呢,下面我将引用万表商城的分层图给大家展示以下一般在 Android 中的分层架构是怎么样的。
我们可以看到前三层基本是一致的,但是在 Android 中一般没有数据层;数据层一般由 Android 内部提供,或者是继承在最底层的第三方库中了。
当我们的项目发展到分层的阶段,我们的项目架构其实已经基本成型了,再往后的阶段就是对项目架构的优化了。
架构的优化演进
事件驱动架构
在我们的架构分了层级之后,各个业务和模块之间,可以抽离出一些公共的部分为其他业务或者功能提供服务。这时候我们的项目等于步入了青年期,需要使用到服务化的架构。例如抽离出视频播放能力,流媒体能力成为一个服务,将其提供给众多的调用方。在设计模式中所讲的 IOC
:控制反转模型,它就类似于服务化架构。其中调用方不直接依赖被调用方,而是依赖于抽象,这也符合依赖倒置的思想。
Android 中,在上文中提到的服务管理,也是一个服务化的架构,对外只提供服务接口、隐藏具体实现,可以让调用者和提供者更加解耦。
而服务化架构的一种实现,就是事件驱动模型
在上述的服务化架构中,调用方和被调用方是基于抽象来调用的。那么这个抽象的实现形式怎么样才是最好的呢?这里给大家介绍事件驱动模型,用这个模型架构来解决服务化的抽象调用问题。
在事件驱动架构中,主要包括 Event
、Event Processor
和 Event Channel
这三部分。其主要作用就是请求服务方和服务提供方之间,可以 无痛沟通。其思想是基于订阅者模式和责任链模式。
- Event:事件。请求服务方请求服务的时候,会发出一个事件。这个事件具象到 Android 中就是某种点击事件或者某种事件变化。
- Event Processor:事件处理器。事件的消费者或者订阅者,会接收到事件,可以选择自行消费或者交由其他消费者消费掉。
- Event Channel:事件队列。类似于菜市场,所有的事件都交由这个队列售卖,对应的订阅者获取到它来进行消费。
我们使用过的 EventBus
或者 RXjava
就是类似这种的模型。其优点是适用广泛,可以拓展出很多的变种,且其支持消息的异步处理;而缺点则是消息过多之后很容易膨胀,且处理事件的链路的不明晰,使得我们的理解成本会很高。
下面的一张图片,是一个事件驱动架构的实例,可以很好的展示其各级分发和调用的特点。
我们可以看到,下面的事件并不是直接就被订阅消费的了,而是在订阅之后又会再次派发,直到出现了可以消费该事件的处理器。
而下面不同处理器之间的互通,使用的通信机制可以是:Binder、Handler 或者是 Broadcast 等,这些都是可以进行跨进程通信的。
微内核架构
在我们的业务愈发扩大的时候,我们的产品进入了壮年期,出现了很多非刚需的业务。例如我们的一些灰度测试、一些实现组的模型,或者一些其他想要动态化发布的业务,我们不需要它一开始在安装的时候就出现,而是在使用过程中在动态安装下来。需要实现这种功能的时候,我们应该怎么办呢?这个时候,我们应该使用的是宿主-插件架构,这在 Android 中就是我们经常听的插件化。使用插件化,动态下发 APK,实现灵活可插拔的功能。
而宿主-插件架构的一个实现,就是 微内核架构 ,将插件注册到内核,由内核加载调度。下图中的右侧就是微内核的示意图。
- Core System:宿主容器。不含盖业务逻辑,它是提供给不同的业务插件运行在其中的一个运行环境。
- Plug-in Component:插件。这是具体的业务实现,通过挂载到宿主容器中运行。
在 Android 中由于要实现四大组件,其方案便是:要在宿主容器中预埋四大组件(提供四大组件的桩函数),在插件中调用这些桩能力。这样子就可以在插件中实现四大组件了。
微内核架构的优缺点如下:
优点:
- 高拓展性,可做到随意加载业务
- 插件隔离化,其实和组件化,模块化一样具有解耦能力,但是它是天然解耦,无法被随意调用的,且其多了动态下发的能力
缺点:
- 对宿主要求高,且其不易拓展,宿主是运行环境,需要时较为固定的
- 插件的注册和通信机制较为复杂,需要宿主做通信派发
微服务架构
当业务和团队逐渐稳定的时候,我们的产品进入了稳定期,这个是时候由于前期快速开发、业务快速增长,会出现很多之前留下来的问题,包括冗余的业务代码、有限制改动的地方等等。这个阶段我们就需要去解决这些问题了,需要使用到的手段是 领域驱动架构。
所谓邻域驱动,是以领域专家和问题域为驱动,在特定的领域(问题域)去解决相对小的问题。其中,领域专家会使用特定的领域语言,可能是某种约定的标记语言或者特定文本。例如小程序是某个特定的问题域,由小程序的专家去解决和将其隔离开来。我们就只需要请求调起小程序,由小程序闭环去使用和解决其对应的问题。
领域驱动架构中使用的实例是:微服务架构
这里的微服务和后端所说的微服务是一样道理的,但是在这里我们所解决的问题并非和服务端要实现的负载均衡一模一样。这里的微服务还能解决一些异构问题,串联不同平台开发的服务,使得其合并到一起使用。
- Client Requests:服务发起方。以某种方式发送请求。例如点击跳转出小程序。
- Broker:服务调度。将请求放置于对应的微服务节点上面去处理
- Service Component:微服务。是高度内聚的模块,对外暴露出接口。在服务被使用之前,该服务需要被注册到服务中心中。
这里的微服务架构和 IOC 不同的地方是,IOC 是为同构服务,微服务可以服务于异构模型。所谓异构,就是使用不同语言,运行于不同平台。
本文到此就结束了,文章从产品的雏形期讲述到产品的稳定期,希望这个过程能让你更加了解一个产品对应的架构演化过程。