iOS项目组件化

背景

我们提供车联网全套解决方案,向外输出能力是其中一种。

关于如何与第三方企业合作,向外输出技术能力,无非就三种方式

-w880

可以看出,SDK方案相对可取。 如果仅仅为第三方封装SDK显然是资源浪费。

什么是组件化

将程序中功能相对独立的部分打包在一起形成模块,并且减少模块之间的直接依赖。

-w988

  1. 底层是中间件(业务无关的组件,如网络请求、存储、工具类),共同为上层业务提供服务,允许相互引用(但应尽量减少);
  2. 业务组件在上层依赖中间件,相互之间不允许直接引用。

为什么要用组件化研发方案

因素
对内敏捷开发,解决跨团队、异地办公的问题
对外输出能力
架构要具有延伸性,为可预见的业务发展提供技术支持

在业务初期,采用单一工程开发周期更短,是合适的开发模式,但是随着业务复杂度不断增加,工程越来越庞大,开发人员逐渐增多,单一工程的开发模式会出现一系列问题:

问题点 举例
耦合严重 组件之间依赖过于复杂,维护成本高
容易出现冲突 xib 或者代码冲突机会大大增加
开发效率低 每次都需要编译整个项目

近两年组件化开发较为火热,总的来说,组件化最大的好处就是低耦合,这是程序开发最基本的原则

收益
维护成本低
复用性好
版本控制冲突少
加快编译速度
方便 QA 有针对性地测试

当然组件化也有一些代价:

代价
对新加入团队的研发人员不友好
开发流程变复杂,开发成本变高
模块化初期投入较大,影响发版节奏

从技术角度来讲,组件化是有套路的,将业务根据颗粒度进行划分,基于git管理代码,抽取出不同的组件, 将不同的组件归集到不同的私有仓库,基于Cocospods 管理这些私有仓库,通过壳子工程,抹上胶水将这些组件串通起来,胶水就是所谓的路由或者中间人。

我们APP进行业务开发的同时,沉淀下来的各个独立模块即可向第三方输出能力。

实现方式

  1. 对于基础能力库,直接封装成 pod 放在私有的 repo 上即可
  2. 对于业务组件,重点是如何解决耦合问题

第二点问题的本质是组件之间服务的提供和调用。 需要解决两个问题:

  1. 服务的发现
  2. 服务的调用,并且避免中间人对组件的依赖。

方案分析已在【组件化方案分析】中有详述,本文不再讨论。

对胶水的选择

以上分析的三种方案,我们统称为胶水,它们各有优缺点,没有一个是360°完美的。 综合考虑项目实际情况后,对于APP层面的胶水,选择以Protocol + Wrapper为主, 少量openURL配合的方式。

胶水构成 主要任务
Dubbo 治理组件间通讯,如何提供服务、如何发现服务、如何使用服务
URLRouter 用来处理推送、H5跳转、支付回调、分享等

借鉴后台框架Dubbo及阿里的BeeHive设计思路,我们对胶水层进行优化。 我们将每个组件提供的能力理解为向外提供服务。 业务组件既是服务提供方又是服务使用者。

Dubbo提供的能力
Module治理
Service治理
事件治理

Dubbo不是本篇讨论重点,举个简单实例,不再发散讨论。 发现服务及使用服务

    id<XXLoginModuleService> service = [XXDubbo createService:@protocol(XXLoginModuleService)];
    if(service) {
        @XX_WEAKIFY(self)
        [XXHUD showLoading];
        [service logoutWithCompletion:^(NSError * _Nullable error) {
            [XXHUD hideHUD];
        }];
    }

对外接口规范及实现方式

原则是

  1. 可读性、可维护性、可变更性
  2. 利益最大化,满足项目需要即可,尽量规避缺点
  3. 对外提供的能力,表达方式即规范要一致
  4. 组件内部,对外隐藏具体实现,可以使用MVC、MVVM、MVP、APO 等等方式,自由发挥,需要研发团队协商并建立规范。

Protocol + Wrapper

  1. Protocol定义好对外提供的能力
  2. Wrapper ,一般是组件提供方的私有类,不对外暴露,用来实现Protocol能力

网易云IM的iOS SDK很好的运用了Protocol + Wrapper方案,顺丰内部员工的IM协同办公APP使用了这个SDK,经得起考验。

https://netease.im/im-sdk-demo

感谢

曾静, BASE 深圳