故事要從兩年前說起,那時知乎調(diào)整了移動客戶端的發(fā)布流程,確立了每兩周一次的固定發(fā)版周期,這期間包含了需求產(chǎn)生、設(shè)計、開發(fā)、測試等一系列的流程。當(dāng)時業(yè)務(wù)發(fā)展的速度與現(xiàn)在相比并不快,整體的工作流都是圍繞著 Gitlab 、Jenkins 、Slack 等工具,即在 Jenkins 上打包和測試、在 Gitlab 上通過 MR 的方式管理代碼改動、通過 Slack 接收流程中的各項通知。
每個 MR 在創(chuàng)建或提交新代碼時都會自動觸發(fā) Jenkins 打包,MR 相關(guān)各角色可以方便地安裝這個包進行驗收和測試。在 Gitlab MR 中,我們設(shè)置了如下圖的一系列標(biāo)簽(Labels)用來標(biāo)記各角色的驗收結(jié)果,只有集齊這些標(biāo)簽的 MR 才能被合并,其中 Dev 、PM 、Design 、QA 標(biāo)簽分別代表開發(fā)自測通過、產(chǎn)品驗收通過、設(shè)計師驗收通過以及 QA 測試通過。
一個典型的知乎客戶端 MR
不過隨著知乎用戶量的快速增長,移動客戶端功能也越來越復(fù)雜,開發(fā)團隊也相應(yīng)擴大,與此同時在知乎客戶端的開發(fā)和測試過程中出現(xiàn)了如下問題:
總之,老的客戶端架構(gòu)和發(fā)布流程開發(fā)效率低、測試效率低、功能迭代慢,漸漸不再適應(yīng)業(yè)務(wù)的發(fā)展。于是在 2017 年底,知乎走上了移動客戶端組件化之路,對于組件化的一些概念,這里不再贅述。而組件化給我們帶來的新的挑戰(zhàn)是,如何在每次應(yīng)用迭代的過程中清晰地管理大量的組件信息、組件之間的依賴關(guān)系、應(yīng)用與組件之間的依賴關(guān)系,如何能快速獲取構(gòu)建結(jié)果,如何能在不同測試階段發(fā)現(xiàn) Bug 時快速定位到問題所在等等。
這些新的挑戰(zhàn)最終轉(zhuǎn)化成需求,造就了知乎移動端組件管理平臺 Athena 。將 Gitlab 、Jenkins 在日常迭代中的工作流的作用弱化,取而代之的是一個集成式一體化的平臺,無論是產(chǎn)品、設(shè)計、開發(fā)、測試,在這個平臺上可以很清晰的查看操作所需的組件或應(yīng)用資源,節(jié)省在各個工具之間上下文切換帶來的低效能,以及團隊內(nèi)部溝通的成本。工具的平臺化同時也代表著工作流程的規(guī)范統(tǒng)一,通過使用平臺的權(quán)限控制,使得移動端發(fā)版工作流程更加明確統(tǒng)一。對于新入職的員工,無需再花費大量時間理解消化復(fù)雜的流程,只需要按照平臺的使用說明,即可快速上手工作。
多說一句,我們使用 Athena 命名平臺,正是因為 Athena (希臘神話中的女神) 主司智慧和公正。我們希望 Athena 的誕生能減輕工程師在移動端開發(fā)流程中的心智負擔(dān),并公正客觀的實現(xiàn)統(tǒng)一有效的流程規(guī)范。
知乎移動客戶端組件管理平臺 Athena 是基于 B/S 的架構(gòu),采用前后端分離的策略,前端主要專注于友好的交互和清晰的資源展示,后端則主要負責(zé)資源的業(yè)務(wù)邏輯處理以及與其他工具的交互。
關(guān)于前端選型,我們使用了當(dāng)前趨勢迅猛的前端框架 Vue 以及官方推出的一系列生態(tài)圈產(chǎn)品 Vue Router, Vuex 來搭建。Vue 是一款漸進式的前端框架,這對于平時主要工作集中在后端項目的工程師相對比較友好,學(xué)習(xí)曲線沒有 React 陡峭,其提供了豐富的 API 供用戶使用,同時官方的腳手架工具 Vue CLI 可供用戶快速搭建應(yīng)用。
關(guān)于后端技術(shù)選型,我們選用知乎自研的基于 tornado 的定制 Restful API 框架來搭建,選用 MySQL 負責(zé)數(shù)據(jù)存儲,同時使用知乎自研的部署發(fā)布引擎來執(zhí)行平臺的部署發(fā)布。
同時,Athena 希望在工作流中將 Gitlab 和 Jenkins 弱化,因此我們對二者的常用 API 進行了封裝供 Athena 調(diào)用,用戶只需要在 Athena 上進行操作即可,由 Athena 觸發(fā) Gitlab 和 Jenkins 完成各項任務(wù)。另外,用戶在 Athena 上的任何操作都會使其在 Slack 上收到即時通知。
作為移動客戶端的組件管理平臺,Athena 的主要功能表現(xiàn)為以下兩點:
組件接入 Athena 的前提是擁有自己獨立的 Gitlab 代碼倉庫,且目錄結(jié)構(gòu)符合知乎客戶端組件規(guī)范。目前 Athena 需要人工錄入組件,用戶使用「添加組件」的功能將組件接入至 Athena 平臺后,Athena 會自動為該組件代碼倉庫添加 Webhook 用以監(jiān)聽代碼倉庫中的變更。
同時可以看到,當(dāng)用戶在平臺添加組件的時候,我們設(shè)計了一些組件維度上的權(quán)限管理。只有組件的負責(zé)人擁有平臺上組件的所有操作權(quán)限,并且組件的負責(zé)人可以自定義配置組件驗收過程中所需的角色標(biāo)簽 (包括 Dev 、 PM 、Design 、 QA ),配置好的角色會在組件驗收流程中做相應(yīng)的驗收工作。這里的標(biāo)簽與上述 Gitlab MR 中的標(biāo)簽功能一致,有了這些標(biāo)簽,我們便可以將各角色的驗收工作從 Gitlab 遷移到 Athena ,從而達到弱化 Gitlab 在流程中作用的目的。任一角色未通過驗收,該組件版本就不能作為集成候選版本。這樣我們統(tǒng)一了各組件的集成規(guī)范,與此同時也給予用戶一定程度的自由。
每當(dāng)組件負責(zé)人在代碼倉庫中修改了組件的版本號 ,代碼倉庫的 Webhook 將會被觸發(fā)從而去調(diào)用 Athena 的接口,Athena 則會為以 Gitlab Tag 的形式為該組件創(chuàng)建一個新的版本。同時 Athena 還會自動發(fā)布組件新版本的 aar(Andoid 組件)或 Framework(iOS 組件)。用戶可在 Athena 平臺上瀏覽組件的新版本以及此次組件更新的內(nèi)容。
組件發(fā)布流程
組件集成是指將知乎主 App 依賴的組件升級到新的版本,在組件化之后,我們用組件集成來代替原流程中的 MR 。用戶在 Athena 上選擇組件的新版本并構(gòu)建集成包來驗收,打包也是由 Athena 觸發(fā) Jenkins 來完成的。各業(yè)務(wù)團隊各自在上文提到的組件配置中決定集成驗收參與的角色,所有角色驗收通過后,QA 便可以在 Athena 平臺上將主 App 所依賴的組件升級到指定的版本。
組件集成流程
如下圖所示,用戶在指定的主 App 版本上可以找到對應(yīng)組件的各個版本,對指定的版本構(gòu)建集成測試包,如果此版本通過了驗收,則可以集成至相應(yīng)的主 APP 版本中。
組件各版本列表
基于指定組件版本打集成測試包
如此一來,凡是接入到 Athena 平臺上的組件都拋棄了原始的散養(yǎng)式的管理,而遵循一套統(tǒng)一,清晰且高效的迭代流程。組件發(fā)布流程獨立且快速,業(yè)務(wù)團隊內(nèi)部不同職能的員工溝通成本降低,工作效率提升。為今后移動端更加快速的發(fā)版奠定了基礎(chǔ)。
自從 Athena 平臺上線半年多來,已經(jīng)經(jīng)歷知乎移動端發(fā)版 30+ 次,在此期間 Athena 已經(jīng):
同時客戶端的迭代流程也越來越穩(wěn)定,Athena 持續(xù)為提升知乎移動端質(zhì)量與發(fā)布速度保駕護航。
我們當(dāng)然不會滿足于現(xiàn)狀,Athena 女神的智慧也絕不僅限于此,我們計劃在后續(xù)的工作中賦予她更多的使命:
Athena 依賴 Jenkins 來實現(xiàn)構(gòu)建任務(wù)的管理以及分配,維護 Athena 的同時,我們還需要維護 Jenkins 上的配置。這樣造成了維護和使用成本的上升,我們希望未來 Athena 可以完全摒棄 Jenkins 來實現(xiàn)構(gòu)建的分配和執(zhí)行。
目前組件的測試自動化程度還不高,同時 Athena 對自動化測試的支持也并不好,未來我們會使 Athena 接入更多自動化測試,真正實現(xiàn)組件的持續(xù)集成和持續(xù)發(fā)布,提供更全面的質(zhì)量保障。
質(zhì)量數(shù)據(jù)的重要性不必多說,我們希望能夠?qū)⒌鞒讨懈鱾€環(huán)節(jié)的數(shù)據(jù)收集分析(靜態(tài)代碼掃描、單元測試、包大小檢查等),作為組件持續(xù)集成流程的準入規(guī)則,形成一套更加智能完善的閉環(huán)系統(tǒng)。
作者:鐘離無糖
出處:https://zhuanlan.zhihu.com/p/46411733
知道差友們有沒有發(fā)現(xiàn),現(xiàn)在幾乎每家廠商都喜歡把各種功能塞進一個 App 里,妄圖只用一個軟件就能滿足我們所有的需求。
比如原本一個清爽的瀏覽器,可能某天突然就多了小說和短視頻等功能;一個好用的聊天軟件,也許某天突然就搞起了直播和購物等活動。。。
一個軟件的功能可以 “ 豐富 ” 到讓你意想不到。
自此軟件越更新安裝包越大,無用的功能和廣告也是越來越多,有些應(yīng)用甚至堪比南孚電池,一個軟件的功能更比六個雜,不怕難用就怕人有我無。
相比官方客戶端需要通過在軟件中加入廣告、吸引用戶開通會員等手段來實現(xiàn)商業(yè)化。
那些借助接口開發(fā)而來的第三方客戶端顯然就沒那么大壓力,所以往往能夠做到簡潔與實用兼得。
也正因如此,世超之前給差友們推薦過好幾款軟件的第三方客戶端。
而今天呢,世超要來跟大家分享一款號稱是東半球最好的第三方知乎客戶端——知否,有了它,或許可以還你一個最初認識的知乎。
很多老知乎用戶應(yīng)該都知道,知乎剛開始是沒有廣告的,就是一個純粹的知識問答社區(qū)。
后來也是為了盈利,知乎相繼推出了付費問答 “ 值乎 ” 以及付費課程 “ 知乎 live ”,接著又開始在信息流中插入廣告,并且上線了鹽選會員等各種業(yè)務(wù)。
以至于差友們平時在刷知乎的時候,總能看到各種各樣官方或者非官方的推廣,又或者是不小心點進了其它界面,使用過程中難免會影響體驗。
知否和其它第三方客戶端一樣,刪繁留簡,去除了知乎官方客戶端的很多拓展功能。
首先是取消了包括推薦、讀書會、雜志、專欄和 Live 講座在內(nèi)的一系列會員界面,只在 App 中保留了搜索、關(guān)注、推薦及熱榜等基礎(chǔ)功能。
這就使得整個 App 只有 2.9MB,比一張高清圖片的容量還要小,大小僅為官方的 1/17。
而且不像官方客戶端打開 App 會出現(xiàn)彈窗、瀏覽問題會出現(xiàn)廣告、看回答底部評論偶爾也會出現(xiàn)廣告,甚至消息里也時不時收到官方賬號的推薦。
知否不僅不需要任何亂七八糟的權(quán)限,也沒有任何干擾廣告的存在,無論是關(guān)注、熱榜還是推薦界面都是再清爽干凈不過。
如果差友們把這兩個 App 放在一起仔細對比一番,還會發(fā)現(xiàn)知否把問題下面的回答切換回了以前的左右滑動,而不是像現(xiàn)在這樣的上下翻頁。
左右翻頁的好處顯而易見,差友們在手機屏幕的任何位置都能直接翻看針對當(dāng)前問題的上一條和下一條回答。
而官方客戶端則只給你提供了切換下一條回答的按鈕,中途想要退回到上一條回答只能手動刷回,遇到特別長的回答切換起來就賊雞兒難受。。。
當(dāng)然,由于知否是第三方客戶端,它相比起官方客戶端也不可避免的存在一些不足之處。
比如知否 App 中沒有作答功能,差友們只能圍觀別人的回答,自然也沒了瀉藥( 謝邀 )的機會。
想要關(guān)注其它問題及用戶、給回答點贊或者查看私信也是不行的,作為知否用戶的我們更像是知乎小透明般的存在,只能對回答進行評論和分享。
從前面這些閹割功能中差友也能體會得出來,這款軟件并不是適合所有人使用,它對萬年潛水黨來說可能更友好,刷完即走,不必留下任何痕跡。
而那些重度活躍者,世超還是建議他們繼續(xù)使用原來的知乎客戶端,看著自己的回答和評論受到網(wǎng)友們的認同,對別人有所幫助,也是一種樂趣。
不管怎樣,知否可能是目前你能用到的最簡潔的第三方知乎客戶端了,在開發(fā)者的悉心維護下,軟件更新升級后每次都在變得更好用。
這么干凈的第三方知乎客戶端,大家且用且珍惜。
知乎 iOS 客戶端從一開始圍繞問答社區(qū)到目前涵蓋 Feed,會員,商業(yè),文章,想法等多個業(yè)務(wù)線的綜合內(nèi)容生產(chǎn)與消費平臺。項目的復(fù)雜程度已經(jīng)在超級 App 的范疇。單周發(fā)布與業(yè)務(wù)并行開發(fā)也逐漸變成主流。同時在知乎 iOS 平臺,技術(shù)選型一直也都比較開(sui)放(yi)。較早了引入了 Swift 進行業(yè)務(wù)開發(fā),列表引入了需要 OC++ 的 ComponentKit 作為核心引擎。所以在這種多業(yè)務(wù)方團隊,技術(shù)形態(tài)復(fù)雜,組件倉庫數(shù)量多等場景下,也同樣遇到了各種超級 App 團隊都面臨的一些問題。
問題如下:
當(dāng)然在思考解決上面這些問題前,知乎 iOS 項目也同樣經(jīng)歷過組件化的工作。與眾多組件化拆分方案殊途同歸,進行了業(yè)務(wù)劃分,主倉庫代碼清空,業(yè)務(wù)線及 SDK 進行獨立倉庫管理。引入基于路由,基于協(xié)議聲明的組件間通信等機制等,這里就不多贅述了。
核心介紹的項目名稱為 Venom,靈感來源于電影《毒液》。Venom 的用戶端是一款為開發(fā)人員打造 Mac App,應(yīng)用內(nèi)置了工程構(gòu)建需要的全套 Ruby Gem 和 Cocoapods 等其相關(guān)構(gòu)建環(huán)境。核心目標(biāo)是解決工程構(gòu)建,二進制構(gòu)建,組件管理,調(diào)試工具等一系列開發(fā)過程中的繁瑣耗時任務(wù)。
所以當(dāng)一臺全新的 Mac 電腦希望運行工程時, 只需要 3 步:
從此告別 ruby,cocoapods 版本不對,gem 問題,bundle 問題以及權(quán)限問題等困擾。因為構(gòu)建環(huán)境內(nèi)置,使得構(gòu)建環(huán)境與工程師本地環(huán)境隔離,極大的降低了工程 setup 的成本。
完整的 Venom 包含了 3 個部分:
下面會著重介紹客戶端和內(nèi)核相關(guān)的技術(shù)方案,數(shù)據(jù)服務(wù)目前僅為組件的附加信息提供 API 支持。
在引入 Venom 前,一直使用 Cocoapods 的 Podfile 進行組件的引用。但如果希望對 pod 命令的 DSL 進行擴展,發(fā)現(xiàn)是不夠方便的。索性在 Cocoapods 上層建立自己的組件描述文件,每一個描述文件最終都會被轉(zhuǎn)化為一次 podfile 的 pod 調(diào)用。
如上圖,使用 Venom 方式集成的項目,由在 VenomFiles 目錄內(nèi)的組建描述文件組成。
VenomFile.new do |v|
v.name='XXModuleA'
v.git='git@git.abc.abc.com:Team-iOS-Module/XXModule.git'
v.tag='1.0.0'
v.binary=false
v.use_module_map=true
v.XX...
end
組件描述文件可以理解是 pod 命令的一個超集,在包含了 pod 的原有功能基礎(chǔ)上,擴展其他功能(膠水代碼創(chuàng)建,二進制化與源碼切換等)。
同時在與 VenomFile 同級別還設(shè)計了一個 Customization.yml 的文件。當(dāng)開發(fā)過程中,需要對某個組件進行源碼二進制的切換,或者源碼路徑的切換,版本引用的切換等,不會直接改動 VenomFile,會改動 Customization.yml 來進行。在構(gòu)建過程中的優(yōu)先,Customization.yml > Venomfile 。為了每個工程師的改動不會互相影響,Customization.yml 是非 git 托管的。而 VenomFiles 內(nèi)的文件只有更新版本號或其他配置改動,才會更新。
所有組件都通過一個個 Venomfile 文件方式管理在主工程倉庫中,通過目錄對組件進行層級劃分管理。
原來的 Podfile 文件通過嵌入 Venom 進行構(gòu)建職責(zé)的接管。
使用 Venom 后 pod install 的實際過程就如下圖:
整體上來看, Venom 內(nèi)核提供了一套擴展 pod 屬性的描述文件,開發(fā)階段通過 customization.yml 進行可配置的構(gòu)建。構(gòu)建過程中,依賴 Venomfile 文件的唯一標(biāo)識進行二進制庫和源碼的關(guān)聯(lián)。通過對 Cocoapods 構(gòu)建過程的 hook 實現(xiàn)二進制與源碼的引用切換。二進制化方案可參考 :
Xinyu Zhao:知乎 iOS 基于 CocoaPods 實現(xiàn)的二進制化方案40 贊同 · 15 評論文章
Venom 內(nèi)核除了主要的構(gòu)建職責(zé),還提供了一系列的 ipc 命令。通過這些 ipc 命令,上層的 Venom 客戶端就可以更容易的操作每個組件,進行定制化的開發(fā)組織。來構(gòu)建工程。
例如:
// 修改組件二進制使用方式,使用二進制
venom ipc customization \
--path /Users/abc/Developer/zhihu/abc/def \
--edit \
--name ZHModuleABC \
--binary
// 修改組件二進制使用方式,使用源碼
venom ipc customization \
--path /Users/abc/Developer/zhihu/abc/def \
--edit \
--name ZHModuleABC \
--source
// 修改 yml 文件中指定組件的路徑
venom ipc customization \
--path /Users/abc/Developer/zhihu/abc/def \
--edit \
--name ZHModuleABC \
--pod_path /path/to/ZHModuleABC
// reset 某個組件在 customization 中的 change,不指定 name 參數(shù)會給整個文件置成空
venom ipc customization \
--path /xxx \
--reset \
--name ZHModuleABC
通過對 Venom 內(nèi)核的簡單介紹,其實可以認為,只通過命令行版的工具,就可以達到用到的大部分功能。但因為實際開發(fā)情況一般不會一個人一次只處理一個模塊,所以希望以一種所見即所得方式來讓業(yè)務(wù)工程師不用關(guān)心下層的邏輯,學(xué)習(xí)命令??梢钥焖俳⑵痖_發(fā)環(huán)境是我們的主要目標(biāo)。
客戶端主要模塊
Venom App 內(nèi)置了全套的 guby gem 環(huán)境來運行命令。通過 CLITask 來訪問 Venom-core 以及 git 等其他命令(venom 內(nèi)核一樣內(nèi)置在 Venom App 內(nèi))。
這樣很好的控制了執(zhí)行命令的環(huán)境,特別是對新入職的員工是十分友好的。
開發(fā)組件關(guān)聯(lián)
正常情況下 clone 下來的主工程(殼工程)內(nèi)是沒有代碼的,只有空的工程文件和組件描述文件。Venom 工具劃分了2個區(qū)域,普通組件和定制組件。
因為每個開發(fā)者維護的組件其實是有限的幾個,一般都會將源碼放在固定目錄,所以通過設(shè)置客戶端的自動掃描路徑。在 Venom 界面上,如果在掃碼路徑下發(fā)現(xiàn)了相關(guān)組件,則可以一鍵關(guān)聯(lián)本地目錄組件,這樣組件會切換到定制組件的模式進行開發(fā)。
特定版本關(guān)聯(lián)
在開發(fā)過程中,有時需要對某一個依賴庫的特定版本進行調(diào)試或連調(diào)。所以也支持通過 tag,commit,branch 等方式,進行特定源碼的切換和關(guān)聯(lián)。
源碼與二進制切換
某些特殊場景下,可能希望工程以所有組件都是源代碼方式構(gòu)建,排查問題。那么也可以通過 2 種不同的構(gòu)建模式一鍵切換。(當(dāng)然全源碼構(gòu)建一次需要十足的耐心)
二進制模式下搜索與調(diào)試
二進制化后,大部分情況下都工作在二進制模式下,但有時在進行源碼搜索時,希望可以全局搜索。所以在構(gòu)建過程中,會把當(dāng)前版本的源碼目錄也引用到工程目錄下。
所以在工程進行檢索代碼時,是完全沒問題的。有了源碼,在云端進行二進制打包時,通過 fdebug-prefix-map (Clang command line argument reference )這個參數(shù)重新在二進制文件中改寫 Debug 模式的源代碼路徑。這樣即使在二進制模式下,也可以直接關(guān)聯(lián)源碼進行斷點調(diào)試。
組件依賴關(guān)系分析
當(dāng)組件很多后,就會出現(xiàn)一些工程師對組件所處層級不夠了解,導(dǎo)致出現(xiàn)依賴混亂的問題。所以在構(gòu)建結(jié)束后會通過對組件層級的檢查,進行組件依賴層級的判斷。
在推進所有工程師使用 Venom 客戶端后,相當(dāng)于在開發(fā)環(huán)節(jié)有了一個強有力的抓手。由于 App 的自動更新功能,可以在平臺下提供給開發(fā)者更多的工具,而開發(fā)者只需要更新客戶端使用。通過工具化客戶端的開發(fā),我們重構(gòu)了原有散落在各處的腳步,工具集中整合在一起。使得開發(fā)工具維護更統(tǒng)一,更新也更及時,開發(fā)人員上手成本也更低。
Venom 核心承擔(dān)的是開發(fā)環(huán)境管理,工程組織與構(gòu)建管理,提高工程效率工作。但上線后,我們還陸續(xù)在此基礎(chǔ)上提供了一些其他功能。
作者:付三歲
出處:https://zhuanlan.zhihu.com/p/69526642