iOS developer的良好習慣

前言

隱藏細節,暴露抽象。git

做爲一名有追求的工程師,咱們但願代碼可以在版本迭代中逐漸優化而不是劣化;同時也會學習掌握更多的技巧和工具,去更好的設計、實現和組織代碼。偶然看到一個apple工程師的分享,因而加上一些本身的經驗和感覺,作一些總結。編程

正文

1、代碼組織

一、使用group

做爲一名iOS工程師,Xcode應該是最熟悉的工具之一。舊版本的Xcode在新建一個目錄時,只會做爲建立一個引用,不會同時在相同的路徑下去建立目錄。新版本Xcode建立目錄的時候都是以group的形式去建立,會在同級路徑下去建立對應的目錄。
好比下圖,在建立New Group的時候,就會一樣在Audio的目錄下去建立一個New Group的目錄。若是項目的代碼是好久之前的Xcode建立的,最好檢查一遍目錄,使得Xcode的工程文件目錄和實際的文件目錄結構保持一致;若是項目是新Xcode建立則儘可能在Xcode中建立group。 xcode

二、拆分大文件

若是項目有使用storyboard,則能夠把較大的storyboard文件,經過引用的方式拆分紅多個storyboard。這樣能提高打開時的速度,也能使得多人協同開發時減小衝突的產生。
可是我經歷過的項目都沒有使用storyboard,大文件的矛盾更可能是產生在.m文件,以一個咱們項目中的文件爲例:性能優化

這個2000行的.m文件並非一蹴而就,而是隨着十幾個版本的迭代,邏輯不斷增長,慢慢變大的文件。這也是咱們常說的歷史技術債務。技術債務產生的緣由多種多樣,多是最開始的時候沒有很好的框架設計,也多是實現過程當中有不規範的現象,又或者是多人協做開發致使的代碼膨脹。當發現問題以後,就須要去償還這個技術債務。markdown

.m文件拆分首先須要把業務的核心邏輯梳理出來,抽象出來該模塊的狀態信息、關鍵參數,將外部業務在.m內添加的邏輯改成依賴.m提供的狀態,而狀態能夠經過通知、消息等方式拋出去;
核心可是又內聚的邏輯可使用xxLogic去封裝,而後.m文件直接依賴該xxLogic;也能夠將其聚合到.m文件的一個Category之中;
通過這番處理,.m文件能獲得極大瘦身,而梳理完內外部依賴以後,後續再新增邏輯也不用去查看.m文件,而是依賴下面的.h文件。
網絡

三、重視Xcode的提示

保持Xcode工程設置是最新的,使用Xcode自帶的性能優化。當Xcode彈出下面這個框的提示時,若是沒有特殊訴求,apple工程師推薦點擊Perform Changes按鈕。多線程

在編譯的過程當中,Xcode給出的warning可能在線上運行時就是一個Bug。建議在debug開發階段,打開Treat Warnings as Errors選項;追本溯源,找到問題的根本緣由,解決每個編譯期間的warning。架構

若是是已知問題,暫無解決方案,爲了不阻塞編譯運行,可使用xcode指令去忽略。(具體的warning類型能夠在Xcode的Issue Navigator查看,快捷鍵是command+5)app

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// ingore code
#pragma clang diagnostic pop
複製代碼
四、去掉無用的代碼

咱們有時會提交一部分被註釋代碼,理由多是代碼如今不須要但下個版本可能會用到,臨時註釋一下,反正不影響運行。可是設想一下,若是團隊裏面每一個人都有這個習慣,那麼項目中是否會存在不少無用的代碼?而且這個代碼可能永遠也不會有用武之地。
因此,果斷地刪除那些無用代碼吧,即便真的有須要用到的時候,也能夠經過代碼的版本控制工具去找到那些歷史代碼。框架

2、代碼管理

版本控制系統已經成爲開發的必備工具之一。曾經svn也是版本管理的高效工具,Windows系統中的小烏龜(TortoiseSVN)很是好用。可是隨着git的出現,svn已經被逐漸淘汰。

一、提交獨立

一個複雜功能每每由多個需求點組成,開發過程也可能持續數天時間。能夠把需求的提交拆分紅屢次,儘可能使得單次提交獨立,Xcode能夠看到每一行代碼的提交備註信息。 換位思考,咱們但願從git的commit信息裏面,看到這段代碼的原因。
點一下右邊對應信息,選擇show commit,還能夠看到對應commit的具體內容。

一我的能夠記住昨天爲何寫這段代碼,但很難記住一段數月乃至數年前的代碼爲什麼出現。

二、分支管理

爲了保持開發階段的便利,提供alpha分支,做爲平常開發的合入分支;爲了保證外網代碼的可查,提供beta分支,做爲版本發佈的打包分支;當版本發佈以後,還須要打tag記錄對應版本,好比說release_1.0.0.10。
平常的需求開發(feature分支)、問題修復(bug分支)都是在非主幹分支進行開發,最終再合入alpha分支。合入的要求根據團隊實際狀況,能夠是分支驗收完成再合入,也能夠合入後統一驗收。

三、Code Review

Code Review(代碼審查,後面簡稱CR)是發生在分支合入的狀況,是成熟開發團隊必不可少的環節。CR有助於團隊代碼風格的統一,包括函數命名、變量命名、代碼組織風格等。同時,CR要求代碼具有必定的可讀性,也要求單次提交不過包括過多改動。

