你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS App開發那些事:如何選擇合適的人、規范和框架?

iOS App開發那些事:如何選擇合適的人、規范和框架?

編輯:IOS開發基礎

自從做Team Leader之後,身上權責發生了變化,於是讓我煩惱的不再是具體某個功能,某個界面的實現,而是如何在現有代碼的基礎上做漸進式的改進,創造出比較合適規范和框架,使得組內成員更快更好地完成任務。一年下來,頗有點想法,於是啰嗦幾句關於iOS App開發的那些事。

brainstorm.jpg

合適的人

首先明確一點,合適的人是指純技術團隊的建設。一支戰斗力再強的技術團隊,面對一個朝三暮四,分分鐘推翻自己原有想法的產品經理/項目經理,再好的戲也唱不出來。花幾個月加班加點做項目,還沒發布,直接推翻重做,這時候你就得去樓下ATM機看看卡內余額了:余額夠了,收拾收拾好找下一家了。

計算機界有句名言:計算機相關的所有問題都可以通過增加一個額外的抽象層來解決。但是軟件開發卻不是這樣:增加層(人手)在一定程度上可以加快開發進度,當過了某個阈值後其效果就顯得不是那麼明顯,甚至會起反效果。對於一個項目而言需要的往往不是更多的成員,而是適量的合適成員。

每一個人因為不同的教育背景,從業背景,項目經歷(技術選型,學習經歷,項目管理)對程序開發都會有不同的理解和思維模式。反應在業務上就是各種各樣的代碼風格。舉例來說:有些人恨不得把所有單一功能都一一獨立出來封裝成類,而有些人卻喜歡一個大類洋洋灑灑寫上上千行。大部分情況下我都是傾向於前者,但是就像我時常吐槽的那樣:It depends。不僅僅是軟件開發,幾乎所有的事到最終都會歸結到一個統一的問題上:怎樣才是一個度?

一群理念相去甚遠的人在一起工作是件異常痛苦的事:相當一部分的時間會浪費在解釋,爭論和排遣由此帶來的沮喪和憤怒上。古人語:道不同,不相為謀。但到了真正的工作中卻不能如此隨性,缺乏足夠動力的老人,能力出眾的技術骨干,干勁十足卻缺乏經驗的新人都需要互相體諒,學習和磨合。所以大部分的創業團隊的技術團隊因為理念相近,往往效率會足夠高,而大公司內的開發小組卻永遠無法達到那樣的效率,更需要相應的規范和程序框架。

得出上面這個結論的另一個理由是我對人的可塑造性是持悲觀態度的:多數人並沒有跳出自己思維局限性的意願,動力和能力。少數人在沒有任何外界壓力的情況下仍會不斷總結學習進步(主動學習型),而其余的人要麼沒有任何意願,關心的只是完成任務和拿到工資而已,要麼想要進步而不得法。而你的團隊不可能全由主動學習型的成員組成,這時候規范和程序框架的引入才能夠讓各種類型的人更好的合作。

合適的規范

大家都理解軟件開發需要合適的規范:代碼規范,程序規范,流程規范等等,以此來減少意外的出現:最少驚訝原則。但在實際執行中卻會碰到各種情況,其中最大的問題是:怎麼鑒別哪些規范是需要強制執行,那些規范是推薦執行。規范的強制執行帶來的是代碼的可讀性提升和二義性減少,而壞處也是顯而易見的:對於大部分有想法的程序員而言這種規定太死板,容易引起抵觸心理,產生不安定因素。這種情況常見於各種標准的外包公司。

而如果大部分的規范設定為推薦執行,在沒有良好的引導下,規范容易被忽視。 網上有很多關於ObjC的代碼規范,比如蘋果自家的規范和《Google Objective-C Style Guide》等。這些規范一般只有兩種分級:推薦和不推薦。而我更推薦把代碼規范分成五個等級:強制要求,強烈推薦(但不強制),良好,可接受和不可接受。以下僅舉部分例子加以說明。

  • 符合蘋果規范的命名方式。

    • 類名開頭大寫,方法和變量名以駝峰法命名。強烈要求,這沒有什麼好說的,蘋果系統類庫和絕大多數的第三方開源庫都是如此。但在部分蘋果的sample中也看到過用m做前綴表示類成員變量的寫法,這些都是屬於遺產代碼的問題,仍舊是可接受范圍,但是自己代碼內部使用類似匈牙利的命名法就是不可接受。

    • 類名使用至少三個字符做前綴,內部方法使用兩個下劃線做前綴。強烈推薦。上面的做法可以最大程度避免和系統類庫發生重名的情況:因為蘋果宣稱保留所有兩位字符前綴的使用權,同時其內部方法命名以一個下劃線做前綴。

    • 無論使用K&R Style還是Allman Style都是可接受的范圍,但是強烈推薦在一個文件內保持一種形式。

    • 在保證代碼可讀性的基礎上保持代碼的簡短和統一性:小類,小方法,統一的函數返回。小類,小方法可以保證他人閱讀時更方便地關注類邏輯,而不是具體細節,而統一的函數返回可以減少意外錯誤和降低錯誤排查的難度。而保證代碼的簡短和不羅嗦也是很重要一點,經常會看到如下代碼: > (count > 1) { return YES; } { return NO; }  真心無法直視。

  • 良好的代碼/工程結構

    • 為整個工程創建worksapce。

    • 按照權責分門別類存放資源文件:每種類型的資源存放於獨立的目錄下:圖片,聲音,配置文件等等。而圖片又可以按照類型分別存放在不同的子目錄下:全局類型,背景圖,logo,登錄等等。

    • 合理的代碼結構。推薦如下的工程目錄結構

