Open yuhanle opened 4 years ago
首先我觉得”组件”在这里不太合适,因为按我理解组件是指比较小的功能块,这些组件不需要多少组件间通信,没什么依赖,也就不需要做什么其他处理,面向对象就能搞定。 而这里提到的是较大粒度的业务功能,我们习惯称为”模块”。为了方便表述,下面模块和组件代表同一个意思,都是指较大粒度的业务模块。
首先我觉得”组件”在这里不太合适,因为按我理解组件是指比较小的功能块,这些组件不需要多少组件间通信,没什么依赖,也就不需要做什么其他处理,面向对象就能搞定。
而这里提到的是较大粒度的业务功能,我们习惯称为”模块”。为了方便表述,下面模块和组件代表同一个意思,都是指较大粒度的业务模块。
去年对于流利说的一次业务模块化重构,在业务开发上提高了团队协作效率,模块间解耦以及模块重用。但仍存在较多问题,比如:
业务模块的问题:
业务导航的问题:
决定了要开始组件化之路后,就需要思考我们的目标了。一个组件化方案需要达到怎样的效果呢?我在这里给出 8个理想情况下的指标:
需要管理导航的导航栈,在页面切换过程中,像一只监督者
参考:https://github.com/RxSwiftCommunity/RxFlow
其他路由
提高代码的可维护性、模块重用
解耦的过程就是职责分离、依赖管理(依赖声明和注入)、模块通信三大部分
依赖,就是模块中用到的外部数据和外部模块
根据依赖关系,接口可以分为required protocol和provided protocol。模块本身提供的接口是provided protocol,模块的调用者需要使用的接口是required protocol。
required protocol
provided protocol
required protocol是provided protocol的子集,调用者只需要声明自己用到的那些接口,不必引入整个provided protocol,这样可以让模块间的耦合进一步减少。
在 UML 的 组件图中,就很明确地表现出了这两者的概念。下图中的半圆就是Required Interface,框外的圆圈就是Provided Interface:
Required Interface
Provided Interface
Input 和 Output,按照约定实现 Provider 和 Requirement 功能
模块的对外接口可以分为 input 和 output。两者的区别主要是控制流的主动权归属不同。
Input 是由外部主动调用的接口,控制流的发起者在外部,例如外部调用 view 的 UI 修改接口。
Output 是模块内部主动调用外部实现的接口,控制流的发起者在内部,需要外部实现 output 所要求的方法。例如输出 UI 事件、事件回调、获取外部的 dataSource。
iOS 中常用的 delegate 模式,也是一种 output。
Venom 的设计主要为了实现自动注册,其中实现了一个 py 脚本,通过反射找到各业务组件提供的模块信息,来初始化组件并通过 Rainbow 注册。
预期通过一些设计模式的结合,各业务提供业务组件包,静态库或者动态库,以及组件信息,集成到壳工程里。
各业务模块独立开发、编译,需要一个 Demo 提供基础能力,类似目前 LLSAppEngine 模块,各业务基于此做一些需求开发。
我们可以看到基于接口管理模块的优势:
去年对于流利说的一次业务模块化重构,在业务开发上提高了团队协作效率,模块间解耦以及模块重用。但仍存在较多问题,比如:
业务模块的问题:
业务导航的问题:
组件化方案的 8条指标
决定了要开始组件化之路后,就需要思考我们的目标了。一个组件化方案需要达到怎样的效果呢?我在这里给出 8个理想情况下的指标:
如何解决
需要管理导航的导航栈,在页面切换过程中,像一只监督者
参考:https://github.com/RxSwiftCommunity/RxFlow
其他路由
模块解耦
提高代码的可维护性、模块重用
解耦的过程就是职责分离、依赖管理(依赖声明和注入)、模块通信三大部分
依赖管理
依赖,就是模块中用到的外部数据和外部模块
模块适配器
根据依赖关系,接口可以分为
required protocol
和provided protocol
。模块本身提供的接口是provided protocol
,模块的调用者需要使用的接口是required protocol
。required protocol
是provided protocol
的子集,调用者只需要声明自己用到的那些接口,不必引入整个provided protocol
,这样可以让模块间的耦合进一步减少。在 UML 的 组件图中,就很明确地表现出了这两者的概念。下图中的半圆就是
Required Interface
,框外的圆圈就是Provided Interface
:模块间通信
Input 和 Output,按照约定实现 Provider 和 Requirement 功能
模块的对外接口可以分为 input 和 output。两者的区别主要是控制流的主动权归属不同。
Input 是由外部主动调用的接口,控制流的发起者在外部,例如外部调用 view 的 UI 修改接口。
Output 是模块内部主动调用外部实现的接口,控制流的发起者在内部,需要外部实现 output 所要求的方法。例如输出 UI 事件、事件回调、获取外部的 dataSource。
iOS 中常用的 delegate 模式,也是一种 output。
自动注册
Venom 的设计主要为了实现自动注册,其中实现了一个 py 脚本,通过反射找到各业务组件提供的模块信息,来初始化组件并通过 Rainbow 注册。
预期通过一些设计模式的结合,各业务提供业务组件包,静态库或者动态库,以及组件信息,集成到壳工程里。
基线
各业务模块独立开发、编译,需要一个 Demo 提供基础能力,类似目前 LLSAppEngine 模块,各业务基于此做一些需求开发。
基于接口进行解耦的优势
我们可以看到基于接口管理模块的优势: