yuhanle / blogbag

我会不断更新这个仓库中的文章
https://latehorse.github.io/
14 stars 1 forks source link

业务模块化路由探索 #11

Open yuhanle opened 4 years ago

yuhanle commented 4 years ago

首先我觉得”组件”在这里不太合适,因为按我理解组件是指比较小的功能块,这些组件不需要多少组件间通信,没什么依赖,也就不需要做什么其他处理,面向对象就能搞定。

而这里提到的是较大粒度的业务功能,我们习惯称为”模块”。为了方便表述,下面模块和组件代表同一个意思,都是指较大粒度的业务模块。

去年对于流利说的一次业务模块化重构,在业务开发上提高了团队协作效率,模块间解耦以及模块重用。但仍存在较多问题,比如:

业务模块的问题:

业务导航的问题:

组件化方案的 8条指标

决定了要开始组件化之路后,就需要思考我们的目标了。一个组件化方案需要达到怎样的效果呢?我在这里给出 8个理想情况下的指标:

  1. 模块间没有直接耦合,一个模块内部的修改不会影响到另一个模块
  2. 模块可以被单独编译
  3. 模块间能够清晰地进行数据传递
  4. 模块可以随时被另一个提供了相同功能的模块替换
  5. 模块的对外接口容易查找和维护
  6. 当模块的接口改变时,使用此模块的外部代码能够被高效地重构
  7. 尽量用最少的修改和代码,让现有的项目实现模块化
  8. 支持 Objective-C 和 Swift,以及混编

如何解决

需要管理导航的导航栈,在页面切换过程中,像一只监督者

参考:https://github.com/RxSwiftCommunity/RxFlow

其他路由

模块解耦

提高代码的可维护性、模块重用

image

解耦的过程就是职责分离、依赖管理(依赖声明和注入)、模块通信三大部分

依赖管理

依赖,就是模块中用到的外部数据和外部模块

image

模块适配器

根据依赖关系,接口可以分为required protocolprovided protocol。模块本身提供的接口是provided protocol,模块的调用者需要使用的接口是required protocol

required protocolprovided protocol的子集,调用者只需要声明自己用到的那些接口,不必引入整个provided protocol,这样可以让模块间的耦合进一步减少。

在 UML 的 组件图中,就很明确地表现出了这两者的概念。下图中的半圆就是Required Interface,框外的圆圈就是Provided Interface

image

模块间通信

Input 和 Output,按照约定实现 Provider 和 Requirement 功能

模块的对外接口可以分为 input 和 output。两者的区别主要是控制流的主动权归属不同。

Input 是由外部主动调用的接口,控制流的发起者在外部,例如外部调用 view 的 UI 修改接口。

Output 是模块内部主动调用外部实现的接口,控制流的发起者在内部,需要外部实现 output 所要求的方法。例如输出 UI 事件、事件回调、获取外部的 dataSource。

iOS 中常用的 delegate 模式,也是一种 output。

自动注册

Venom 的设计主要为了实现自动注册,其中实现了一个 py 脚本,通过反射找到各业务组件提供的模块信息,来初始化组件并通过 Rainbow 注册。

image

预期通过一些设计模式的结合,各业务提供业务组件包,静态库或者动态库,以及组件信息,集成到壳工程里。

基线

各业务模块独立开发、编译,需要一个 Demo 提供基础能力,类似目前 LLSAppEngine 模块,各业务基于此做一些需求开发。

基于接口进行解耦的优势

我们可以看到基于接口管理模块的优势: