Skip to content

结束语眼见千遍,不如手过一遍

首先,我要说一句:恭喜你完成了整个课程的学习!当然,我也很感谢你这四个月来的陪伴和支持!相信通过这个课程的学习,你会对 iOS 开发有了一个整体的认识和理解了。不过,在这最后的结束语中,我还是想强调一下:提升技术最有效的办法是动手实践,眼见千遍,不如手过一遍。

那怎么来"手过一遍"呢?下面我就结合课程的内容来给你提供一条实践路径,你可以使用它来提高架构和编码能力,以及推动项目的自动化和工程化进程。

第一步,我建议你先搭建一个统一的开发环境 。磨刀不误砍柴工,统一的开发环境是项目规范化和自动化的基础。你可以通过《01 | 开发环境:如何使用 Ruby 工具链统一开发环境?》《02 | 依赖管理:如何使用 CocoaPods 统一依赖库的管理? 》《03 | 配置准备:如何搭建多环境支持,为 App 开发作准备》的学习来为团队搭建统一的开发环境。该环境包括统一的开发工具和 Ruby 工具链、统一的依赖库管理,以及为 App 配置开发、测试和生产等不同运行版本。

有了统一的环境以后,接下来我建议你使用 fastlane 来开发自动化脚本 ,以减少大量重复的手工操作。课程的《05 | 自动化准备:如何使用 fastlane 管理自动化操作?》《24 | 解决打包痛点:如何统一管理 Certificates 和 Profiles?》《25 | 自动化构建:解决大量重复性人力工作神器》中详细讲述了如何使用 fastlane 管理私钥、Certificates 和 Provisioning Profiles,以及如何自动化打包、签名和发布等操作。从时间成本来看,开发自动化脚本的投入收益率非常最高,你可以参考这些文章以及 Moments App 的 Fastfile 文件来为项目定制一套顺手的自动化配置。

完成自动化脚本的开发以后,你就可以在任何一台机器上进行打包、签名和发布了。为了进一步推动工程化建设,你可以搭建 CI 来完成无人手交付 。要搭建 CI,就要先统一代码的管理流程,这个你可以参考《06 | 代码管理:如何使用 Git 与 GitHub 统一代码管理流程?》来规范代码管理流程,然后参考《26 | 持续集成:如何实现无需人手的快速交付?》来搭建你所需的 CI,例如使用 Travis CI 来搭建全服务 CI,当然也可以随着团队发展升级为云端虚拟机 CI 乃至全手工维护 CI。CI 不仅能优化构建、测试和发布流程,从而保证产品的快速交付,同时也能推动工程化进程。因此,可以利用 CI 来优化流程并推进工程师文化的建设。

假如你成功搭建了 CI,相信已经为团队节省了大量的时间,再接下来就可以把精力专注在推动产品的快速迭代和优化上面了。

从课程留言反馈来看,功能开关是一个非常实用的功能,它能帮助我们分离开发、测试和产品环境,并能帮助测试人员和产品经理快速验证产品的功能。你可以参考《09 | 开关组件:如何使用功能开关,支持产品快速迭代》《10 | 支撑组件:如何实现隐藏菜单,快速测试与验证?》实现功能开关和隐藏菜单

为了进一步优化线上的 App,我建议所有的 App 都添加统计分析服务、崩溃和性能监控以及执行 A/B 测试 。引入这些服务的开发成本都非常低,具体操作可以参考《27 | 统计分析:如何架构灵活的统计分析服务,助力产品增长?》《28 | 崩溃报告:如何借助崩溃报告解决线上的 Bug?》《29 | 远程开关:如何远程遥控上线 App 的产品行为?》《30 | A/B 测试:如何用 A/B 测试协助产品抉择?》

除此之外,你还可以根据自身的需求为 App添加多语言、动态字体或者深色模式的支持 ,这样能帮助你把 App 推广到更广阔的用户群。这些功能都相对独立,可以参考《12 | 功能组件:如何设置多语言支持,为全球化做准备?》《13 | 功能组件:如何设置动态字体,提升视力辅助功能?》《14 | 功能组件:如何使用语义色,支持深色模式?》来选择实施。

这里再看一下 App 的架构与实现。从课程留言反馈来看,组件化是大家最为关心的一个主题。其实,我们课程中有好几讲都与组件化相关。以我的理解,组件化主要由两大部分组成:逻辑上的解耦和物理上的分离 。物理上的分离相对简单,通常使用依赖管理工具来完成,我们在《08 | 设计组件:DesignKit 组件桥接设计与开发规范》里讲述了如何使用 CocoaPods 来管理内部的 Pod。从技术深度来看,这方面属于"术",遇到问题可以通过查看文档等方式得以很好地解决。在组件化的建设道路上,我认为最为重要的是如何实现架构上的解耦和分层,以及理顺各个模块之间的单向依赖关系。只要模块内部的职责定义好,模块之间的依赖关系设计好,要实现物理上的分离就变成水到渠成的事情了。反过来,如果代码的架构没有解耦,模块之间彼此依赖,就无法把模块进行物理分离了。由此可见,实现逻辑上的解耦属于"道",是我们关注的重点。

那怎么才能设计一个责任清晰的模块呢?又该如何理顺模块间的依赖关系呢?我们在课程的"模块三:架构与实现"中详细讲述了如何使用 BFF 和 MVVM 来进行 App 的架构,并介绍了 MVVM 内每一层的架构与实现方式。在《32 | UI 替换:如何使用 SwiftUI 快速替换原有 UI?》中还进一步讲解了如何在不改动其他模块的情况下把 UIKit 替换成 SwiftUI,想必你已经见识到这套架构的威力了。当然,这并不代表课程里的架构就是默认的或者标准的 MVVM 实现方式,软件架构领域根本就没有什么一成不变的标准方案,一套好的方案应该可以根据需求的变化而不断地迭代与改进。在课程里面,我们沿用了一些通用的原则,例如单一责任原则和开闭原则等进行架构和设计。遵循这些原则,我们就能开发出具备可重用、可扩展和可维护等特性的高质量代码。我希望你在学习完这个课程以后能灵活运行那些原则来架构和设计 App,而不是简单地照搬 Moments App 上的实现。

假如你自己编写完了代码,那怎样才能验证这些代码是否具备高质量呢?单元测试是检验代码质量的一种有效办法 ,因为单元测试能强迫我们厘清模块内部的责任,并且强迫我们使用依赖注入的方式来管理模块之间的依赖关系。你可以参考《23 | TDD 与单元测试:如何保证功能模块的高质量?》来看看如何进行单元测试。

最后,我想说的是:写代码是一门手艺活。我们整个课程的所有知识点都是通过 Moments App 表现出来的,你要融会贯通,把所学应用到实际工作中,动手实践是关键,我建议你把 Moments App 的代码从 GitHub 下载下来,然后对照课程思考为什么这样做、这样做有什么优缺点,等等。

关于这个课程,我是从去年 9 月份开始编写 Moments App 的代码,然后梳理大纲,分类知识点并完善 Moments App 的架构与实现,最后再编写文章和反复审核,历经了整整 9 个月的时间。这段时间不仅仅是一个输出的过程,更多的是我对自己多年来经验的总结与提炼,是一个自我提升的过程。很感谢拉勾教育团队给予我分享经验的机会,还有再次感谢有你相伴,希望在移动开发的道路上一起并肩前行。

这里我也邀请你参与对本课程的评价,你的每一个意见或建议对我来说都是很重要的。点击链接,即可参与评价,还有机会获得惊喜奖品哦!