Objective-C 与 Swift 混合编程中的一些实践

2020-05-23  本文已影响0人  csqingyang

从利于编写 Unit test 的方面来说, 在 Objective-C 和 Swift 混编的项目中, 更推荐将 Swift 中调用的 Objective-C 中的代码集中管理.
  举例说明: Objective-C 中由于历史原因, 单例普遍比较常见. 在 Swift 中使用也十分方便. 但是在编写单元测试时, 就相对比较困难. 解决方案1:
  将对单例的引用拆分为这个 Swift 文件中对自己私有属性的访问, 让属性指向这个单例实体. 在对象的构造函数中提供对应的设置默认值的方法, 比如此时在构造函数中, 设置这个私有属性的默认值为获取 Objective-C 中的单例. 这样在 Swift 侧编写单元测试时就可以提供一个 mock 对象来给 Swift 对象.
  这个 mock 对象可以规定成遵守某种协议的对象. 这样在测试时提供一个遵守要求协议的 mock 对象, 达到测试目的. 如果原来的单例对象没有能抽离一定的协议供外界使用, 则可以在 Unit test target 中提供一个继承了原来单例对象的 mock 对象达到测试目的.
  优势: Swift 对象对外只允许通过构造函数初始化自己的成员变量, 一定程度上, 保证了安全.
  劣势: 需要对原来的工程代码做改动, 这部分的 change 需要有对应的验证步骤.
解决方案2:
  将对单例的引用同样设置为属性, 但是不使用 private 修饰, 使用默认 internal 修饰, 并设置为 lazy 属性, 并提供默认值来延缓初始化时间. 这样在 unit test target 部分就可以为这个对象的 lazy 属性设置对应的 mock 对象来达到测试目的.
  优势: 不用大范围更改 production code, 同时能延缓没有用到的对象的初始化时间, 能提供有限的应用性能.
  劣势: Swift 对象对外的属性控制不能有效控制, 不是特别好的实践.
解决方案3:
  将 Swift 中用到的 Objective-C 部分, 尽量集中在一个部分管理, 或者是尽量集中在某几个功能明确的模块中调用. 简单说就是在 Swift 模块中就尽量 Swifty. Swift 模块部分调用 Objective-C 部分就都通过这一个模块对外通信. 一段时间发展之后, 还可以将这个对外模块设置为工厂模式, 提供更方便的访问控制. 在编写单元测试时也可以尽量 mock 这个对外接口.
  优势: Swift 模块对 Objective-C 部分的访问被管控在小范围内, 对外逻辑清晰, 不会造成很多困扰.
  劣势: 这种方式如果演进的不好, 可能会造成一个接口中有了好多不相干的访问方法, 对外的文件命名也不是很好确定.
  解决方式: 在定义时, 可以将对外文件定义的尽量模块相关化, 比如工具类的放一起, 扩展类放一起, 模块访问类放一起, 在开始时就尽量避免复杂情况出现.

总结: 在项目初期, 应该确定一个原则: 将对 Objective-C 模块的访问控制在一个部分, 在 Swift 中定义使用时, 可以多考虑下如果要写单元测试时, 这部分可以怎么写. 开发工程师应该自己尽量做到稳定测试. 设计模式大法好啊.

上一篇下一篇

猜你喜欢

热点阅读