與 objc.io 這期專題的其他團(tuán)隊(duì)規(guī)模相比,Astsy 的移動團(tuán)隊(duì)很小。盡管如此,我們卻因?yàn)槲覀冊谏鐓^(qū)的影響力而被關(guān)注。我們的 iOS 開發(fā)團(tuán)隊(duì)成員都參加過著名和大型的 Cocoa 社區(qū)開源項(xiàng)目。
Artsy 團(tuán)隊(duì)內(nèi)部充滿了我們稱之為默認(rèn)開源的技術(shù)氛圍。我們不是絕無僅有的一個(gè)。開源一個(gè)項(xiàng)目有時(shí)候聽起來更像獲得了一個(gè)技術(shù)勛章,但是這個(gè)項(xiàng)目所影響到的東西可能會超出你的想象。開源不單單是創(chuàng)建一個(gè) GitHub repository -- 同時(shí)也是我們團(tuán)隊(duì)成員的情感分享。
我們團(tuán)隊(duì)都信奉開源。盡管我們每個(gè)人的動機(jī)各不相同 - 從堅(jiān)信教育的力量到想要幫助其他人站在巨人的肩膀上看得更遠(yuǎn) - 我們都從開源中受益匪淺。
我們團(tuán)隊(duì)的每個(gè)人相信,除非的確有一個(gè)理由需要你保密,否則你就應(yīng)該把它開源。這種精神不單單對于代碼。我們在 Google Hangouts On Air 定期舉辦交流會,邀請其他人參與進(jìn)來和討論問題。我們的團(tuán)隊(duì)也用一個(gè)開源的倉庫來組織活動。
我們這個(gè)小團(tuán)隊(duì)為 Cocoa 開發(fā)者社區(qū)作出了顯著的貢獻(xiàn)。我們以這三種方式貢獻(xiàn)自己的力量:
1.我們經(jīng)常會發(fā)布一些應(yīng)用的組件,這些組件作為開源庫可能會幫助其他開發(fā)者。 2.在使用其他的庫的同時(shí),我們發(fā)送反饋,bug report 和 pull request。 3.我們鼓勵(lì)所有的團(tuán)隊(duì)成員積極參加社區(qū)活動,包括演講,寫博客或者出版書籍。
有幾個(gè)很好理解的原因可以解釋我們?yōu)槭裁聪胍獪p少代碼的規(guī)模和復(fù)雜度。我們通過編寫小而穩(wěn)定的組件來提高應(yīng)用整體的穩(wěn)定性和完整性。另外,通過可重用的庫,我們在編寫多個(gè)應(yīng)用時(shí)也減少了工作量。
Artsy 主要有三個(gè) iOS 應(yīng)用,同時(shí)還維護(hù)著一些小的項(xiàng)目,當(dāng)有新的項(xiàng)目時(shí),可以避免重復(fù)造輪子從而節(jié)省時(shí)間。對于為了一個(gè)應(yīng)用而創(chuàng)造的庫來說,維護(hù)和修復(fù)漏洞是一件很值得分享的事。我們過去在代碼重用的策略做得很好,但是仍然有很大提升的空間。
如果將我們的應(yīng)用拆分成小而且可重用的幾部分的話,會有很多技術(shù)上的優(yōu)點(diǎn),但同時(shí)這些不同的組件也有明確的擁有者。當(dāng)我們這樣做的時(shí)候,我們需要確保我們確實(shí)把知識分享給團(tuán)隊(duì)成員,來保證團(tuán)隊(duì)成員們對我們的代碼盡可能的熟悉。這一點(diǎn)是非常重要的;當(dāng)我們團(tuán)隊(duì)里的某一個(gè)成員突然被法院傳召三個(gè)月,我們不需要苦惱,因?yàn)樗皇俏ㄒ坏膶μ囟ú糠执a熟悉的人。
除了團(tuán)隊(duì)實(shí)際的管理外,鼓勵(lì)開發(fā)者去探索 iOS 開發(fā)的不同的方向,能幫助他們更專業(yè),更全面。我們在 iOS 領(lǐng)域自然已經(jīng)爐火純青,而與此同時(shí)學(xué)習(xí)其他編程語言能幫助我們保持頭腦清醒和情緒放松,并且可以發(fā)現(xiàn)新的思路來解決相似的問題。
我們遠(yuǎn)程工作;我們的團(tuán)隊(duì)到目前為止還沒有同時(shí)呆在一個(gè)屋子里過。通過像一個(gè)開源社區(qū)來工作,團(tuán)隊(duì)結(jié)構(gòu)更加靈活和可伸縮,而不是像傳統(tǒng)的團(tuán)隊(duì)一樣。
2015 年初,我們完成了 Artsy 的 iOS 應(yīng)用 eigen 的開源工作。這是一個(gè)持續(xù)了很多個(gè)月的項(xiàng)目;我們慎重考慮過,并逐漸地證明,開源一個(gè)面向消費(fèi)者的應(yīng)用的確會有它的商業(yè)價(jià)值。這也反駁了那些質(zhì)疑我們的聲音,讓他們看到了這一切是如何發(fā)生的。這對于公司來說并不是一個(gè)艱難的決定,因?yàn)榉窒碇R已然是我們公司的每個(gè)人所信奉的核心價(jià)值。
開源 eigen 的第一步工作已經(jīng)完成得差不多了;我們已經(jīng)盡可能地從我們的應(yīng)用中開源代碼。我們的大部分的準(zhǔn)備工作都是在確保代碼中敏感的細(xì)節(jié)不會通過 git 歷史記錄和 GitHub 的 issue 泄露出去。最后,我們決定用一個(gè)全新的 repository,還有完全空白的歷史記錄以及 issue。
在前面,我說過如果開源則意味著全部對外開放,除非確實(shí)有一個(gè)理由想讓它保密。我們所開源的那些代碼并不是讓 Artsy 獨(dú)具一格或者更有價(jià)值的代碼。Artsy 的有些代碼是需要一直閉源的。其中的例子中包括一個(gè)商業(yè)許可用途的字體,還有 Art Genome Project 所用到的推薦引擎等。
做完前期開源工作的準(zhǔn)備后,接下來就是從基礎(chǔ)開始搭建一個(gè)完整的開源應(yīng)用。這給了我們機(jī)會來審視要如何在開源環(huán)境下進(jìn)行管理項(xiàng)目,處理開發(fā)的問題以及進(jìn)行實(shí)際的開發(fā)。這種體驗(yàn)與維護(hù)社區(qū)的開源項(xiàng)目非常類似。
在開發(fā)前期我們不會設(shè)定嚴(yán)格的的線路圖。這部分程度上歸咎于我們需要準(zhǔn)時(shí)完成項(xiàng)目,另外在我們內(nèi)部的 Slack 頻道里也已經(jīng)有很多交流了。將來,我們會嘗試盡量多地將我們的交流放到公共的倉庫里去。
開發(fā)并開源一個(gè)復(fù)雜的 iOS 應(yīng)用這件事并沒有很多公司嘗試過。在開發(fā)工具方面,我們還有些欠缺,這也是必須努力的方向。最常見莫過于 API tokens 的保密。為了解決這個(gè)問題,我們創(chuàng)造了一個(gè)新的,更加安全的方法來保存這些 keys。
Artsy 是一個(gè)設(shè)計(jì)驅(qū)動型的公司,我們的設(shè)計(jì)師在我們開發(fā)工作進(jìn)行時(shí)經(jīng)常參加進(jìn)來。我們的設(shè)計(jì)師能夠很容易地參加到開源項(xiàng)目中。只需稍加援手,我們的設(shè)計(jì)師們就可以調(diào)整到開放的方式進(jìn)行工作。他們已經(jīng)對如何使用 GitHub 來反饋問題相當(dāng)熟悉,所以他們參加到開源項(xiàng)目的貢獻(xiàn)中是一件再簡單不過的事了。他們都有著關(guān)于回饋設(shè)計(jì)社區(qū)的想法,和像我們對開發(fā)者社區(qū)的態(tài)度一樣。
我們上面說明了一些概念和理論上的東西,接下來說一下我們真實(shí)的日常工作。
開源工作與典型的軟件開發(fā)并沒有那么大的差別。我們打開 issue,提交 pull requests,并在 GitHub 上討論交流。當(dāng)我們有機(jī)會創(chuàng)造一個(gè)新的開源庫的時(shí)候,負(fù)責(zé)這個(gè)庫的開發(fā)者會使用他自己的賬號來創(chuàng)建倉庫,而不是使用 Artsy 的賬號。
這是一種產(chǎn)品歸屬感。如果在六個(gè)月之后某個(gè)團(tuán)隊(duì)成員對這個(gè)庫有什么疑問的話,他可以很快地找到求助的人。同樣地,開發(fā)者也會有歸屬感,并且?guī)椭覀儬I造令人滿足和愉悅的工作環(huán)境。最后,開發(fā)者們了解到這些由他們創(chuàng)造的代碼是屬于他們的,這樣他們可以繼續(xù)使用這些代碼,即使他們離開了 Artsy。
讓我們來看一個(gè)例子吧。
像很多可靠的開發(fā)者一樣,我們在盡可能地嘗試自動化我們的工作。這其中包括使用持續(xù)集成 (CI) 來減少新的 bugs 的產(chǎn)生以及回退。目前,我們使用 Travis 來持續(xù)集成,當(dāng)然,也有很多其他解決方案。
我們很多的測試都是基于 Facebook 的 iOS 截屏測試庫來進(jìn)行的。這個(gè)庫可以構(gòu)造一個(gè) view (或者 ViewController),來模擬交互,然后將視圖層次結(jié)構(gòu)截圖以作參考。之后,當(dāng)我們測試時(shí),我們進(jìn)行相同的操作和截圖,從而與之前的參考截圖作對比。
我們所遇到的一個(gè)問題是關(guān)于 Travis 的使用。雖然截屏測試在本地能夠通過,但它會在 CI 環(huán)境下失敗。究其原因,是因?yàn)榻仄翜y試是由 Kaleidoscope 對提供的參考和不通過的截圖進(jìn)行比對,從而診斷出原因。但是,在 CI 環(huán)境下,我們沒有取得這些截圖的權(quán)限,那我們應(yīng)該怎么辦呢?
在維也納的周末旅行中,Orta 和 Ash 一起討論了可能的解決辦法。最后我們決定構(gòu)建一個(gè)叫 Second Curtain 的工具,它可以解析 xcodebuild
的輸出。如果它檢測到任何測試失敗,那么有關(guān)不通過的截圖和參考文件截圖將會被上傳到一個(gè) S3 bucket 上,并可以比較出不同的地方。這是 Ash 第一次用 Ruby 寫的比較重量級的工具,這給了開發(fā)者一個(gè)機(jī)會來改進(jìn)我們的配置工具,并且拓展了知識。
經(jīng)常有人會問我們?yōu)槭裁窗秧?xiàng)目都開源。我們已經(jīng)討論了我們的技術(shù)上的目的,以及它給予我們團(tuán)體每個(gè)成員的感受,但坦白說,開源其實(shí)是一樁很聰明的交易。例如,我們正在編寫一個(gè)開源庫來處理使用我們的 API 時(shí)所需要進(jìn)行的身份驗(yàn)證。這項(xiàng)工作不單單會讓那些使用我們的 API 進(jìn)行的開發(fā)工作更簡單,同時(shí)它也使每個(gè)人的開發(fā)更輕松。這真是太爽啦。
對于開發(fā)者,經(jīng)常有特意避開第三方依賴庫的傾向,這種現(xiàn)象在 iOS 開發(fā)社區(qū)尤為明顯。他們經(jīng)常受害于重復(fù)制造輪子,并浪費(fèi)很多時(shí)間來調(diào)試,而不是使用那些已經(jīng)為他們解決了相似問題的庫。在我們的移動團(tuán)隊(duì),我們非常反感這種現(xiàn)象,反而,我們更欣賞那種 “自豪地到處搜刮” 的思想 (我們很贊同這個(gè)開發(fā)者說過的話)。
在我們的公司里,我們都會認(rèn)真評估員工的個(gè)人素質(zhì)和技術(shù)水平;但是,這些指標(biāo)不單單是 HR 手里的表格上面的幾個(gè)選項(xiàng)這么簡單。如果你確實(shí)很優(yōu)秀,那么這些東西會潛移默化地融入你的日常生活和工作中。而我們,正是由于待在這么一個(gè)開源項(xiàng)目的團(tuán)隊(duì)里而身體力行。
通過將我們的軟件開源,龐大的開發(fā)者社群能夠?qū)ξ覀兊墓ぷ魈峁┓答仯屛覀冇袡C(jī)會與全世界那些出色的開發(fā)者一起交流。與別人分享知識同時(shí)也幫助我們培養(yǎng)良好的工作氛圍 -- 當(dāng)我們出名以后 -- 反過來會吸引那些好的開發(fā)者加入我們。畢竟,我們從來沒有得到如此多的尊敬和聲望。
我們經(jīng)常整理那些從博客或者會議演講中獲得的技術(shù)知識和技術(shù)筆記。它們不僅會幫助我們將見解和技術(shù)傳給公司外部的開發(fā)者,同時(shí)便利了那些加入我們團(tuán)隊(duì)的新成員,讓他們更加迅速地了解到我們的工作,以及我們所使用的工具。我們甚至分享那些關(guān)于如何分享知識的經(jīng)驗(yàn),這也是其中一件我們正努力去做的事。
開源工作不總是一帆風(fēng)順的,但是我們遇到的困難仍然不值一提。一種普遍的關(guān)于開源的看法是,讓別人看到自己不完美的代碼會很尷尬。但我們認(rèn)為,提高水平最好的辦法就是讓別人看你的代碼,讓別人評論你的代碼。這不應(yīng)該成為讓你尷尬的原因 -- 同時(shí),幾乎,所有開發(fā)者都明白,截止日期快要來的時(shí)候,項(xiàng)目里那些迫不得已的 hacky 代碼必定會缺乏可讀性和優(yōu)雅性。
我們的一些競爭對手在使用我們的代碼,因?yàn)樗麄兎答伭艘恍└倪M(jìn)給我們。我們也一樣。實(shí)際上,開源一個(gè)商業(yè)項(xiàng)目最大的挑戰(zhàn)在于管理。這種責(zé)任關(guān)系是處理人際關(guān)系最重要的部分,也是需要認(rèn)真處理好的 -- 特別是當(dāng)一個(gè)項(xiàng)目得到了足夠多的好名聲。大部分的項(xiàng)目都沒有得到足夠的管理,這使它們最終舉步維艱。
發(fā)布完代碼,將項(xiàng)目拋之腦外,并忽視開發(fā)者的反饋是一件很常見的事情,但是我們卻樂于接受開源項(xiàng)目的責(zé)任,并努力繼續(xù)把項(xiàng)目開源。
那些需要額外花費(fèi)我們時(shí)間來開發(fā)和維護(hù)的開源項(xiàng)目,經(jīng)常能幫助從日常的任務(wù)中解放出來,而且,通過 GitHub 進(jìn)行的交流也能夠幫到我們團(tuán)隊(duì)中遠(yuǎn)程工作的成員。
在一個(gè)擁抱開源的公司里作為一個(gè)小的團(tuán)隊(duì)而工作,可以讓那些由于開源而要承擔(dān)的各種風(fēng)險(xiǎn)微不足道。如果這種風(fēng)險(xiǎn)確實(shí)存在的話,技術(shù)好處,商業(yè)前景以及開源項(xiàng)目所帶來的樂趣要比它們大,并且大得多。
將一個(gè)庫開源和創(chuàng)建一個(gè)開源庫其實(shí)有著本質(zhì)上的不同 - 這種不同和從技術(shù)上開源還是從精神上開源是一樣的。一句話來說,回答這個(gè)問題就可以總結(jié)兩者的差異:
你是為了自己的利益而開源呢,還是為了所有人的利益?