Artsy
与 objc.io 这期专题的其他团队规模相比,Astsy 的移动团队很小。尽管如此,我们却因为我们在社区的影响力而被关注。我们的 iOS 开发团队成员都参加过著名和大型的 Cocoa 社区开源项目。
Artsy 团队内部充满了我们称之为默认开源的技术氛围。我们不是绝无仅有的一个。开源一个项目有时候听起来更像获得了一个技术勋章,但是这个项目所影响到的东西可能会超出你的想象。开源不单单是创建一个 GitHub repository -- 同时也是我们团队成员的情感分享。
我们团队都信奉开源。尽管我们每个人的动机各不相同 - 从坚信教育的力量到想要帮助其他人站在巨人的肩膀上看得更远 - 我们都从开源中受益匪浅。
我们团队的每个人相信,除非的确有一个理由需要你保密,否则你就应该把它开源。这种精神不单单对于代码。我们在 Google Hangouts On Air 定期举办交流会,邀请其他人参与进来和讨论问题。我们的团队也用一个开源的仓库来组织活动。
我们这个小团队为 Cocoa 开发者社区作出了显著的贡献。我们以这三种方式贡献自己的力量:
1.我们经常会发布一些应用的组件,这些组件作为开源库可能会帮助其他开发者。 2.在使用其他的库的同时,我们发送反馈,bug report 和 pull request。 3.我们鼓励所有的团队成员积极参加社区活动,包括演讲,写博客或者出版书籍。
有几个很好理解的原因可以解释我们为什么想要减少代码的规模和复杂度。我们通过编写小而稳定的组件来提高应用整体的稳定性和完整性。另外,通过可重用的库,我们在编写多个应用时也减少了工作量。
Artsy 主要有三个 iOS 应用,同时还维护着一些小的项目,当有新的项目时,可以避免重复造轮子从而节省时间。对于为了一个应用而创造的库来说,维护和修复漏洞是一件很值得分享的事。我们过去在代码重用的策略做得很好,但是仍然有很大提升的空间。
如果将我们的应用拆分成小而且可重用的几部分的话,会有很多技术上的优点,但同时这些不同的组件也有明确的拥有者。当我们这样做的时候,我们需要确保我们确实把知识分享给团队成员,来保证团队成员们对我们的代码尽可能的熟悉。这一点是非常重要的;当我们团队里的某一个成员突然被法院传召三个月,我们不需要苦恼,因为他不是唯一的对特定部分代码熟悉的人。
除了团队实际的管理外,鼓励开发者去探索 iOS 开发的不同的方向,能帮助他们更专业,更全面。我们在 iOS 领域自然已经炉火纯青,而与此同时学习其他编程语言能帮助我们保持头脑清醒和情绪放松,并且可以发现新的思路来解决相似的问题。
我们远程工作;我们的团队到目前为止还没有同时呆在一个屋子里过。通过像一个开源社区来工作,团队结构更加灵活和可伸缩,而不是像传统的团队一样。
2015 年初,我们完成了 Artsy 的 iOS 应用 eigen 的开源工作。这是一个持续了很多个月的项目;我们慎重考虑过,并逐渐地证明,开源一个面向消费者的应用的确会有它的商业价值。这也反驳了那些质疑我们的声音,让他们看到了这一切是如何发生的。这对于公司来说并不是一个艰难的决定,因为分享知识已然是我们公司的每个人所信奉的核心价值。
开源 eigen 的第一步工作已经完成得差不多了;我们已经尽可能地从我们的应用中开源代码。我们的大部分的准备工作都是在确保代码中敏感的细节不会通过 git 历史记录和 GitHub 的 issue 泄露出去。最后,我们决定用一个全新的 repository,还有完全空白的历史记录以及 issue。
在前面,我说过如果开源则意味着全部对外开放,除非确实有一个理由想让它保密。我们所开源的那些代码并不是让 Artsy 独具一格或者更有价值的代码。Artsy 的有些代码是需要一直闭源的。其中的例子中包括一个商业许可用途的字体,还有 Art Genome Project 所用到的推荐引擎等。
做完前期开源工作的准备后,接下来就是从基础开始搭建一个完整的开源应用。这给了我们机会来审视要如何在开源环境下进行管理项目,处理开发的问题以及进行实际的开发。这种体验与维护社区的开源项目非常类似。
在开发前期我们不会设定严格的的线路图。这部分程度上归咎于我们需要准时完成项目,另外在我们内部的 Slack 频道里也已经有很多交流了。将来,我们会尝试尽量多地将我们的交流放到公共的仓库里去。
开发并开源一个复杂的 iOS 应用这件事并没有很多公司尝试过。在开发工具方面,我们还有些欠缺,这也是必须努力的方向。最常见莫过于 API tokens 的保密。为了解决这个问题,我们创造了一个新的,更加安全的方法来保存这些 keys。
Artsy 是一个设计驱动型的公司,我们的设计师在我们开发工作进行时经常参加进来。我们的设计师能够很容易地参加到开源项目中。只需稍加援手,我们的设计师们就可以调整到开放的方式进行工作。他们已经对如何使用 GitHub 来反馈问题相当熟悉,所以他们参加到开源项目的贡献中是一件再简单不过的事了。他们都有着关于回馈设计社区的想法,和像我们对开发者社区的态度一样。
我们上面说明了一些概念和理论上的东西,接下来说一下我们真实的日常工作。
开源工作与典型的软件开发并没有那么大的差别。我们打开 issue,提交 pull requests,并在 GitHub 上讨论交流。当我们有机会创造一个新的开源库的时候,负责这个库的开发者会使用他自己的账号来创建仓库,而不是使用 Artsy 的账号。
这是一种产品归属感。如果在六个月之后某个团队成员对这个库有什么疑问的话,他可以很快地找到求助的人。同样地,开发者也会有归属感,并且帮助我们营造令人满足和愉悦的工作环境。最后,开发者们了解到这些由他们创造的代码是属于他们的,这样他们可以继续使用这些代码,即使他们离开了 Artsy。
让我们来看一个例子吧。
像很多可靠的开发者一样,我们在尽可能地尝试自动化我们的工作。这其中包括使用持续集成 (CI) 来减少新的 bugs 的产生以及回退。目前,我们使用 Travis 来持续集成,当然,也有很多其他解决方案。
我们很多的测试都是基于 Facebook 的 iOS 截屏测试库来进行的。这个库可以构造一个 view (或者 ViewController),来模拟交互,然后将视图层次结构截图以作参考。之后,当我们测试时,我们进行相同的操作和截图,从而与之前的参考截图作对比。
我们所遇到的一个问题是关于 Travis 的使用。虽然截屏测试在本地能够通过,但它会在 CI 环境下失败。究其原因,是因为截屏测试是由 Kaleidoscope 对提供的参考和不通过的截图进行比对,从而诊断出原因。但是,在 CI 环境下,我们没有取得这些截图的权限,那我们应该怎么办呢?
在维也纳的周末旅行中,Orta 和 Ash 一起讨论了可能的解决办法。最后我们决定构建一个叫 Second Curtain 的工具,它可以解析 xcodebuild
的输出。如果它检测到任何测试失败,那么有关不通过的截图和参考文件截图将会被上传到一个 S3 bucket 上,并可以比较出不同的地方。这是 Ash 第一次用 Ruby 写的比较重量级的工具,这给了开发者一个机会来改进我们的配置工具,并且拓展了知识。
经常有人会问我们为什么把项目都开源。我们已经讨论了我们的技术上的目的,以及它给予我们团体每个成员的感受,但坦白说,开源其实是一桩很聪明的交易。例如,我们正在编写一个开源库来处理使用我们的 API 时所需要进行的身份验证。这项工作不单单会让那些使用我们的 API 进行的开发工作更简单,同时它也使每个人的开发更轻松。这真是太爽啦。
对于开发者,经常有特意避开第三方依赖库的倾向,这种现象在 iOS 开发社区尤为明显。他们经常受害于重复制造轮子,并浪费很多时间来调试,而不是使用那些已经为他们解决了相似问题的库。在我们的移动团队,我们非常反感这种现象,反而,我们更欣赏那种 “自豪地到处搜刮” 的思想 (我们很赞同这个开发者说过的话)。
在我们的公司里,我们都会认真评估员工的个人素质和技术水平;但是,这些指标不单单是 HR 手里的表格上面的几个选项这么简单。如果你确实很优秀,那么这些东西会潜移默化地融入你的日常生活和工作中。而我们,正是由于待在这么一个开源项目的团队里而身体力行。
通过将我们的软件开源,庞大的开发者社群能够对我们的工作提供反馈,让我们有机会与全世界那些出色的开发者一起交流。与别人分享知识同时也帮助我们培养良好的工作氛围 -- 当我们出名以后 -- 反过来会吸引那些好的开发者加入我们。毕竟,我们从来没有得到如此多的尊敬和声望。
我们经常整理那些从博客或者会议演讲中获得的技术知识和技术笔记。它们不仅会帮助我们将见解和技术传给公司外部的开发者,同时便利了那些加入我们团队的新成员,让他们更加迅速地了解到我们的工作,以及我们所使用的工具。我们甚至分享那些关于如何分享知识的经验,这也是其中一件我们正努力去做的事。
开源工作不总是一帆风顺的,但是我们遇到的困难仍然不值一提。一种普遍的关于开源的看法是,让别人看到自己不完美的代码会很尴尬。但我们认为,提高水平最好的办法就是让别人看你的代码,让别人评论你的代码。这不应该成为让你尴尬的原因 -- 同时,几乎,所有开发者都明白,截止日期快要来的时候,项目里那些迫不得已的 hacky 代码必定会缺乏可读性和优雅性。
我们的一些竞争对手在使用我们的代码,因为他们反馈了一些改进给我们。我们也一样。实际上,开源一个商业项目最大的挑战在于管理。这种责任关系是处理人际关系最重要的部分,也是需要认真处理好的 -- 特别是当一个项目得到了足够多的好名声。大部分的项目都没有得到足够的管理,这使它们最终举步维艰。
发布完代码,将项目抛之脑外,并忽视开发者的反馈是一件很常见的事情,但是我们却乐于接受开源项目的责任,并努力继续把项目开源。
那些需要额外花费我们时间来开发和维护的开源项目,经常能帮助从日常的任务中解放出来,而且,通过 GitHub 进行的交流也能够帮到我们团队中远程工作的成员。
在一个拥抱开源的公司里作为一个小的团队而工作,可以让那些由于开源而要承担的各种风险微不足道。如果这种风险确实存在的话,技术好处,商业前景以及开源项目所带来的乐趣要比它们大,并且大得多。
将一个库开源和创建一个开源库其实有着本质上的不同 - 这种不同和从技术上开源还是从精神上开源是一样的。一句话来说,回答这个问题就可以总结两者的差异:
你是为了自己的利益而开源呢,还是为了所有人的利益?