昨天看了篇博客讨论iOS 组件化方案探索,很受启发,说一下我的几点看法。
起源
这次讨论起源于蘑菇街App的组件化方案,组件间的耦合比较乱,所有功能放到一个大项目里开发的效率也比较低。将App拆成几个大的组件(受React影响,我认为component的粒度很小,叫模块Module可能更加合适),将工程师(估计不少了)拆成几个独立的小组,分别专注于自己组件的开发(提高编译速度),再通过持续集成合并各个小组的代码打包成最终App,是大势所趋,我相信也是所有大公司的普遍做法。
这套方案牵涉到一个组件间通信的问题,包括但不限于以下几种形式:
- 从组件A进入到组件B
- 从组件B获取状态,显示在组件A
- 组件A修改组件B的状态
蘑菇街提供了一个叫做Router的中间件来封装这样的通信,这样每个组件只需要和这个Router交互就行了。后面加入的讨论也是针对这个Router是该使用url、category还是Target-Action的方式展开。
我的看法是,这些方式并没有解决本质问题,即组件间的耦合。但是
这里真的需要解耦吗?
组件间的通信是基于业务上的需求,当组件A肯定需要和组件B通信的时候,他们是直接通信还是通过中间件通信,有什么本质区别呢?他们在业务上是紧密耦合的,是肯定会互相依赖的(比如列表页肯定依赖于详情页)。
组件A不光知道组件B的存在,还知道该调用它的哪个方法,传哪些参数,我都知道这些了,还需要中间件干嘛呢?
而且这种做法会增加额外的维护成本。当组件B的公共接口变化了(比如加了个参数),以前我只需要修改组件A就行了,现在呢,不光要改下组件A(这个参数是要实际的使用者传过来的),还得改下中间件(“转发”下新增的参数),不嫌麻烦么?
另外,这样的修改和你具体使用哪种形式的中间件(url、category、target-action)无关,一旦发生类似的变化,你都要多修改一处代码。
所以,我的看法是静态的组件间不存在解耦,也不需要中间件。
那么不需要组件化了?
组件话肯定是有好处的,但它的好处主要在于工程层面,能将大团队拆分成小组,独立开发,互不干涉,提高协作效率。就像使用React时,你专注于每个component的编写,不用关心其他的component。
这里需要改善的其实是每个组件的公共接口,让其尽量简洁明了,统一规范,降低小组间的沟通成本。
就像React的component间能自由组合,只要传入声明的props就好,这里的组件可以理解为每个小组生成的pod或者framework,我只要看下头文件,就知道该怎么用了。
那么Router就完全没用了?
Router的最大好处,在于动态调用。
组件A不需要知道组件B的存在,甚至它可以在运行时和任何组件通信,这个需求是由服务器传来的或者是其他业务代码动态决定的,我不关心它是具体哪个组件我也不关心它需要哪些参数,我只管把这个需求传给一个Router,它会负责处理。
这里的Router要做得足够健壮,处理好容错和版本兼容性等问题,也要避免Router和各个组件形成依赖,它只负责动态转发,被调用者自己来决定是否能响应具体的请求,这里可能用一个protocol来做好约束比较合适。
Router适合的场景就不用多说了,运营驱动型的产品对此是刚需,一个hybrid页面,通过router能自由跳转到各个组件,这样的灵活性是必须的。