聊聊iOS中的架构模式

924 阅读6分钟

1. 架构是需要演进的

  • 架构是需要演进的, 如果项目规模大了还不演进, 必然就会拖累业务的发展速度.
  • 当业务需求量和团队规模达到一定程度后, 任何一款App都需要考虑架构设计的合理性.
  • 快速迭代的需求开发和漫长重构之间的矛盾, 就像在飞行的飞机上换引擎.
  • 将业务完全解耦, 通用功能下沉
    • 每个业务都是一个独立的Git仓库
    • 每个业务都能生成一个Pod库, 最后再集成到一起
  • MVC是很好的面向对象编程范式, 非常适合个人开发或者小团队开发.
    • 项目大了, 人员多了以后, 这种架构就扛不住了. 因为这时候功能的量级不一样了.
    • 一个大功能, 会由多个功能合并而成, 每个功能都成了一个独立的业务, 团队成员也会按照业务分成不同的团队.
    • 此时, 简单的逻辑、视图、数据划分再也无法满足App大规模工程化的需求.

1.1 模块粒度如何划分? SOLID原则

  • iOS组件, 应该是包含UI控件、相关多个小功能的集合, 是一种粒度适中的模块.
  • S(SRP)单一功能原则: 对象功能要单一, 不要在一个对象里添加很多功能.
  • O(OCP)开闭原则: 扩展是开放的, 修改是封闭的.
  • L(LSP/LOD)里氏替换原则:子类对象是可以替换基类对象的; 迪米特法则:只与你的直接朋友交谈, 不跟"陌生人"说话.
  • I(ISP)接口隔离原则: 接口的用途要单一, 不要在一个接口上根据不同入参实现多个功能.
  • D(DIP)依赖反转原则: 方法应该依赖接口, 不要依赖实例. iOS开发就是高层业务方法依赖于协议.

image.png

1.2 如何分层?

  • 层级最多不要超过三个.
  1. 底层可以使与业务无关的基础组件, 比如网络和存储等.
  2. 中间层一般是通用的业务组件, 比如账号、埋点、支付、购物车等.
  3. 最上层是迭代业务组件, 更新频率最高.

image.png

1.3 多团队如何协作?

  • 合理的团队结构应该是这样的:
    • 首先, 需要一个专门的基建团队, 负责业务无关的基础功能组件和业务相关通用业务组件的开发.
    • 然后, 每个业务都由一个专门的团队来负责开发. 业务可以按照功能耦合度来划分, 耦合度高的业务可以划分成单独的业务团队.
    • 基建团队人员应该是流动的, 从业务团队里来, 再回到业务团队中去. 避免资源浪费, 解决重复建设的问题.
  • 好的架构, 需要在业务开发过程中及早发现开发的痛点, 进行有针对性的改良, 不然就会和实际开发越走越远.
  • 好的架构一定是不简单、不通用的, 但是一定是接地气的, 这样才能更适合自己的团队, 才能够用得上能落地.

2. 中间者架构

  • 采用中间者统一管理的方式, 来控制App的整个生命周期中组件间的调用关系.
  • 好的架构一定是健壮的、灵活的. 中间者架构的易管控使架构更稳固, 易扩展带来了灵活性. image.png
  • CTMediator地址
  • CTMediator使用的是运行时解耦.
// CTMediator调用弹窗显示
[self performTarget:kCTMediatorTargetA
                 action:kCTMediatorActionShowAlert
                 params:paramsToSend
      shouldCacheTarget:NO];
  • Casa的CTMediator实现原理
  • Casa的CTMediator实践
  • CTMediator 本质就是一个方法,用来接收 target、action、params。由于 target、action 都是字符串,params 是字典,对于调用者来说十分不友好,因为调用者要写字符串,而且调用的时候若是不看文档,他也不知道这个字典里该塞什么东西。
  • 所以实际情况中,调用者是不会直接调用 CTMediator 的方法的。那调用者怎么发起调用呢?通过响应者给 CTMediator 做的 category 或者 extension 发起调用。
  • category 或 extension 以函数声明的方式,解决了参数的问题。调用者看这个函数长什么样子,就知道给哪些参数。在 category 或 extension 的方法实现中,把参数字典化,顺便把 target、action 这俩字符串写死在调用里。
  • 于是,对于调用者来说,他就不必查文档去看参数怎么给,也不必担心 target、action 字符串是什么了。这个 category 是一个独立的 Pod,由响应者业务的开发给到。
  • 所以,当一个工程师开发一个业务的时候,他会开发两个 Pod,一个是 category Pod,一个是自己本身的业务 Pod。这样就完美解决了 CTMediator 它自身的缺点。
  • 对于调用者来说,他不会直接依赖 CTMediator 去发起调用,而是直接依赖 category Pod 去发起调用的。这么一来,CTMediator 方案就完美了。
  • 然后还有一点可能需要强调:基于 CTMediator 方案的工程,每一个组件无所谓是 OC 还是 Swift,Pod 也无所谓是 category 还是 extension。也就是说,假设一个工程由 100 个组件组成,那可以是 50 个 OC、50 个 Swift。因为 CTMediator 抹去了不同语言的组件之间的隔阂,所以大家老的 OC 工程可以先应用 CTMediator,把组件拆出来。然后新的业务来了,用 Swift 写,等有空的时候再把老的 OC 改成 Swift,或者不改,都是没问题的。
  • 解耦的精髓在于业务逻辑能够独立出来, 并不是形式上的解除编译上的耦合.
    • 在考虑架构设计时, 我们更多的还是需要在功能逻辑和组件划分上做到同层级解耦, 上下层依赖清晰,
    • 这样的结构才能够使得上层组件易插拔, 下层组件更稳固.

3. MVP架构

  • Model View Presenter

  • 有新的View搞一个新的Presenter来做管理

  • ViewController中设置Presenter, Presenter相当于取代了控制器的角色, 对控制器进行一个瘦身

image.png

  • Presenter还能这样优化

image.png image.png

image.png

  • View层这样用

image.png

4. MVVM架构

  • 属性监听, 赋值, KVO做监听有点麻烦, Facebook有个FBKVOController, RAC框架有点重
  • 控制器做了瘦身, 里的代码很少

image.png

  • V

image.png

image.png

  • VM

image.png

image.png

image.png

发文不易, 喜欢点赞的人更有好运气👍 :), 定期更新+关注不迷路~

ps:欢迎加入笔者18年建立的研究iOS审核及前沿技术的三千人扣群:662339934,坑位有限,备注“掘金网友”可被群管通过~