iOS 模块化与依赖方向

举报
shenlan9755 发表于 2026/09/23 09:27:51 2026/09/23
【摘要】 iOS 模块化与依赖方向业务增长后,单一工程目标容易出现编译影响面大、代码跨业务引用和公共资源混乱等问题。模块化可以隔离变化,但拆成许多包并不会自动形成良好架构。模块边界应对应稳定业务能力,依赖保持单向,公共接口尽可能小。 一、从变化原因划分模块常见模块类型包括:应用装配:入口、场景和依赖组装。业务功能:账户、订单、资讯等完整能力。领域模块:模型与业务规则。基础设施:网络、存储、日志和任务...

iOS 模块化与依赖方向

业务增长后,单一工程目标容易出现编译影响面大、代码跨业务引用和公共资源混乱等问题。模块化可以隔离变化,但拆成许多包并不会自动形成良好架构。模块边界应对应稳定业务能力,依赖保持单向,公共接口尽可能小。

一、从变化原因划分模块

常见模块类型包括:

  • 应用装配:入口、场景和依赖组装。
  • 业务功能:账户、订单、资讯等完整能力。
  • 领域模块:模型与业务规则。
  • 基础设施:网络、存储、日志和任务调度。
  • 设计系统:颜色、字体、图标和公共组件。

边界来自团队所有权和变化原因,不应机械地为每个控制器创建模块。

二、保持依赖向内

业务功能可以依赖领域协议,基础实现则由应用层注入。领域规则不应引用具体页面和网络客户端。

public protocol AccountSession {
    var currentUserId: String? { get }
    var isSignedIn: Bool { get }
}

public final class SubmitOrderUseCase {
    private let session: AccountSession
    private let repository: OrderRepository

    public init(
        session: AccountSession,
        repository: OrderRepository
    ) {
        self.session = session
        self.repository = repository
    }
}

应用装配层提供实现,订单模块不需要知道账户页面和存储细节。

三、缩小 public 表面

模块内部控制器、数据实体和辅助类尽量保持内部可见。跨模块只暴露入口协议、稳定参数和结果类型。

public struct OrderDetailInput: Equatable {
    public let orderId: String
    public let source: OrderSource
}

public protocol OrderFeatureRouting {
    func makeOrderDetail(input: OrderDetailInput) -> UIViewController
}

不要跨模块传递数据库对象或内部页面模型,这会把实现细节变成长期契约。

四、用协议打破反向依赖

账户模块不应为了打开订单页而直接依赖订单内部类型。可以由应用层实现路由协议,或通过协调器把两个功能装配起来。

协议应放在依赖方向合理的一侧。为每个类都创建协议会增加理解成本,只抽象真正需要替换或跨边界的能力。

五、避免万能 Core 模块

所有无法归类的代码都放进核心模块,会让它最终被所有功能依赖,也依赖大量基础组件,形成新的单体。

一段代码只有在语义稳定、被多个独立模块复用时才适合提取。偶然相似但未来变化原因不同的实现,可以暂时保留在各自业务中。

六、管理资源

颜色和组件优先来自设计系统模块,业务图片和本地化文本留在功能模块。资源名称使用项目约定前缀,避免合并冲突。

代码读取必需资源时,可以让缺失在开发阶段直接暴露,不用为每项资源添加不符合设计的随机默认值。

七、依赖注入集中在装配层

final class OrderFeatureFactory {
    private let session: AccountSession
    private let repository: OrderRepository

    init(session: AccountSession, repository: OrderRepository) {
        self.session = session
        self.repository = repository
    }

    func makeSubmitUseCase() -> SubmitOrderUseCase {
        SubmitOrderUseCase(session: session, repository: repository)
    }
}

集中装配能清楚展示依赖图,也便于测试替换。业务内部到处读取全局单例会隐藏真实依赖。

八、控制跨模块事件

全局通知看似能消除依赖,过多后却让事件来源和顺序不可追踪。关键流程通过明确协议和调用链完成,一对多的全局事实才使用广播。

模块事件载荷只包含稳定领域值,不携带视图和上下文对象。

九、逐步迁移

模块化适合渐进实施:

  1. 绘制当前依赖关系。
  2. 选择边界清晰的功能。
  3. 定义最小公共契约。
  4. 保持行为不变地移动实现。
  5. 删除旧入口并验证构建与测试。

不要在移动模块的同时大规模改写业务,否则问题来源难以定位。

十、衡量模块化效果

观察指标包括:

  • 小改动影响的编译范围。
  • 跨业务导入数量。
  • 公共接口大小。
  • 循环依赖是否消失。
  • 团队并行修改冲突。
  • 单模块测试是否容易执行。

使用新的包管理或构建能力前,要确认项目最低系统和工具链兼容要求。

总结

iOS 模块化的目标是隔离变化。围绕业务能力划分模块,保持单向依赖,缩小公开表面,并由应用层集中装配实现。避免万能公共模块和全局事件总线,再用编译影响与协作效果验证拆分价值。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。