iOS 组件化改造:从私有 pod 源开始

App 三岁了,单工程 40 万行代码,全量编译要 15 分钟,改一行代码喝杯水回来才能跑真机。终于说服老板让我们做组件化。这篇记录前期的方案取舍,给后来人省点力气。 先说结论:不要一步到位上"总线"架构。 网上流传的组件化方案大多是 CTMediator 那一派,运行时解注册表调用。演示很漂亮,但真落地会发现调用关系全靠字符串,IDE 跳转变瞎,重构基本靠全局搜索。我们最后的方案保守得多: 底层工具库(网络、缓存、埋点)拆成独立的私有 pod,用 cocoapods-packager 发到自建的私有源; 业务模块先只在物理上拆目录,通过 protocol 文件互相依赖,暂时不做运行时解耦; 主工程退化为一个壳,只负责组装 tab 和路由。 这个方案跑了半年,编译时间从 15 分钟降到 4 分钟(业务模块可以用 pod install 之后按需引入调试),虽然没到网上吹的"秒级编译",但对日常开发体验的提升已经非常明显。 私有源的坑。 自建源用的是 nexus,权限管理一塌糊涂,最后是靠 git tag + CI 校验版本号一致性来保证不出乱子。后来听说公司内部有 Artifactory 的 license,就迁过去了,省心很多。建议准备做组件化的团队先解决制品库的问题,工具链不顺手,组件化推行不下去——这不是技术问题,是工程习惯问题。 下一阶段的计划是把业务模块间的 protocol 依赖收敛到一个独立的接口层仓库里,谁改接口谁发版。半年后 hopefully 能再写一篇续集,写写中间件方案到底要不要上。

2019-05-21 · 芮靖安

从 Objective-C 到 Swift:一次不太顺利的迁移

公司的主 App 跑了三年多 Objective-C,今年年初终于下定决心往 Swift 迁。原计划三个月迁完,实际用了五个多月,中间踩的坑值得记一笔。 不要想着一次性迁完。 我们最初的方案是新开一个 Swift 分支,集中人力把旧代码全部翻译一遍。干了两个星期就发现这条路走不通:业务需求不会停,分支落后主干越来越多,合并冲突解到怀疑人生。后来改成混合编译,新的模块用 Swift 写,旧的 OC 代码按模块逐步迁,才把节奏理顺。 bridging header 是个大坑。 项目里如果既有 OC 引用 Swift,又有 Swift 引用 OC,Xcode 的报错信息基本不可读。我们最后的经验是:所有 OC 头文件里用到的第三方类型,尽量在 pch 里收口,别让 Swift 端直接碰到太深的头文件链。 还有一个血泪教训:Swift 4.2 之前 API 变动太剧烈了,我们迁移中途 Swift 4.1 发布,#selector 和 KVO 相关的写法改了不少,又返工了半个月。现在回头看,选对版本窗口期很重要,大版本发布前千万别开迁。 代码示例没什么好贴的,唯一想留的是这条规律:迁移期间新代码的 code review 强度要加倍。Swift 写起来太舒服,新人很容易在 optional 处理上放飞自我,! 满天飞。我们在 CI 里加了 SwiftLint 的 implicitly_unwrapped_optional 规则之后,线上 crash 率才慢慢降下来。 总结:迁移本身不难,难的是在业务不停的情况下迁。如果重来一次,我会在开始前先把模块依赖关系理清楚,从依赖最少的叶子模块开始迁,而不是按页面从上往下迁。

2018-04-12 · 芮靖安