组件化
考虑到公司目前的项目的业务越来越庞杂,模块也越来越多。模块之间 免不了要进行通信,相互调用。例如生意圈模块、聊天模块、商城模块、赠礼模块、商机模块、订单模块等等都需要调用用户模块个人主页。一般都是通过直接import导入相关的页面,虽然这样简单明了,但是却使得模块之间的耦合度越来越高,对于后期的业务扩展来说简直是灾难,而且目前也拆分出来司机端,之后也免不了两端会进行相互调用。所以最近研究组件化以应对之后业务发展。
由于目前项目的设计已经对业务层、网络层、持久层、展示层进行了分层和单向依赖,现在只需要处理业务层之间的耦合问题,以后以后其他端app调用问题。
模块耦合问题:
1、提取公共代码
对于模块之间都需要使用的工具类、或者BaseUI库可以提供到common库或者Tools里面
2、模块依赖
主要是基于Mediator模式和Target-Action模式,比如聊天模块点击用户头像跳转个人主页场景,此时可以将用户模块看成是一个Target,模块里面定义一个Action类暴露可供外界调用的接口,由Mediator中介者负责统一调度。
此处需要注意的是:
1、对外定义的接口参数不能使用Model,不然会增加其他模块对Model的耦合,对于其他模块而言只需要引用这个模块的Action类,具体Action类里面是如何跳转到该模块其他类或者该模块相应类名是什么外界不需要关心也不需要知道。
2、怎么做到远程app调度与本地调度,以及不同模块业务场景怎么做到用统一的mediator调度?对于远程的调度而言,远程应用通过openURL的方式,由iOS系统根据info.plist里的scheme配置找到可以响应URL的应用,应用通过AppDelegate接收到URL之后,调用CTMediator的openUrl:方法将接收到的URL信息传入。当然,CTMediator也可以用openUrl:options:的方式顺便把随之而来的option也接收。而本地调度当前模块可以通过performTarget:targetName action:actionName params:@{...}向Mediator发起跨组件调用,Mediator根据获得的target和action信息,通过objective-C的runtime转化生成target实例以及对应的action选择子,然后最终调用到目标业务提供的逻辑,完成需求。
3、当外界传入的参数不对时,Mediator中需要做相应的容错处理,比如debug模式下打印错误信息,Assert断言抛出异常,release模式跳转一个错误的页面等等手段。
4、调用方如何知道接收方所需的参数?使用category。mediator这个repo维护了若干个针对mediator的category,每一个对应一个target,每个category里的方法对应了这个target下所有可能的调用场景,这样调用者在包含mediator的时候,自动获得了所有可用的target-action,无论是调用还是参数传递,都非常方便。不同的模块使用相应的Mediator分类,因为不同模块本就是一个不同的分类,而且在category的方法中可以做到参数的验证,在架构中对于保证参数安全是很有必要的,category统一了所有的模块间调用入口,因此无论是在调试还是源码阅读上,都提供了极大的方便;由于category统一了所有的调用入口,使得在跨模块调用时,对于param的hardcode在整个App中的作用域仅存在于category中,在这种场景下的hardcode就已经变成和调用宏或者调用声明没有任何区别了,因此是可以接受的。
参考:
https://casatwy.com/iOS-Modulization.html