背景

我们教育产品移动端团队中多个应用都使用 CocoaPods 来管理各种私有库,但是私有库本身维护起来有一定的麻烦。比如说 CocoaPods 官方的 master Specs 太大,每次更新都需要很长时间;再比如说私有库在开发过程中主工程通常是通过指向本地代码来进行整合,经常会遇到自己在本地开发,别人拉取新代码后编译不通过的问题;另外我们团队还维护了多个私有的 Specs 库,当某个 pod 提交新版本到 Specs 中,每次往往需要手动更新才能下载到最新代码。有没有什么方法可以让这一切工作自动化,傻瓜化,刚入职的新人也可以快速把项目跑起来,并且能支持持续集成?想到这里,开发一个iOS工程规范命令行工具的需求便在我脑海中生根发芽开来。

技术选型

作为一个 iOS 端开发,开发命令行工具的首选语言肯定是 Swift(OC 还是算了吧),我之前有写过纯 Swift 项目,API 和框架都比较熟悉,但我觉得想要成为一个优秀的工程师/架构师,不应该只把眼界局限在自己的技能范围之内,终身学习/跨界学习应该成为自己的习惯。看了一圈主流的脚本语言,Ruby 是造轮子神器,JS 有一统天下之势,但我最后选择了 Python 。原因无他,唯手熟尔(笑~,其实是个人比较喜欢)。

用户界面

由于这次编写的是 CLI(command line tool)程序,所以用户界面虽然不需要像 GUI 那么花哨,但是至少也要能详尽地描述清楚功能,命令行参数肯定是必须的。这时候就需要一个可以解析命令行参数的库了,在 Python 中我使用了 argparse

添加一条子命令:

1
pods_parser = subparsers.add_parser('pods', help='更新所有私有 pod ,使用 jyios pods -h 查看 -d/-b 等选项')

添加一条可选选项:

1
pods_parser.add_argument("-d", "--directory", default='.', help="指定 PrivatePods 存放的目录,若不指定则默认为当前目录")

最后实现出来的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
usage: jyios [-h] {init,ykt2c,ykt2b,imooc,k12,pods,master,specs} ...
positional arguments:
{init,ykt2c,ykt2b,imooc,k12,pods,master,specs}
init 新人入职初始化,拉取包括 Homebrew、Bundler、Charles 等开发环境和产品源码
ykt2c 云课堂大众版
ykt2b 云课堂企业版
imooc 中国大学MOOC
k12 网易100分
pods 更新所有私有 pod ,使用 jyios pods -h 查看 -d/-b 等选项
master 更新 master specs 仓库
specs 更新除 master 外其他私有 specs 仓库
optional arguments:
-h, --help show this help message and exit

是不是看起来颇有开源项目或者系统自带命令的风格了呢?

程序分发

代码写起来很愉快,如何才能让使用程序的人用起来也很愉快呢?这就涉及到了怎样把程序分发出去的过程,我觉得 App Store 在这方面做得是最好的,全球统一入口,开发者/用户/苹果公司三者都很爽(如果忽略掉扣除的三成平台税的话)。如果把一个 py 文件直接给到用户手里肯定是极不友好的,即使程序的用户本身就是开发者。因为我是用 Python3 写的,如果用户电脑上 Python 版本是2.x甚至根本没有安装 Python 解释器,那这就是一个普通的文本文件,无法实现相应的功能。

我也考虑过使用 Homebrew (用 Mac 的应该都知道)或者 Pip 这种包管理工具分发,但也遇到了一些问题,比如我的电脑环境安装了一些 Python 库,但是 brew 不能直接指定 Python 相关库的依赖,用 pip 的话也会遇到上面说的 Python 版本问题。完成前面的调研之后,我决定采用最简单的直接进行二进制分发,使用 PyInstaller 将 py 文件打包成了一个可执行文件后上传到 GitLab,然后提供了一个安装脚本 install.sh(模仿了一些开源软件),直接使用 curl 就可以一站式安装。

版本更新

写这个命令行工具纯属个人兴趣驱动,写完后自己很爽,不过因为还有两三个命令不太完善,暂时没有在组里推广。但是强哥(我的老大)不仅在 CI 中已经用到这个工具了,而且还给了我很多正向的反馈,促使我又迭代新增了两个功能。一个是把之前硬编码在程序里的私有库数组写成了一个 JSON 文件放在服务器上,方便日后新增私有库;第二是新增了指定私有库分支的命令行选项,方便在持续集成时指向私有库的开发/提测分支。优秀的开源软件一般会迭代后在 CHANGELOG 中补充说明新的功能,我也没有打算例外,及时更新了 README 文件中的内容。

几天下来,我觉得写一个小巧的命令行工具和写一个复杂的大型项目还是有很多区别,但设计开发测试时候的软件工程方面的思路还是一致的,它们都需要 Git 进行版本管理,面向对象进行建模,单元测试驱动开发(惭愧,这个没做好),持续集成进而交付,相关文档也需要及时完善,至少应该做到这样才不失为一个完整的程序。


阅读