3、文檔

一、必要的註釋

好的代碼一目瞭然,能清晰描述邏輯,不須要註釋來輔助描述。可是一段特殊邏輯,須要有註釋來描述爲什麼存在,以方便在改動以後去迴歸影響點。
好比說一段經典的dispatch_after 1秒的邏輯,這1秒多是爲了不某些異常case,也多是產品側的需求要求。

二、對外方法的描述

平時的開發過程,除了注意變量和方法的命名要具備含義,對外提供方法的註釋能夠清晰描述須要的參數。好比說下面的一個方法:

在Xcode中選擇對應的方法,按下快捷鍵option+?就能夠看到該方法的描述,以及各個參數的要求。若是方法還沒添加描述,則按下option+command+?自動生成待補充的描述。

三、文檔積累

隨着業務的發展,項目中代碼不可避免的會快速膨脹,直接閱讀代碼會很是吃力。此時就須要有文檔來輔助瞭解各個模塊的狀況。
文檔應當避免對具體邏輯細節的贅述,更是和從總體的設計和考慮的因素出發,描述該模塊是如何運行起來。同時在設計的過程,也應該基於以前的技術方案設計。

培養團隊的寫文檔習慣,每一個版本前期組織技術方案評審,由負責較爲複雜需求的工程師準備一份技術方案的設計文檔,能夠達到事半功倍的效果。

4、便捷工具

你們提到Xcode的分析工具,第一反應每每是Instrucment中的工具集。可是實際開發中還有一些便捷工具。

一、Network Link Conditioner

模擬弱網絡環境,之前是在手機的設置-開發者-Network Link Conditioner能夠去設置,如今真機鏈接以後能夠在Xcode中按下command+shift+2,選擇對應的設備就能夠選擇具體的網絡環境。

二、 Address Sanitizer

Address Sanitizer是內存錯誤檢測工具,經過malloc/free增長標記實現。 好比說下面這一段代碼,buf指針建立了1024內存,再手動釋放,而後再去訪問buf指針的元素。這段代碼編譯時正常,在運行時不必定會崩潰 ,有可能就會演化成一個偶現bug,難以定位。 在使用Address Sanitizer工具的時候,運行到130行時就會報錯:Use of dealloccated memory

打開方式是在scheme選項中,勾選Address Sanitizer。

三、Thread Sanitizer

Thread Sanitizer是線程錯誤檢測工具,能夠檢測到一些多線程數據訪問的錯誤,好比說下面的代碼。 sTestNum是靜態全局變量,建立了多個線程去操做該變量,會觸發Data Race

打開方式是在scheme選項中,勾選Thread Sanitizer。

Thread Sanitizer關注的是數據的多線程訪問,經過記錄內存的訪問來實現,並不能定位到多線程的crash問題,好比下面這個crash:

四、Main Thread Checker

Main Thread Checker是多線程操做UI檢查工具,UI操做只能在主線程執行,若是在子線操做則會觸發警告。

打開方式是在scheme選項中,勾選Main Thread Checker。

五、Debug Gauges

在debug運行程序的時候,Debug Gauge能快捷地查看CPU、Memory、Disk、Network信息。

打開方式是Xcode按下command+7。

5、開發建議

一、最小依賴原則

一段邏輯的運行,每每須要外部的變量輸入。有時候爲了便捷開發,函數調用時候不會傳遞參數,而是經過全局變量、self指針等直接去獲取須要的數據。可是這樣會致使代碼邏輯紊亂。在編碼的時候,很是建議使用最小依賴原則:儘量少的使用外部依賴。
以函數爲例,一個xx邏輯處理的方法應該只依賴函數參數。這樣函數的輸入輸出是固定的,即便函數放到其餘地方,只要保證函數的輸入不變,則邏輯的輸出是不變的。
同理,除了函數還有view、model等等,儘量少的去依賴外部數據、外部模塊,則該處邏輯更加獨立,更容易實現能夠直接複用的view、model等等。

二、組件化&模塊化

實現功能的時候,應儘量去除耦合;特定功能組成的庫就是組件,寫新功能代碼儘量要往組件方向實現;而模塊化指的是根據業務形態,把代碼按照功能、業務進行聚合,至關於組合了各類組件和業務邏輯的庫。
模塊化和組件化等一個重要特色就是Pod化,將這些特定、獨立的功能代碼和業務代碼從主工程中剝離,抽象出來業務須要的接口,再從新經過pod依賴引入主工程。在這個過程,不僅僅是把代碼轉移到Pod庫,還須要作一些業務的解耦和依賴抽象。
好處也是顯而易見:
開發上,模塊化後各個業務相對獨立,可以更加專一本身業務邏輯,即便業務出錯影響面也比較可控;
效率上,模塊化後能夠作二進制組件,加快編譯速度;
管理上,組件owner的意識更強,方便添加數據監控;
架構上,強迫面向接口編程,避免大量耦合的膠水代碼。

總結

本文部分參考自 WWDC2019,結合一些工做經驗,作了更適合本身的闡述。 本身也梳理了接下來一段時間的技術優化方向: 平常業務迭代,經過CR保證新增代碼風格統一; 複雜業務需求,須要作技術方案評審,集思廣益; 已有歷史債務,小模塊微整實現,大業務走專項重構,注意人力投入、業務影響和收益評估。

相關文章
相關標籤/搜索