ios_arch.jpg

Core:工程內一些通用的機制實現類:統一的任務管理,模塊管理,服務管理。

General:公用類和方法,包括工程內ViewController,UITableViewCell基類(Base),公用Category(Category),公用UI組件(CustomUI),公用輔助方法(Helper)和宏定義(Marco)。

Model:公用數據模型

Sections:不同程序單元。如登錄,設置等等。其下又可以按照功能分成不同的子目錄:當前單元使用的自定義UI組件,管理類,數據模型和ViewController等等。

Vendors:第三方庫。

合適的框架

一個合適的框架不是銀彈,在我看來框架要解決的問題從來不是:有了框架之後,工程就能無比正確地進行下去。好的框架能夠做到的事僅僅只是:降低通用問題的復雜度和減少發生錯誤的可能性。個人認為一個良好iOS App框架應該是有如下特點:

  • 定義清晰的層次結構。

    • 展現層(Presentation layer),負責管理UI和UIViewController

    • 邏輯層(Business/Service Layer),負責邏輯數據的定義和轉發,起到承上啟下的作用。

    • 數據訪問層(Data Access Layer),負責具體API構造,網絡請求,數據持久化等。

    • 各層根據業務邏輯的復雜性內部又會使用單層或者多層結構。以數據訪問層為例,一般又可以細分為網絡層,持久化層。而一般而言,展現層(UIView和UIViewController)都是直接使用邏輯層提供的Model進行展現,但是某些場景下往往需要不同的Model有相同的界面展示(如我們的App易信中,會話界面,收藏界面,問一問功能都需要進行圖片的展現,但這三個模塊下的Model定義並不一致),這就需要增加額外的ViewModel層用於粘合展現層和邏輯Model。

    • 橫向上,各模塊互相獨立,僅通過有限的幾個接口進行通訊。最理想的狀態是除核心模塊外,其他模塊都是可拔插。縱向上,各層次間依賴關系清晰,基本不出現逆向依賴的情況。

    • 橫向模塊一般依賴於業務需求,常被定義成各種Service或Manager。一種好的做法是有個統一的Service管理器負責相應Serivce的加載,卸載,監聽和分發App級別的通知給相應Service,如前後台切換,收到內存警告等。這樣做一方面容易實現上面說的模塊的可插拔化,另一方面也保證了公用特性處理的一致性。在這方面微信就做得不錯,基本所有的模塊都是從MMService繼承而來,由MMServiceCenter進行管理。當然從dump出來的頭文件也可以發現一些管理上的紊亂,比如一些ViewController都是繼承自MMService。

    • 縱向的層次劃分基本各個App不會有太大區別,一般可以分為三個層次:

  • 遵守SOLID原則和慎用各種設計模式。這是個老生常談的話題了,並不是iOS開發獨有,展開講可以講上幾天幾夜,不贅述。

  • 定義自己的UI基類:UIView,UIViewController,UITableviewCell。這一點的好處不言而喻,所有的子View,Controller,Cell都能夠很方便的繼承基類的共有的行為,樣式。但也會引進很大的管理風險:組內成員總會經不起誘惑往基類塞各種並不普適的特性,引起基類權責的無限膨脹。大基類不僅增加組內成員對代碼的理解難度,同時也增加出現問題時的排查難度。從這方面講,微信的UIViewController基類設計就極端失敗:MMUIViewController。

  • 提供方便好用的工具類。一些好用的工具類往往會成為框架重要的有機組成部分,方便快捷地解決局部問題,同時又不引入過多的復雜度。NSTimer的retain cycle是個很容易掉去的坑,那麼提供一個基於Block或者weak delegate的NSTimer的封裝就是不錯的選擇。使用KVO容易發生add和remove的不配對調用,那麼就引入THObserversAndBinders或者FB的KVOContorller。某些核心模塊需要被多個模塊依賴時,引入類似XMPP的GCDMulticastDelegate就能夠方便地進行解耦。

  • 好的范例。在前幾年使用C++的那段暗無天日的日子裡,我常想的一個問題是:如何在API層面去限制和規避一些錯誤。比如往線程池裡面扔的task必須是堆上分配的對象,那麼如何去強制傳入的指針指向的是堆地址而不是棧地址呢?這種傻問題大部分情況下是無解的,有時候有解卻是個異常別扭的解。而現在我更相信破窗理論所提供的可能性:做好示范,接下來的一切都會水到渠成。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved