編碼規範,objective-c編碼規範

來源:互聯網
上載者:User

參考了<<C++編程規範 101條規則,準則與最佳實務>>

1.匈牙利命名 和 不要盲目使用匈牙利命名

命名規範是程式書寫規範中最重要也是最富爭議的地方,自古乃兵家必爭之地。命名規範有何用?四個字:名正言順。好的舞鞋是讓舞者感覺不到其存在的舞鞋,壞的舞鞋是讓舞者帶著鐐銬起舞。

匈牙利命名法的成本:匈法的表現形式為給變數名附加上類型名首碼,例如:nFoo,szFoo,pFoo,cpFoo分別表示整型變數,字串型變數,指標型變數和常指標型變數。可以看出,匈法將變數的類型資訊從單一地點(聲明變數處)複製到了多個地點(使用變數處),這是冗餘法。冗餘法的成本之一是要維護副本的一致性。這個成本在編寫和維護代碼的過程中需要改變變數的類型時付出。冗餘法的成本之二是佔用了額外的空間。一個優秀的書寫者會自覺地遵從一個法則:代碼最小組織單位的長度以30個自然行以下為宜,如果超過50行就應該重新組織。一個變數的書寫空間會給這一法則添加不必要的難度。

匈牙利命名法的收益是含糊的,無法預期的。

 

  Charles Simonyi(他後來成為微軟的著名程式員)設計了一種以首碼為基礎的命名方法,這種方法後來稱為"匈牙利標記法"以記念他.他的思想是根據每個標識符所代表的含義給它一個首碼.微軟後來採用了這個思想,給每個標識符一個首碼以說明它的資料類型.因此,整型變數的首碼是n,長整型變數是nl,字元型陣列變數是ca,以及字串(以空類型結尾的字元數組)以sz為首碼.這些名字可能會非常古怪.比如說:lpszFoo表示"Foo"是一個指向以Null 字元為結尾的字串的長整型指標.

這種方法的優點是使人能夠通過變數的名字來辨別變數的類型,而不比去尋找它的定義。遺憾的是,這種方法不僅使變數名字非常繞口,而且使改變變數類型的工作變得十分艱巨.在Windows3.1中,整型變數為16為寬.如果我們在開始時採用了一個整型變數,但是在通過30---40個函數的計算之後,發現採用整型變數寬度不夠,這時我們不僅要改變這個變數的類型,而且要改變這個變數在這30--40個函數中的名字.

因為不切實際,除了一些頑固的Windows程式員外,已經沒有人再使用"匈牙利標記法"了。毫無疑問,在某種場合它依然存在,但大部分人現在已經拋棄它了。一般而言,輸入首碼是一種糟糕的想法,因為它把變數與其類型緊緊地綁在了一起。

http://www.cppblog.com/justin-shi/archive/2008/05/02/48615.html
http://www.cnitblog.com/ffan/archive/2005/09/21/2815.html
匈命名規範表
http://dev.csdn.net/htmls/34/34000.html


將類型資訊併入變數名的記法,是混用了類型不安全語言(特別是C)中的設施,這在物件導向語言中是可以存在的,但是有害無益,在泛型程式設計中則根本不可行。所以,任何C++編程規範都不應該要求使用匈牙利記法,而在規範中選擇禁用該記法則是合理的。

關於對象的類型,編譯器知道的要比你多得多。改變變數的名字,蘊入類型資訊,其好處實在有限,而且使之更脆弱。如果說在C風格的語言裡使用匈牙利記法還存在一些理由的話(即使這點也存在爭議),那麼在型別安全的語言中使用它則是有害無利。

如果知道類型名,便會引出變數名,即變數名本身就可以體現出自己的類型。如果加入類型標識,萬一類型發生改變,必須修改變數名。如:int改為了long.

對於編程人員,瞬間知道變數的範圍比瞬間知道它的類型有用的多。

匈牙利命名法更已不適合現在的物件導向語言。

但對於類型是數組,字典等集合體的變數,在名稱的最後標識出類型資訊更好。也允許在局部很短的範圍內使用這種命名法。

2.關於有人盲目推薦“不要在迴圈體內定義變數”,http://topic.csdn.net/t/20061229/10/5263622.html

   參考 java:string博文。

   變數聲明在for內外對於GC沒有太大區別。先不論gc時機和具體回收的堆內容的不確定性,就光看棧引用和堆對象的關係而言,兩種寫法都只會新建立N個堆對象,同時,任意時刻,都只有一個棧引用一個堆對象。

   迴圈體外定義的變數只產生一次,迴圈體內定義變數理論上每次迴圈都回產生變數。產生一個變數,系統仍然要分配記憶體空間的,所以效率較低,但是現在的編譯器都是帶最佳化的,編譯的時候一最佳化就一樣了。可能會被最佳化為,只在第一次迴圈才聲明,編譯器會記住此聲明,後面的迴圈就不再聲明了。

  例如:

   for( ...)
{
   int i=5;   //只在第一次迴圈才聲明
}

試想一下,如果想當然的認為是每次迴圈都會定義,那麼把這個迴圈展開就會是
int i=5;
int i=5;
......
顯示是不能為編譯器接受的。

另外,在VC裡調試
void main()
{
for(int i=0;i<5;i++)
{
int* num = new int;
}
}
可以發現每次迴圈時 &num是同一個值,指標本身這個32位整數值是不變的。
  在迴圈體外聲明一個只有迴圈體內才使用的變數是一個不良習慣,這是典型老式C語言的編程風格,就像在C語言中濫用全域變數一樣,這樣會擾亂上下文變數的定義和語義,造成程式本身的不可讀性。非持久性狀態變數聲明盡量局部化,這是模組化和物件導向思想的一般準則。

  隨著硬體水平的提高,清晰、易懂的代碼更優於不清晰,不易懂但效率只是略高的代碼。
  從普遍意義上來說,“不要在迴圈體內定義變數”只適用於在心理上對效率差要求極高的高手。

   自動生存期變數:其記憶體空間在程式執行到定義它們的複合陳述式時才分配,定義它們的複合陳述式結束時,空間被收回,局部變數和函數參數一般具有自動生存期。
   當在一段代碼塊中定義一個變數時,java就在棧中為這個變數分配記憶體空間,當超過變數的範圍後,java會自動釋放掉為該變數分配的記憶體空間,該記憶體空間可以立刻被另作他用。
   棧展開:因發生異常而逐步退出複合陳述式和函數定義,被稱為棧展開(stack unwinding)。棧展開才是異常處理的核心技術。隨著棧展開,在退出的複合陳述式和函數定義中聲明的局部變數的生命期也結束了。在棧中分配的局部量佔用的資源也被釋放,由系統回收。

3.google出的C++編碼規範 英文版

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#File_Names

Google Objective-C Style Guide 中文版

http://www.cocoachina.com/macdev/objc/2011/0328/2740.html

4.ios編碼規範摘要

4.1.格式化代碼

     *號的位置

     括弧對齊

      方法名和參數間不留空格

      當參數過長時,每個參數佔用一行,以冒號對齊;如果方法名比參數名短,每個參數佔用一行,至少縮排4個字元,且為垂直對齊(而非使用冒號對齊)

      使用分段宏,註明函數來源

