iOS应用架构谈 组件化方案:https://casatwy.com/iOS-Modulization.html
1.组件化有什么好处?
- 业务分层、解耦,使代码变得可维护;
- 有效的拆分、组织日益庞大的工程代码,使工程目录变得可维护;
- 便于各业务功能拆分、抽离,实现真正的功能复用;
- 业务隔离,跨团队开发代码控制和版本风险控制的实现;
- 模块化对代码的封装性、合理性都有一定的要求,提升开发同学的设计能力;
- 在维护好各级组件的情况下,随意组合满嘴不同产品需求;(只需要将之前的多个业务组件模块在新的主App中进行组装即可快速迭代出下一个全新App)
2.你是如何组件化解耦的?
(a)分层:
- 基础功能组件:按功能分库,不涉及产品业务需求,跟系统库类似,通过良好的接口供上层业务组件调用;不写入产品定制逻辑,通过扩展接口完成定制;
- 基础UI组件:各个业务模块依赖使用,但需要保持好定制和扩展的设计;
- 业务组件:业务功能间相互独立,相互间没有model共享的依赖;业务之间的页面调用只能通过UIBus进行跳转;业务之间的逻辑Action调用只能通过服务提供;
(b)中间件:target-action,url-block,protocl-class
3.为什么CTMediator方案优于Router方案?
CTMediator的优点:
-
(1)调用时,区分了本地应用调用和远程应用调用。本地应用调用为远程应用调用提供服务。
-
(2)组件仅通过Action暴露可调用接口,模块与模块之间的接口被固化在了Target-Action这一层,避免了实施组件化的改造过程中,对Business的侵入,同时也提高了组件化接口的可维护性。
-
(3)方便传递各种类型的参数。
Router的缺点:
-
(1)在组件化的实施过程中,注册URL并不是充分必要条件。组件是不需要向组件管理器注册URL的,注册了URL之后,会造成不必要的内存常驻。注册URL的目的其实是一个服务发现的过程,在iOS领域中,服务发现的方式是不需要通过主动注册的,使用runtime就可以了。另外,注册部分的代码的维护是一个相对麻烦的事情,每一次支持新调用时,都要去维护一次注册列表。如果有调用被弃用了,是经常会忘记删项目的。runtime由于不存在注册过程,那就也不会产生维护的操作,维护成本就降低了。 由于通过runtime做到了服务的自动发现,拓展调用接口的任务就仅在于各自的模块,任何一次新接口添加,新业务添加,都不必去主工程做操作,十分透明。
-
(2)在iOS领域里,一定是组件化的中间件为openURL提供服务,而不是openURL方式为组件化提供服务。如果在给App实施组件化方案的过程中是基于openURL的方案的话,有一个致命缺陷:非常规对象(不能被字符串化到URL中的对象,例如UIImage)无法参与本地组件间调度。 在本地调用中使用URL的方式其实是不必要的,如果业务工程师在本地间调度时需要给出URL,那么就不可避免要提供params,在调用时要提供哪些params是业务工程师很容易懵逼的地方。
-
(3)为了支持传递非常规参数,蘑菇街的方案采用了protocol,这个会侵入业务。由于业务中的某个对象需要被调用,因此必须要符合某个可被调用的protocol,然而这个protocol又不存在于当前业务领域,于是当前业务就不得不依赖public Protocol。这对于将来的业务迁移是有非常大的影响的。
4.基于CTMediator的组件化方案,有哪些核心组成?
(1)CTMediator中间件:集成就可以了;
(2)模块Target_%@:模块的实现以及提供对外的额方法,调用Action_methodName,需要传参数时,都统一以NSDictionary *的方式传入。
(3)CTMediator+%@类目扩展:类目里声明了模块业务的对外接口,参数明确,这样外部调用者可以 很容易理解如何调用接口。