1、CodeReview
Code Review 中文應該譯作 “代碼審查” 或是 “代碼評審”,這是一個流程,當開發人員寫好代碼后,需要讓別人來 review 一下他的代碼,這是一種有效查找系統缺陷的方法。由此,我們可以審查代碼的風格、邏輯、思路 。。。。。。,找出問題,以及改進代碼,保證軟件總體質量和提升開發者自身水平。因為這是代碼剛剛出爐的時候,所以,這也是代碼重構,代碼調整,代碼修改的最佳時候。所以,Code Review 是編碼實現中最最重要的一個環節。
代碼評審通常有兩種類型:正式代碼評審(formal code review),輕量級代碼評審(light code review)。
1.1 為什么要進行代碼評審
a、可以通過大家的建議增進代碼的質量。
b、是一個傳遞知識的手段,可以讓其它并不熟悉代碼的人知道作者的意圖和想法,從而可以在以后輕松維護代碼。
c、鼓勵程序員們相互學習對方的長處和優點,提高團隊整體水平。
d、可以被用來確認自己的設計和實現是一個清楚和簡單的。對開發人員來說也是一次開發思想重新重構的過程,可以更好的理解系統。
1.2 代碼評審的方式和時間
a、
由作者啟動評審,展示評審文檔(over-the shoulder)。它的優點是開發團隊內部可以快速進行評審交流,對于項目架構,后期可擴展性,可維護性等可以啟用這樣的評審,通過啟動這樣的評審,一方面評審者可以學習作者的架構思想,另一方面也可以團隊內部討論架構上的不足加以改進。
b、
組織評審會議(review meeting),由團隊成員輪流選出自己的評審作品共其它評審者學習。可以在項目結束后進行,通過這種敦促的方式共享好的東西讓整體團隊一起進步。
c、利用評審工具(tool assited code review)。
1.3 代碼評審的層級
a、實現正確性:主要包括是否實現預期功能,是否存在 bug,是否存在性能問題等。
b、設計合理性:主要包括實現方法,數據接口,設計模式,擴展性等,是否存在大量重復代碼和其它組件是否有重復代碼,包括結構設計是否合理,是否存在性能問題等。
c、代碼可讀性:主要包括代碼風格,美觀性。
實現正確性和設計合理性是必須要進行的 code review。對于代碼可讀性,由于每個人的編碼風格不一樣,建議做最低級別的 review,比如注釋。
1.4 使用代碼評審的注意點
a、Code reviews 不應該承擔發現代碼錯誤的職責。Code Review 主要是審核代碼的質量,如可讀性,可維護性,以及程序的邏輯和對需求和設計的實現。代碼中的 bug 和錯誤應該由單元測試,功能測試,性能測試,回歸測試來保證的(其中主要是單元測試,因為那是最接近 Bug,也是 Bug 沒有擴散的地方)。
b、Code reviews 不應該成為保證代碼風格和編碼標準的手段。編碼風格和代碼規范都屬于死的東西,每個程序員在把自己的代碼提交團隊 Review 的時候,代碼就應該是符合規范的,這是默認值,屬于每個人自己的事情,不應該交由團隊來完成,否則只會浪費大家本來就不夠的時間。個人認為 “meeting” 是奢侈的,因為那需要大家在同一時刻都擠出時間,所以應該用在最需要的地方。代碼規范比起程序的邏輯和對需求設計的實現來說,太不值得讓大家都來了。
10 年前,上面這兩件事會是理所當然的(10 年前的中國的軟件開發還沒有 Code Reivew 呢),今天,在中國的很多公司上面這兩件事依然被認為是 Code Reivew 最重要的事,所以,能夠看到很多開發 Team 抱怨 Code Review 就是一個形式,費時費力不說,發現的問題還不如測試,而評審者們起初在代碼風格上有些見術,別的也就沒什么用了,長而久之,大家都會開始厭煩這個事了。
所以,在今天,請不要把上面的那兩件事分散了 Code Review 的注意力,取而代之的是,對于 Bug,程序的作者要在 Review 前提交自己的單元測試報告(如:XUnit 的測試結果),對于代碼規范,這是程序作者自己需要保證的,而且,有一些工具是可以幫你來檢查代碼規范的。
當然,上述這些言論并不是說,你不能在 Code Review 中報告一個程序的 bug 或是一個代碼規范的問題。只是說,那并不是 Code Review 的意圖。
1.5 使用代碼評審的小提示
- 1、經常進行 Code Review
以前經歷過幾個相當痛苦的Code Review,那幾次Code Review都是在程序完成的時候進行的,當你面對那近萬行的代碼,以前 N 我摻和在一起的功能,你會發現,整個 Code Review 變得非常地艱難,用不了一會兒,你就會發現大家都在拼命地打著哈欠,但還是要堅持,有時候,這樣的 Review 會持續 3 個小時以上,相當的夸張。而且,會議上會出現相當多的問題和爭論,因為,這就好像,人家都把整個房子蓋好了,大家 Review 時這挑一點那挑一點,有時候觸動地基或是承重墻體,需要大動手術,讓人返工,這當然會讓蓋房的人一下就跳起來極力地維護自己的代碼,最后還傷了團隊成員的感情。
所以,千萬不要等大廈都蓋好了再去 Reivew,而且當有了地基,有了框架,有了房頂,有了門窗,有了裝修的各個時候循序漸進地進行 Review,這樣反而會更有效率,也更有幫助。
下面是一些觀點,千萬要銘記:
- 要 Review 的代碼越多,那么要重構,重寫的代碼就會越多。而越不被程序作者接受的建議也會越多,唾沫口水戰也會越多。
程序員代碼寫得時候越長,程序員就會在代碼中加入越來越多的個人的東西。 程序員最大的問題就是 “自負”,無論什么時候,什么情況下,有太多的機會會讓這種 “自負” 澎漲開來,并開始影響團隊影響整個項目,以至于聽不見別人的建議,從而讓 Code Review 變成了口水戰。
越接近軟件發布的最終期限,代碼也就不能改得太多。
個人的習慣,也是對團隊成員的要求是:先 Review 設計實現思路,然后 Review 設計模式,接著 Review 成形的骨干代碼,最后 Review 完成的代碼,如果程序復雜的話,需要拆成幾個單元或模塊分別 Review。當然,最佳的實踐是,每次 Review 的代碼應該在 1000 行以內,時間不能超過一部電影的時間 1.5 小時。
當然,在敏捷開發中,他們不需要 Code Reivew,其實,敏捷開發中使用更為極端的 “結對編程”(Pair-Programming)的方法:一種時時刻刻都在進行 Code Review 的方法,個人感覺在實際過程中,這種方法有點過了。另外,大家可以看看《結對編程的利與弊》來了解一下這種方法的問題。
- Code Review 不要太正式,而且要短
- 忘了那個代碼評審的 Checklist 吧,走到你的同事座位跟前,像請師父一樣請他坐到你的電腦面前,然后,花 5 分鐘給他講講你的代碼,給他另外一個 5 分鐘讓他給你的代碼提提意見,這比什么都好。而如果你用了一個 Checklist,讓這個事情表現得很正式的話,下面兩件事中必有一件事會發生:
- 只有在 Checklist 上存在的東西會被 Review。
- Code Reviews 變成了一種禮節性的東西,你的同事會裝做很關心你的代碼,但其實他心里想著盡快地離開你。
只有不正式的 Code Review 才會讓你和評審者放輕松,人只有放松了,才會表現得很真實,很真誠。記住 Review 只不過是一種形式,而只有通過相互的討論得到了有意義和有建設性的建議和意見,那才是最實在的
。不然,作者和評審者的關系就會變成小偷和警察的關系。
- 盡可能的讓不同的人 Reivew 你的代碼
-
這是一個好主意,如果可能的話,不要總是只找一個人來 Review 你的代碼,不同的人有不同的思考方式,有不同的見解,所以,不同的人可以全面的從各個方面評論你的代碼,有的從實現的角度,有的從需求的角度,有的從用戶使用的角度,有的從算法的角度,有的從性能效率的角度,有的從易讀的角度,有的從擴展性的角度……,啊,好多啊,還讓不讓人活了。不管怎么說,多找一些不同的人會對你很有好處。當然,不要太多了,人多嘴雜反而適得其反,基本上來說,不要超過 3 個人,這是因為,這是一個可以圍在一起討論的最大人員尺寸。
- 下面是幾個優點:
- 從不同的方向評審代碼總是好的。
- 會有更多的人幫你在日后維護你的代碼。
3.這也是一個增加團隊凝聚力的方法。
- 保持積極的正面的態度
再說一次,程序最大的問題就是 “自負”,尤其當我們 Review 別人的代碼的時候,我已經見過無數的場面,程序員在 Code Review 的時候,開始抨擊別人的代碼,質疑別人的能力。太可笑了,我分析了一下,這類的程序員其實并沒有什么本事,因為他們指責對方的目的是想告訴大家自己有多么的牛,其實,靠這種手段來表現自己的程序員,其實是就是傳說中所說的 “半瓶水”。
所以,無論是代碼作者,還是評審者,都需要一種積極向上的正面的態度,作者需要能夠虛心接受別人的建議,因為別人的建議是為了讓你做得更好;評審者也需要以一種積極的正面的態度向作者提意見,因為那是和你在一個戰壕里的戰友。記住,你不是一段代碼,你是一個人。
- 學會享受 Code Reivew
這可能是最重要的一個提示了,如果你到了一個人人都喜歡 Code Reivew 的團隊,那么,你會進入到一個生機勃勃的地方,在那里,每個人都能寫出質量非常好的代碼,在那里,你不需要經理的管理,團隊會自適應一切變化,他們相互學習,相互幫助,不僅僅是寫出好的代碼,而且團隊和其中的每個人都會自動進化,最關鍵的是,這個是一個團隊。
2、實用的 Code Review 工具
- 長時間以來,Code Review 需要有一些有效的工具來支持,這樣我們就可以更容易,更有效率地來進行代碼審查工作。下面是 5 個開源的代碼審查工具,他們可以幫助你更容易地進行這項活動。
2.1 Review board
Review board 是一個基于 web 的工具,主要設計給 django 和 python 的用戶。Review board 可以幫助我們追蹤待決代碼的改動,并可以讓 Code Review 更為容易和簡練。盡管 Review board 最初被設計在 VMware 項目中使用,但現在其足夠地通用。當前,其支持這些代碼版本管理軟件:SVN、CVS、Perforce、Git、Bazaar 和 Mercurial。
Yahoo 是 Review board 的其中一個用戶。
“Review board 已經改變了代碼評審的方式,其可以強迫高質量的代碼標準和風格,并可以成為程序員編程的指導者。每一次,當你訪問 search.yahoo.com 時,其代碼都是使用 Review board 工具 Review 過的。We’re great fans of your work!” – Yahoo! Web Search。
2.2 Codestriker
Codestriker 也是一個基于 Web 的應用,其主要使用 GCI-Perl 腳本支持在線的代碼審查。Codestriker 可以集成于 CVS, Subversion, ClearCase, Perforce 和 Visual SourceSafe。并有一些插件可以提供支持其它的源碼管理工具。
David Sitsky 是 Codestriker 的作者,并也是最活躍的開發人員之一。Jason Remillard 是另一個活躍的開發者,并給這個項目提供了最深遠最有意義的貢獻。大量的程序員貢獻他們的代碼給 Codestriker 項目,導致了這個項目空前的繁榮。
2.3 Groogle
Groogle 是一個基于 Web 的代碼評審工具。Groogle 支持和 Subversion 集成。它主要提供如下的功能:
-
各式各樣語言的語法高亮。
支持整個版本樹的比較。
支持當個文件不同版本的 diff 功能,并有一個圖形的版本樹。
郵件通知所有的 Reivew 的人當前的狀態。
認證機制。
2.4 Rietveld
- Rietveld 由 Guido van Rossum 開發(他是 Python 的創造者,現在是 Google 的員工),這個工具是基于 Mondrian 工具,作者一開始是為了 Google 開發的,并且,它在很多方面和 Review board 很像。它也是一個基于 Web 的應用,并可以 Google App Engine 當主機。它使用了目前最流行的 Web 開發框架 django 并支持 Subversion 。當前,任何一個使用 Google Code 的項目都可以使用 Rietveld 并且使用 python Subversion 服務器。當然,它同樣支持其它的 Subversion 服務器。
2.5 JCR
JCR 或者叫做 JCodeReview 也是一個基于 Web 界面的最初設計給 Reivew Java 語言的一個工具。當然,現在,它可以被用于其它的非 Java 的代碼。
JCR 主要想協助:
-
審查者。所有的代碼更改都會被高亮,以及大多數語言的語法高亮。Code extracts 可以顯示代碼評審意見。如果你正在 Review Java 的代碼,你可以點擊代碼中的類名來查看相關的類的聲明。
項目所有者。可以輕松創建并配置需要 Review 的項目,并不需要集成任何的軟件配置管理系統(SCM)。
流程信仰者。所有的評語都會被記錄在數據庫中,并且會有狀態報告,以及各種各樣的統計。
架構師和開發者。這個系統也可以讓我們查看屬于單個文件的評語,這樣有利于我們重構代碼。
JCR 主要面對的是大型的項目,或是非常正式的代碼評審,從這方面看來,他并不像上面的那些工具。
2.6 Jupiter
- Jupiter,是另一個代碼 review 的工具你可以去考慮使用的,它是一個 Eclipse IDE 的插件。
3、改善代碼質量的一些方法
3.1 減少對象屬性
這個是最容易改善代碼質量的一個點,很多代碼一眼看上去就會讓人感覺很凌亂,一上來就是幾十個不同的對象變量定義在里面,這讓不同邏輯之間莫名其妙沒法分開。一個是定義的方式不對,很多莫名其妙的內部變量暴露在頭文件中,讓外部調用者根本不知道哪些才是 public 可以操作的方法。另外實際上,大多數是可以通過局部變量或者 __block 變量來代替的。
頭文件中盡可能少暴露變量或方法,而要使用 extension 或者 category 放在 .m 文件,或者專門的 private 頭文件中,頭文件中暴露的信息越少越好,一切不必要的信息都不要暴露出來。.m 文件的 extension 中,定義 conforms protocol 和對象屬性,對于對象屬性的定義,使用 getter/setter 來定義。
使用局部變量或者 __block 變量代替
局部變量不需要多說,需要寫碼的時候思路清晰一些,寫完之后在 commit 之前即使 review 一定要 check 一遍,對自己的代碼質量負責,code review 往往檢查不出來冗余或者廢棄的代碼。不添加一個多余的對象屬性,不留注釋掉的代碼,不留沒有用途的代碼,這些都是基本功,但是很多開發者就是做不到,或者說對寫碼沒有愛,所以很多廢棄的代碼,我重構代碼的時候,雖然對業務不熟悉,但是大多數模塊都能刪除掉十分之一的代碼和大量的對象屬性,這個是單純的不夠用心。
可以盡可能避免循環引用
有個地方很多開發者會疏漏,在 block 中使用 _XXX 對象變量的時候,block 會 retain self 指針,一不小心就會造成循環引用的出現。所以使用局部變量的話,就能扼殺這種問題在搖籃之中。
3.2 減少和模塊化對象消息
- 減少對象消息
減少 UI 的 action 類消息,感謝 block 和 RAC,或者 blockskit,讓我們得以通過 hook 來把之前 target-action 模型換為 block 來實現,UI 和 action 的代碼終于可以一起了,使整個邏輯變得緊湊,在查看代碼的時候終于不用跳來跳去了。還有就是日常開發中,把自己寫的各種 protocol 或者傳遞 target/selector 的地方,盡量使用 block 來代替,相信我,這個會使代碼好讀很多。
- 模塊化
使用 “#pragma mark - XXX” 進行分割不同邏輯之間的界限,讓整個文件閱讀起來更加結構化。還有一個我現在最常用的就是是設置 Xcode 的快捷鍵,把 Ctrl + 6 顯示文檔結構的快捷鍵改為:Command + D ,搜索來快速跳轉到對應的消息和模塊,要盡量避免文檔結構顯示超過兩屏幕,超過兩屏幕說明有點多了,你肯定考慮一下重構了。
個人習慣一般劃分的模塊有:life cycle,ui helper,datasource/delegate,依據功能進行劃分的模塊等等。
3.3 MVVM && RAC
MVVM 不一定需要使用 RAC,但是 data binding 少不了,在 iOS 中也就是 KVO 了,建議大家都去嘗試一下,這個基本上是 MVVM的 最核心的東西了,連 Android SDK 也不得不引入這個特性。把數據部分的邏輯抽取放在 ViewModel 中,然后讓 UI 和 ViewModel 中的數據 binding,這個不會減少代碼量,但是絕對可以大大簡化開發時邏輯的重復度,再也不用重寫 -setXXX: 方法來 update 一大堆不相關的 UI 了。
關于 RAC,即使你不使用 RAC,有一些東西也是絕對值得你在項目中引入的,比如 @weakify(self)/@strongify(self),通過預編譯查看的話,這個的做法是設置一個局部變量 self 來覆蓋全局的 self,進而避免循環引用的,需要注意的是 block 層次較深的時候使用的問題。
3.4 UI 開發
- 重寫 setter 方法和 Code Block Evaluation C Extension 語法
重寫 UI 的 getter 方法,把 UI 的初始化放在 getter 中,減輕 -viewDidLoad 的負荷,同時可以使整個頁面變得清晰;同時,可以通過使用使用 GCC Code Block Evaluation C Extension ({…}) 語法,結構化局部變量初始化和處理的邏輯。
舉一個例子,-viewDidLoad 中,做為邏輯的入口,代碼會變少但是變清晰,代碼如下:
然后重寫 bgView 的 getter 方法,包括 View 和 frame 這些都可以使用 ({...}) 語法使代碼結構化層次化:
*復雜 UI 的開發
有時候我們開發業務的時候,產品需求往往非常復雜,酷炫的 UI 加上各種考慮全面的邏輯,這個的結果就是,碼農的超長代碼,而我們平時工作面對的也大多數都是這類問題。關于這個問題,解決方式是組合式 UI / custom view / child view controller 來解決。
1 組合式 view
這個概念是從 Android 中借鑒而來。重構時查看項目中的代碼,發現大家用的做 UI 的時候,對這個概念不是很強烈,感覺是對 UIView 的 view hierarchy 理解不夠。比如一個復雜的 UI,直接把所有的 subviews 直接堆積到 super view 上面,這樣的結果就是,調整 subview 的 frame 非常困難。我個人的做法是,首先對復雜 UI 進行分塊,從左到右或者從上倒下,把各個 UI 元素放到不同的 container view 上面,然后組合這些 container view 放到 super view 上面,這樣的好處非常明顯,首先 UI 干凈清晰,閱讀起來不那么費勁。其次就是你計算坐標或者設置約束會變得很簡單,因為你調整一個 UI 元素的時候,只需要考慮它與包含它的 container view 的坐標關系即可,而不是通過一大堆無趣計算跟最外層 super view 關聯起來。還有就是可以充分利用 Auto Layout 和 autoresiziingmask 這些 UI 利器,使用的時候會非常方便。再有就是結合 RACObserver 這個利器之后,你能很容易做到根據 data 來 update ui。
舉個例子,是我們項目中前一段時間我重構的一個頁面,這個首頁列表,性能要求比較高。并沒有使用 Auto Layout 來實現,但是不使用 Auto Layout 并不是不把它寫的很干凈的理由。
這是我對一個 UITableViewCell 的分層,最外層由 icon view / right view / bottom view 這些 container view 組成,而 right view 這個 container view 則又是由 right top view / right middle view /right bottom view 這些 sub container view 組合而成,而具體的 UI 元素則是放在這些 sub container view 之中。這樣 UI 代碼就會以一種層次化樣式展示出來,init/layoutsubviews 只需要維護 self 與container view 的關系即可,而具體展示數據的 UI 元素也只跟 sub container view 存在坐標關系。我們看一下 right view 這個 container view 的代碼實現: 5 6 7 * 關于性能的話,感謝 iOS,我們不存在 Android 中頁面層次較深性能卡頓的問題,放心把 UI 層次化就行。
- custom view
對于非常復雜并且相對獨立或者可以重用的 UI,及時使用 custom view 子類化。對于單純的展示 UI,我們只需要簡單通過組合式 view 就可以實現了。但是有時候,我們會遇到一些包含無論是動畫,邏輯都比較復雜的情況,這個時候使用組合式 View 去實現,一方面容易把邏輯弄混亂,會把文件的文檔結構變得很復雜,簡單來說就是對象的消息數量很多。這個時候,我們可以通過 custom view 來實現,實際上這個也是組合式 view,但是我們是把這些組合式 view 變成了一個類而已,只暴露少量的接口給外部調用。如果這個 custom view 會出現在多個業務模塊中,那么有必要使用一個單獨的文件來容納這個類,如果僅僅是這個模塊一個使用的話,可以直接寫在這個業務模塊的文件中即可,沒有必要對所有的類都單獨一個文件,我們就當作這個 “內部類” 來弄了。
什么時候使用 custom view 而不是組合 view,我想了很久,你覺得組合式 view 的代碼很亂的時候,別客氣,包裝為一個 custom view 就行了。我這邊最近遇到的幾個問題是使用 UICollectionView 來做部分 UI 的時候,同時還有其他很多 UI 元素,我會寫一個 custom view。比如把一個左右滑動查看圖片的 UI 使用 PhotoView 這個 custom view 進行包裝,內部使用 UICollectionView 實現一部分相對獨立的模塊,這個時候這個控件實際上是可以包裝為一個相對獨立的模塊的,用子類我感覺比較合適一些。
- container view controller
這個用法很多開發者不熟悉或者說是用的不多,但實際業務中,這個技術非常有用途,可以大大提高開發效率。對于有相對獨立業務邏輯以及生命周期要求的業務,使用 child view controller 進行包裝,如果 parent view contrller 與 child view controller 之間非常密切,則使用 View Model 以及 block 來對 parent view controller 和 child view controller 進行銜接。
使用 child view controller 來開發 UI 而不是 custom view 的優勢很多,我個人認為最大優勢在于可以方便利用 View Controller 的生命周期以及 View Controller Hierarchy,比如在 -viewWillAppear/-viewDidDisappear 中做一些操作,再比如直接獲取 UINavigationController 指針等等。之前的做法一般是在 View Controller 的對應生命周期內調用 custom view 的方法,傳遞 self.navigationController 指針給 custom view 等。所以可以不僅僅把 UI 相關的代碼包裝進入這個 child view controller,也可以把網絡請求,數據處理這些這些邏輯放到 child view controller 中,這樣下來就能避免那種動不動超過 1k 行的 view controller 的出現了。
利用 MVVM 之后,還有一個比較有好處的用法,比如公用一些數據的時候,之前我們是把對象傳遞來傳遞去,這樣的問題是很容易出現混亂,這個時候我們是傳遞 ViewModel 就可以避免這個問題,ViewModel 既負責網絡請求又負責數據處理,而 parent view controller 與 child view controller 所需要做的事情就是跟 ViewModel 進行 binding 而已。
3.5 Auto Layout/Masonry
在一些性能要求不是那么強烈的非列表頁,我們可以大量使用 Auto Layout 來開發 UI,充分利用 UI 根據數據的自適應能力,連在 container view 中調整 UI 的步驟都不需要了。
至于 Masonry 這個框架,之前我對這個抱有一定的懷疑不敢使用,所以我把源碼讀了一遍,發現這個包裝很薄很巧妙,很多設計思路也值得借鑒,對源碼有興趣的可以參考博客。我讀完源碼之后,嘗試著完全使用 Mansory 來開發一個展示信息的頁面,感覺太爽了。
說一下 Auto Layout 的問題:
1、首先一個問題,是如果一個 view 不是 leaf view 的話,那么這個 UIView 如果 hidden 的話,它的約束仍然是 work 的,所以會留下空白,不會像 Android 中那樣設置 GONE 那么方便。國內 sunny 大神開源一個不錯的解決方式。這里說一下我之前的解決方式,比較土逼,直接子類化:
2、動畫的問題
使用 Auto Layout 有一個比較大的問題在于動畫,通過更改約束來進行動畫,一直是我比較頭疼的問題,所以一般遇到這類問題的時候,我都會盡量避免使用 Auto Layout 來解決,而是使用 frame 的方式來做。可以參考 objc.io 上面的一篇文章。
- 3、多行 UILabel 的問題
iOS7 以及以下的操作系統上,UILabel 顯示多行文本是有不足的,你需要設置 UILabel 的 preferredMaxLayoutWidth 為一個固定值才能顯示多行文本。在 iOS8 以后就不再需要設置這個了。
- 4、UIScrollView 的問題以及約束歧義和其他問題
這個地方,我的建議是根據具體問題來選擇實現方式:spring & structs 也好,Auto Layout 也好,那種解決問題較為簡潔快速就用那種,不一定非要固定于一種行為,尤其是開發的頁面有大量動畫的時候。
3.6 注釋
不要寫一堆中文注釋,代碼不要出現大量的中文,OC 已經夠啰嗦,不要這么啰嗦地寫碼。除了提供服務的 public 功能或者方法,業務代碼僅在某些關鍵點上注釋一下就行,不需要一大堆中文,這樣太 low,代碼自注釋即可。
而對于出現拼音命名代碼的人,能做主的話,別猶豫,開掉吧。這里吐一下槽,之前的公司就有這樣的哥們,不是我招進來的,老板硬塞給我的。
3.7 善用 OC 的新語法
OC 有很多新的語法糖,可以大大提高我們的效率,參考 Apple Guide。
比如打印數字的時候,我們可以用 @(xxx) 來打印,定義枚舉的時候使用 typedef NS_ENUM,使用 instancetype 而不用 id 等等。
3.8 JSON 數據的處理
- 新手往往會被這個稍微困惑一下,比如服務器返回的數據格式不正確啦,包含 null 啦,都很容易引起項目崩潰。這個問題可以使用 Mantle 來解決,很多兄弟都在使用這個,我自己倒是一直沒有用過。
3.9 block
使用 block 代替 delegate,這個沒啥可多說的,把代碼變得非常緊湊,減少文件的消息數量,最主要的是關系沒那么緊密了。對于有大量的 delegate 方法才考慮使用 protocol 實現,這個時候 block 太多也影響閱讀。
同時,對于傳遞 target/selector,也盡量使用 block 吧,這種閱讀查找起來太不方便了。
3.10 提交代碼
及時 stage,這個非常重要,開發過程中經常需要經常比對上一步的代碼,這樣才能最大程度上確保自己的改動是正確的。如果有一些小問題,也可以及時找到歷史版本。
及時 commit,每完成一個相對完整的需求,就 commit,小提交是個好習慣。
PR code review 要做好,要花大量的時間做,有條件的話,最好每個版本開一次總結會。
3.11 RAC 封裝網絡請求
返回的 signal 要避免多次出現 side effect,但不使用 replay/replayLazily,因為 dispose 不會被調用。
使用 RACCommand 封裝請求,查看這幾篇文章:
結合 RACCommand 和 takeUntil: 來封裝一個可以 cancel 的請求。