4.2.命名

       類名使用首字母大寫的形式分割單詞,camel case,駝峰式命令法。
       在面向特定應用的代碼中,類名應盡量避免使用首碼,每個類都使用相同的首碼影響可讀性。
       在面向多應用的代碼中,推薦使用首碼,這可以避免重名,還聲明了代碼來源。如:GTMSendMessage

       方法名的首字母小寫,且使用首字母大寫的形式分割單詞。方法的參數使用相同的規則。
       方法名+參數應盡量讀起來像一句話(如:)。在這裡查看蘋果對方法命名的規範。
       getter的方法名和變數名應相同。不允許使用“get”首碼。
        本規則僅針對Objective-C代碼,C++代碼使用C++的習慣 

       變數名應使用容易意會的應用全稱,且首字母小寫,且使用首字母大寫的形式分割單詞,參照symbian,參數以a開頭。
       成員變數使用“_”作為首碼(如:“NSString *_varName;”。雖然這與蘋果的標準(使 
用“_”作為尾碼)相衝突,但基於以下原因,仍使用“_”作為首碼。
 使用“_”作為首碼,更容易在有代碼自動補全功能的IDE中區分“屬性 
(self.userInfo)”和“成員變數(_userInfo)” 

       與去掉“_”首碼的成員變數相同,使用@synthesize將二者聯絡起來
       常量(#define, enums, const等)使用小寫“k”作為首碼,首字母大寫來分割單詞。如:  kInvalidHandle

       以 alloc/new/copy/mutableCopy 開頭的函數,只產生對象,不是其持有人。

4.3.邏輯

       在初始化方法中,不要將變數初始化為“0”或“nil”,那是多餘的。但在c++中完全必須初始化。
       使用#import引入Ojbective-C和Ojbective-C++標頭檔,使用#include引入C和C++頭 檔案
       import根架構(root frameworks),而非各單個檔案
, 雖然有時我們僅需要架構(如Cocoa 或 Foundation)的某幾個標頭檔,但引入根檔案編譯
器會啟動並執行更快。因為根架構(root frameworks)一般會先行編譯,所以載入會更快。
        建立臨時對象時,盡量同時在同一行中 autorelease 掉,而非使用單獨的 release 語句
        雖然這樣會稍微有點慢,但這樣可以阻止因為提前 return 或其他意外情況導致的記憶體泄露。 
   通盤來看這是值得的。如:
        dealloc的順序要與變數聲明的順序相同
, 這有利於review代碼
,如果dealloc中調用其他方法來release變數,將被release的變數以注釋的形式標註清楚

       NSString的屬性的setter使用“copy” ,禁止使用retain,以防止意外的修改了NSString變數的值。如:
       避免拋出異常(Throwing Exceptions)
       對 nil 的檢查
 僅在有商務邏輯需求時檢查nil,而非為了防止崩潰
       向 nil 發送訊息不會導致系統崩潰,Objective-C運行時負責處理。
       將int值轉換為BOOL時應特別小心。避免直接和YES比較
       Objective-C中,BOOL被定義為unsigned char,這意味著除了 YES(1) 和NO(0)外它 
還可以是其他值。禁止將int直接轉換(cast or convert)為BOOL。
       delegate對象使用assign,禁止使用retain。因為retain會導致迴圈索引導致記憶體泄露, 
並且此類型的記憶體泄露無法被Instrument發現,極難調試
       成員變數命名為_delegate,屬性名稱為delegate 
◦

       不要在與view相關的類中添加過多的商務邏輯代碼,這讓代碼的可重用性很差 
 Controller負責商務邏輯代碼,且Controller的代碼與view盡量無關

       如果並非所有回調方法都是必須的,使用@optional標示

        init方法和dealloc方法是是最常用的方法,所以將他們放在類實現的開始位置

        對某個類擴充功能時優先使用增加類別。

5.標準命名規範

http://blog.csdn.net/bill1315/article/details/1698202

命名方法:
(1),駱駝(Camel)命名法:第一個字母小寫,隨後的每個單詞的第一個字母大寫。如:studentName
(2),帕斯卡(Pascal)命名法:每一個單詞的第一個字母都大寫。如:StudentName
(3),匈牙利命名法:加首碼。如btnName,txtName.

6.對網路請求對象的處理要點:

  引用request控制代碼,

  在請求結束後request=nil,

  在析構中和其它需要的地方 request.delegate=nil; [request cancel]; request=nil;

7.防禦式編程的要求使用NSAssert語句來保證一些必不可錯的錯誤發生,比如參數屬於正確的類。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.