接手一個負分的 iOS 項目後我做了什麼
半年前我加入一個剛剛拿到 A 輪資金的創業團隊負責 iOS 項目。早期的時候公司生死未卜,只追求快速迭代找到一個正確的方向。這種早期默默無聞的團隊也沒什麼工程追求,就是寫的快就好了。但是確定方向後要長期發展,就不能再野蠻生長了。
基於過去半年我在這個項目里的實踐經驗,和大家分享一下。
代碼託管:自建 Gitlab
早期草根團隊最省事的就是用 GitHub 了。但是團隊人數增加後用 GitHub 的成本就很高了。普通的團隊套餐每個月每人 9 刀。另外一個問題就是 GitHub 部署在國外,國內訪問網路時常不穩定。聽聞某跨國團隊代碼託管在 GitHub 上,某次重要會議期間 GitHub 無法正常訪問。真是突如其來的父愛如山。另外一個缺點就是服務端如果要自己配置 CI 服務不太方便。如果部署在自己的伺服器上,其他一些服務腳本也部署在一起,會有很大的自主權。綜合之後選擇了主流的 Gitlab。
工程師的時間比機器貴
很多短視的團隊覺得配給工程師的設備太貴,挑個便宜點的就好了。一台好的電腦雖然貴點,可是長期下來節省下來的工程師的編譯時間比機器貴多了。在設備上我跟公司建議那就配最新的 15 寸的 rmbp 唄,再來一個 dell 4K 顯示器唄。後面發現鍵盤滑鼠也重要啊,每個人又補貼了 500 塊的鍵鼠額度。看到很多工程師還在用 air 開發,還有 mac mini 的。真的為這種傻逼公司感到心痛。我曾經在的某團隊還是 4 個終端用同一台電腦。每次編譯的時候我就到南京路散個步。如果晚上要上線,可以去看個電影回來。
儘早招人
招人是團隊發展過程中非常重要的一環。很多早期團隊都低估了招人的難度和周期。因為不太知名的團隊招人有兩個缺點:
不能給出太高的薪水
優秀的人才當然會比較市場上薪水。已經成名已久的 BAT 這種公司自然會有薪水的優勢。創業公司雖然有期權,但是畢竟公司前途未卜。很多工程師也擔心公司會不會過陣子就倒閉的問題。
團隊事情多且雜
項目成熟後的迭代大多是按部就班,有穩定的節奏。每個環節的都有很細分的專職人員。早期的項目因為項目還是處於成長階段,很可能半路做著看到直播火了,我們加個直播的需求。或者做著做著發現競品有個功能,管不了那麼多我們下個版本就上。或者 CEO 路過的時候突然有了個想法,上線的時間又推後一下。
招人除了技術的硬指標,在早期團隊還有一個工程團隊文化的問題。一個幾十個人的項目,裡面某個特定的人的積極性對於項目其實是不太重要的。他只要完成應該完成的工作。甚至和其他人不說話也影響不大。一個大的項目也不能因為任何一個人不在了就運行不下去。
但是早期團隊,人就這麼幾個。有一個人對團隊的使命認知不一致,日常行為里就會有很多摩擦。
我之前思考過團隊文化是什麼,怎麼形容團隊文化。後來看到一個說法感覺挺貼切。文化是空氣,無處不在。公司沒有規定下班後社交平台上看到用戶反饋需要你去回應,也不會規定你發現其他部門的產品有問題是不當回事還是應該去和其他部門的人溝通,又或者看到一個更好的建議是不是要和公司提出來。這些行為背後的支撐就是團隊文化。在團隊里的人決定了價值觀。
綜合上面說的,招到一個匹配的技術人員,運氣好的話幾天就你能遇到,更常見的情況是可能要好幾周的時間。當然如果情急之下招進來一個人,幹了幾個月後發現不合適就走了,對於團隊的士氣損害也挺大的。
所以考慮到項目未來的進展,要及時啟動招人的計劃。當你發現進度忙不過來的時候開始招人,這個時候你要抽時間去準備面試的事情,還要兼顧項目進度,會很焦頭爛額。
轉型 Swift
團隊里的另外 3 個同事之前都沒有寫 Swift 的經驗。但是考慮到未來的發展趨勢,並且我們的業務類型對動態化的要求沒那麼強。我堅持在團隊里推行使用 Swift 編程。
我經常被問到的一個問題是你想用 Swift 但是團隊里其他人不會用,會不會給項目推進帶來困難。其實如果團隊里有人正確的引導,幫他們解決上手過程中的問題,再給一段時間過渡。很快他們就會退不回去。
下面介紹一下我把從 OC 遷移到 Swift 的過程。
先用 Swift 寫好網路層的庫。借著把常用的幾個 OC Model 和 Swift 對象做好橋接。類似下面這樣:
class SwiftUser {
init(ocUser: OCUser) {
}
func convertOCUser() {
}
}
這樣改造之後如果一個新的模塊就可以完全用 Swift 編寫。一開始肯定是用 OC 的思維寫 Swift 的代碼。但是在熟悉了 Swift 語法後可以慢慢在 review 過程中提出可以用更 Swift 的寫法。有些功能需要 OC 和 Swift 互相調用確實挺麻煩。如果讓一個沒 Swift 經驗的上手就解決這些問題一定很氣餒。所以在項目過程中也要分配一定時間把老的 OC 代碼重寫了。好在原先的代碼本來就很亂,需要重寫。這樣就隨著業務推進中,Swift 比例越來越高。
這樣經過一兩個月後大家就慢慢熟悉了 Swift ,此時再去推進 RxSwift 等框架的使用。
理順開發工作流
項目早期的時候需求千千萬,一個迭代版本中應該開發多少功能呢?產品經理本能的就是靠拍腦袋。列了一頁需求後表示這就是這個版本了。程序員都傾向於樂觀估時間,做著做著半個月過去了。下個迭代的需求、UI 設計,交付前測試的工作都很混亂。
後來經過討論確定了兩周一個迭代周期。開發過程中發現某個需求這個迭代里無法完成就挪到了下個迭代中。每個周期階段要做什麼大家都很明確。兩周左右發布參考用戶反饋也是一個比較好的節奏。
這裡要強調的是開發過程前期的準備工作。主要指需求和 UI 圖。大多數的需求設計都是圍繞某個需求展開,但是這個需求要融入到現有體系里是有很多周邊的工作要做的。比如產品提出用戶資料里應該可以打標籤。於是畫了一個草圖裡有標籤。對於他可能這個需求描述的很明確了,但是真正落地的時候就有其他工作要做。比如標籤怎麼刪除?標籤有字數限制嗎?標籤重複了怎麼辦?這些問題如果前期設計的時候產品沒有表達清楚,就只能在開發的過程中來回溝通。有一個經驗豐富的開發者在前期就參與需求的討論,和提出問題對於在後期開發有很大的幫助。
不用 Sketch 的設計師不是好設計師
我看到很多設計師沿用傳統,一直使用 PS 。然而實際上業界使用矢量設計工具 Skecth 已經很普遍了。現在手機的屏幕尺寸更異,如果設計的時候不是矢量圖,而是點陣圖,做響應式的布局設計就會很不方便。實際上移動的 UI 設計如果用慣 Sketch ,絕對是生產力的極大提升。
但是和大多數人一樣,很多設計師都會覺得 PS 用的也挺順手的,Sketch 沒用過。其實 leader 是有義務去推動一些人,讓美好發生。
之前我在的團隊我就一直不斷暗示不厲害的設計師才用 PS ,後來刺激了幾周後他說他現在也可以用 Sketch ,後來慢慢項目 symbol 都湊齊了 PS 他也退不回去了。
當然也有非常老派的設計師,這種只能給他壓力讓他去被動改變。當時我們團隊有一個四十多高齡設計師,我們也很為難。我當時想那算了,下個月如果你不能用 Sketch 出圖就自己準備換個工作吧。當然作為一個團隊也不能給個指示就甩手不管了。中間已經熟練使用 Sketch 的設計師會特別關注他的學習狀態,及時指導。最後也得到了一個好的結果,他在被迫改變後發現 Sketch 確實更好用。
這裡還有安利一個很好用的輸出設計圖的軟體:zeplin。設計圖直接採用標註的方式會很死板。程序員在查看過程中可以自己查看到設計圖的所有源信息效率會得到極大的提升。
接入 CI
很多團隊改變代碼里的宏來區別 app 里的環境,每次提交前改下宏。常在河邊走,哪能不濕鞋。我還真遇到過提交 App Store 的時候,有人忘記改環境的宏,app 連接到的是測試環境。這裡想說的不是發布前要仔細檢查,而是這種情況就不應該發生。
實際上通過 Xcode 打包手動提交也是一個充滿風險的過程。因為不時會出現本地改了幾行代碼,提交的時候把本地的代碼也提交了。帶來了未知的風險。
我通過配置 Xcode 里的 scheme、target 來區分環境。利用 fastlane 來完成自動打包上傳的工作。結合 Gitlab 的 CI ,配置了 Gitlab runner,從此打包只需要點擊一下按鈕。降低了發布的人工操作風險。
我們的組件是用 cocoapods 管理依賴的。配置了 Gitlab runner 後,組件的版本更新也放在遠端工作,不再基於本地。配置了 webhook 後,每次 job 完成後 slack 的 channel 里大家都會收到消息。
用好 Testflight,注重 beta 反饋
早期業務變化頻繁,沒有自動化測試,只能靠人工測試保證穩定。一開始團隊選擇了發布企業版的包來測試。當然企業版用戶可以方便的下載安裝,但是也有不少缺點。最大的缺點就是這個包和 App Store 的包是兩個包,不一樣的 bundle id 。會導致一些跟包綁定的功能無法正常測試,比如微信登錄、支付後的跳轉。
我們的業務里有聊天的功能,聊天記錄是只存在本地的。而且我們認為一個賬號只能在同一個平台上的一台設備登錄。這就導致用戶測試的時候賬號會從 App Store 版本登出,這樣聊天記錄就沒了。熱心用戶願意試用我們的 beta 版,但是也承擔了不該有的代價。基於這點考慮在我的主導下我們放棄了發布企業版的包測試的方式。而是改用利用 testflight 測試。
Testflight 有個較大的使用門檻,需要收集用戶的郵箱,之後在 testflight 里輸入蘋果發出的邀請碼才能開始測試。很多用戶嫌麻煩就退出了,運營認為這樣會給測試帶來很大的不便。但是冷靜了心態後其實事情並沒有那麼糟糕。真正對這個產品有興趣的用戶不會因為要填個郵箱就放棄了。那些流失的只是普通的用戶。用戶使用了 Testflight 後,後續的測試包的發布也會收到更新。不會像企業版那樣,只能手動的告訴用戶我們有新的測試包。當 beta 測試活躍用戶超過 100 個會有一個質變。這些都是積極的重度用戶,一群重度用戶使用你的新版本幾天,至少可以保證核心業務邏輯是沒有紕漏的。
之前有人問過我們使用 Swift ,線上出嚴重 bug 時沒法動態修復,會不會帶來很多問題。實際上因為有這樣一環 beta 測試環節,很少出現嚴重的事故了。有一次意外是我們的 Swift 版本升級到 4.0 的時候,一個枚舉居然對 iOS 8 設備不兼容(Xcode 並沒有提示我們,蘋果的鍋)。那個版本也恰好是支持 iOS 8 的最後一個版本。我們的測試用戶里剛好沒有使用 iOS 8 系統的。
Beta 測試的時候可以讓用戶及時的反饋問題也是很重要的。如果我跟你反饋一個問題,又要看 app 版本,又要說在哪個頁面,還要說一下我的 userID。用戶的脾氣也是夠好的。我們在 app 集成了搖一搖反饋 bug 的功能,操作步驟,網路請求,設備信息等這些有效的信息都會一起收集起來。在後台可以方便的看到。告訴用戶碰到問題搖一搖,描述一下問題就可以了。用戶反饋後我們會收到郵件,及時的反饋用戶用戶也很有參與感。
搖一搖的功能並沒有對所有用戶開放,只是針對某些特定我們能聯繫到的用戶開放。畢竟每一個反饋工程師都需要跟進,如果面向所有用戶開放,我們會收到太多無效信息。常看到工程師討論這些開發者功能的入口要藏在哪裡,有的說在某個文本框輸入特定字元,有的說在某個角落裡點幾下什麼的。開發者面板的入口我選擇配置在 universal link 里。這樣用戶不會在 app 里任何一個地方誤觸到達,只能通過我們告訴他的鏈接通過跳轉到達。
堅持 Code Review,增強技術交流
Code review 是一件神奇的事情。所有有素養的工程師都覺得 code review 好,據我們所知國外很多優秀的 IT 企業都很注重 code review,但是在國內卻很少看到有團隊執行 code review。或者中小團隊里很少看到 code review。
但是我很看重 code review,從情懷的角度講,這裡面是工程師技藝的一種傳承。一個方法名起的不好,從公司角度來看,這個項目一樣會 work 。但是從工程師角度來說,如果有能力,為什麼不幫助那些剛開始寫代碼的人一些指引呢?
作為一個 leader,在 review 的時候幫助成員成長,和只是看下代碼是不是能完成功能最後會引向不同的結果。看過一句很有觸動的話,現在很多 leader 知道自己的工作里需要管理其他人,但是卻忽略了還需要 lead 。
老實說推進 code review 確實遇到很多阻力。有團隊里的也有團隊外的。團隊外的看法是 code review 拖慢了項目進度。我作為一個核心的開發成員,每天超過 20% 的時間是沒有可見的工作產出的。有時別人寫的有問題被我打回去改,一個已經完成的功能又多花了幾個小時。團隊內遇到的問題是,很多成員不理解這項工作背後的價值。很容易就覺得我早上沒有推進項目進度,只是在坐在那裡不知道在看什麼。覺得我 commit 的代碼不多。最後我獲得了團隊「代碼最少產出」獎。
對於我個人而言,其實不搞 review 我肯定更輕鬆。這個功能我肯定能把控所有細節,這樣寫只是不好而已,也不是不能用。我也大可以不對他們解釋為什麼這樣寫是不好的。只要讓他們按照我的 comment 改就可以了。
但是吃力不討好的堅持是為了什麼?
我剛工作的時候,出去旅遊路上遇到一個大學教授。閑聊起來我說我請教你一個問題,中國古代的鞋子,會把花綉在鞋底。鞋底其他人又看不到,這樣做的意義是什麼。他回答說,我們做事不是做給別人看的,最後還是要過自己心裡這一關。花綉在鞋底,別人看不到,你自己知道。
one more thing
TAG:Cocoa開發者社區 |