熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> PHP編程 >> 正文

從linux kernel coding style看php代碼規范

2013-11-15 12:21:56  來源: PHP編程 

  linux內核的編碼是一種極端情況

  需要清晰明朗以供全世界的開發者學習修改對代碼的質量要求較高

  相信linus大神在長期接觸各種各式代碼後脾氣會變得更暴躁就比如前段時間在某論壇痛斥C++

  節選去除不適合PHP程序員閱讀的部分

  如果你開發PHP程序的核心代碼比如框架尤其建議好好思考

  雖然它和一些權威的代碼規范比如discuz和zend的有所沖突但是依然能從中受益

  linux kernel coding style (針對PHPer作了節選)

  linux kernel coding style的中文譯者:

  中文版維護者 張樂 Zhang Le

  中文版翻譯者 張樂 Zhang Le

  中文版校譯者 王聰 Wang Cong

  wheelz

  管旭東 Xudong Guan

  Li Zefan

  Wang Chen

  第一章縮進

  制表符是個字符所以縮進也是個字符有些異端運動試圖將縮進變為(乃至)個字符深這幾乎相當於嘗試將圓周率的值定義為

  理由縮進的全部意義就在於清楚的定義一個控制塊起止於何處尤其是當你盯著你的屏幕連續看了小時之後你將會發現大一點的縮進會使你更容易分辨縮進

  現在有些人會抱怨個字符的縮進會使代碼向右邊移動的太遠個字符的終端屏幕上就很難讀這樣的代碼這個問題的答案是如果你需要級以上的縮進不管用何種方式你的代碼已經有問題了應該修正你的程序

  在switch語句中消除多級縮進的首選的方式是讓switch和從屬於它的case標簽對齊於同一列而不要兩次縮進case標簽比如

  C++代碼

  switch (suffix) {

  case G:

  case g:

  mem <<= ;

  break;

  case M:

  case m:

  mem <<= ;

  break;

  case K:

  case k:

  mem <<= ;

  /* fall through */

  default:

  break;

  }

  不要把多個語句放在一行裡除非你有什麼東西要隱藏

  C++代碼

  if (condition) do_this;

  do_something_everytime;

  也不要在一行裡放多個賦值語句內核代碼風格超級簡單就是避免可能導致別人誤讀的表達式

  除了注釋文檔和Kconfig之外不要使用空格來縮進前面的例子是例外是有意為之

  選用一個好的編輯器不要在行尾留空格

  第二章把長的行和字符串打散

  代碼風格的意義就在於使用平常使用的工具來維持代碼的可讀性和可維護性

  每一行的長度的限制是我們強烈建議您遵守這個慣例

  長於列的語句要打散成有意義的片段每個片段要明顯短於原來的語句而且放置的位置也明顯的靠右同樣的規則也適用於有很長參數列表的函數頭長字符串也要打散成較短的字符串唯一的例外是超過列可以大幅度提高可讀性並且不會隱藏信息的情況

  C++代碼

  void fun(int a int b int c)

  {

  if (condition)

  printk(KERN_WARNING Warning this is a long

   parameters a: %u b: %u

  c: %u \n a b c);

  else

  next_statement;

  }

  第三章大括號和空格的放置

  C語言風格中另外一個常見問題是大括號的放置和縮進大小不同選擇或棄用某種放置策略並沒有多少技術上的原因不過首選的方式就像Kernighan和Ritchie展示給我們的是把起始大括號放在行尾而把結束大括號放在行首所以

  C++代碼

  if (x is true) {

  we do y

  }

  這適用於所有的非函數語句塊(ifswitchforwhiledo)比如

  C++代碼

  switch (action) {

  case KOBJ_ADD:

  return add;

  case KOBJ_REMOVE:

  return remove;

  case KOBJ_CHANGE:

  return change;

  default:

  return NULL;

  }

  不過有一個例外那就是函數函數的起始大括號放置於下一行的開頭所以

  C++代碼

  int function(int x)

  {

  body of function

  }

  全世界的異端可能會抱怨這個不一致性是……呃……不一致的不過所有思維健全的人都知道(a)K&R是_正確的_並且(b)K&R是正確的此外不管怎樣函數都是特殊的(在C語言中函數是不能嵌套的)

  注意結束大括號獨自占據一行除非它後面跟著同一個語句的剩余部分也就是do語句中的while或者if語句中的else像這樣

  C++代碼

  do {

  body of doloop

  } while (condition);

  和

  C++代碼

  if (x == y) {

  

  } else if (x > y) {

  

  } else {

  

  }

  理由K&R

  也請注意這種大括號的放置方式也能使空(或者差不多空的)行的數量最小化同時不失可讀性因此由於你的屏幕上的新行是不可再生資源(想想行的終端屏幕)你將會有更多的空行來放置注釋

  當只有一個單獨的語句的時候不用加不必要的大括號

  C++代碼

  if (condition)

  action();

  這點不適用於本身為某個條件語句的一個分支的單獨語句這時需要在兩個分支裡都使用大括號

  C++代碼

  if (condition) {

  do_this();

  do_that();

  } else {

  otherwise();

  }

  空格

  Linux內核的空格使用方式(主要)取決於它是用於函數還是關鍵字(大多數)關鍵字後要加一個空格值得注意的例外是sizeoftypeofalignof和__attribute__這些關鍵字某些程度上看起來更像函數(它們在Linux裡也常常伴隨小括號而使用盡管在C語言裡這樣的小括號不是必需的就像struct fileinfo info聲明過後的sizeof info

  所以在這些關鍵字之後放一個空格

  if switch case for do while

  但是不要在sizeoftypeofalignof或者__attribute__這些關鍵字之後放空格例如

  C++代碼

  s = sizeof(struct file);

  不要在小括號裡的表達式兩側加空格這是一個反例

  C++代碼

  s = sizeof( struct file );

  當聲明指針類型或者返回指針類型的函數時*的首選使用方式是使之靠近變量名或者函

  數名而不是靠近類型名例子

  C++代碼

  char *linux_banner;

  unsigned long long memparse(char *ptr char **retptr);

  char *match_strdup(substring_t *s);

  在大多數二元和三元操作符兩側使用一個空格例如下面所有這些操作符

  C++代碼

  = + < > * / % | & ^ <= >= == != ? :

  但是一元操作符後不要加空格

  C++代碼

  & * + ~ ! sizeof typeof alignof __attribute__ defined

  後綴自加和自減一元操作符前不加空格

  ++

  前綴自加和自減一元操作符後不加空格

  ++

  >結構體成員操作符前後不加空格

  不要在行尾留空白有些可以自動縮進的編輯器會在新行的行首加入適量的空白然後你就可以直接在那一行輸入代碼不過假如你最後沒有在那一行輸入代碼有些編輯器就不會移除已經加入的空白就像你故意留下一個只有空白的行包含行尾空白的行就這樣產生了

  當git發現補丁包含了行尾空白的時候會警告你並且可以應你的要求去掉行尾空白不過如果你是正在打一系列補丁這樣做會導致後面的補丁失敗因為你改變了補丁的上下文

  第四章命名

  C是一個簡樸的語言你的命名也應該這樣和Modula和Pascal程序員不同C程序員不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字C程序員會稱那個變量為tmp這樣寫起來會更容易而且至少不會令其難於理解

  不過雖然混用大小寫的名字是不提倡使用的但是全局變量還是需要一個具描述性的名字稱一個全局函數為foo是一個難以饒恕的錯誤

  全局變量(只有當你真正需要它們的時候再用它)需要有一個具描述性的名字就像全局函數如果你有一個可以計算活動用戶數量的函數你應該叫它count_active_users()或者類似的名字你不應該叫它cntuser()

  在函數名中包含函數類型(所謂的匈牙利命名法)是腦子出了問題——編譯器知道那些類型而且能夠檢查那些類型這樣做只能把程序員弄糊塗了難怪微軟總是制造出有問題的程序

  本地變量名應該簡短而且能夠表達相關的含義如果你有一些隨機的整數型的循環計數器它應該被稱為i叫它loop_counter並無益處如果它沒有被誤解的可能的話類似的tmp可以用來稱呼任意類型的臨時變量

  如果你怕混淆了你的本地變量名你就遇到另一個問題了叫做函數增長荷爾蒙失衡綜合症請看第六章(函數)

  第六章函數

  函數應該簡短而漂亮並且只完成一件事情函數應該可以一屏或者兩屏顯示完(我們都知道ISO/ANSI屏幕大小是x只做一件事情而且把它做好

  一個函數的最大長度是和該函數的復雜度和縮進級數成反比的所以如果你有一個理論上很簡單的只有一個很長(但是簡單)的case語句的函數而且你需要在每個case裡做很多很小的事情這樣的函數盡管很長但也是可以的

  不過如果你有一個復雜的函數而且你懷疑一個天分不是很高的高中一年級學生可能甚至搞不清楚這個函數的目的你應該嚴格的遵守前面提到的長度限制使用輔助函數並為之取個具描述性的名字

  函數的另外一個衡量標准是本地變量的數量此數量不應超過否則你的函數就有問題了重新考慮一下你的函數把它分拆成更小的函數人的大腦一般可以輕松的同時跟蹤個不同的事物如果再增多的話就會糊塗了即便你聰穎過人你也可能會記不清你個星期前做過的事情

  在源文件裡使用空行隔開不同的函數

  第八章注釋

  注釋是好的不過有過度注釋的危險永遠不要在注釋裡解釋你的代碼是如何運作的更好

  的做法是讓別人一看你的代碼就可以明白解釋寫的很差的代碼是浪費時間

  一般的你想要你的注釋告訴別人你的代碼做了什麼而不是怎麼做的也請你不要把注釋

  放在一個函數體內部如果函數復雜到你需要獨立的注釋其中的一部分你很可能需要回到

  第六章看一看你可以做一些小注釋來注明或警告某些很聰明(或者槽糕)的做法但不要

  加太多你應該做的是把注釋放在函數的頭部告訴人們它做了什麼也可以加上它做這

  些事情的原因

  當注釋內核API函數時請使用kerneldoc格式請看

  Documentation/kerneldocnanoHOWTOtxt 和 scripts/kerneldoc 以獲得詳細信息

  Linux的注釋風格是C/* */風格不要使用C風格// 注釋

  長(多行)的首選注釋風格是

  C++代碼

  /*

  * This is the preferred style for multiline

  * comments in the Linux kernel source code

  * Please use it consistently

  *

  * Description: A column of asterisks on the left side

  * with beginning and ending almostblank lines

  */

  注釋數據也是很重要的不管是基本類型還是衍生類型為了方便實現這一點每一行應只

  聲明一個數據(不要使用逗號來一次聲明多個數據)這樣你就有空間來為每個數據寫一段

  小注釋來解釋它們的用途了

  對於PHPER來講最好遵循PHPDOC風格的注釋

  第九章你已經把事情弄糟了

  這沒什麼我們都是這樣可能你的使用了很長時間Unix的朋友已經告訴你GNU emacs

  自動幫你格式化C源代碼而且你也注意到了確實是這樣不過它所使用的默認值和我們

  想要的相去甚遠(實際上甚至比隨機打的還要差——無數個猴子在GNU emacs裡打字永遠不

  會創造出一個好程序)(譯注請參考Infinite Monkey Theorem)(對於PHPer可能就是zend studioeclipse之類的自動格式化工具)

  所以你要麼放棄GNU emacs要麼改變它讓它使用更合理的設定

  第十二章枚舉和RTL

  用於定義常量的宏的名字及枚舉裡的標簽需要大寫

  C++代碼

  #define CONSTANT x

  宏的名字請用大寫字母不過形如函數的宏的名字可以用小寫字母

  

  第十三章打印內核消息

  內核開發者應該是受過良好教育的請一定注意內核信息的拼寫以給人以好的印象不要

  用不規范的單詞比如dont而要用do not或者dont保證這些信息簡單明了

  歧義

  內核信息不必以句號(譯注英文句號即點)結束

  寫出好的調試信息可以是一個很大的挑戰當你寫出來之後這些信息在遠程除錯的時候當DEBUG符號沒有被定義的時候這些信息不應該被編譯進內核裡

  就會成為極大的幫助

  (也就是說默認地它們不應該被包含在內)(對於PHPer也是同樣)

  第十八章編輯器模式行和其他需要羅嗦的事情

  有一些編輯器可以解釋嵌入在源文件裡的由一些特殊標記標明的配置信息比如emacs

  能夠解釋被標記成這樣的行

  * mode: c *

  或者這樣的

  /*

  Local Variables:

  compilecommand: gcc DMAGIC_DEBUG_FLAG fooc

  End:

  */

  Vim能夠解釋這樣的標記

  /* vim:set sw= noet */

  這包括有關縮進和模式配置的標記人們可以使用他們自己定制的模

  式或者使用其他可以產生正確的縮進的巧妙方法

  不要在源代碼中包含任何這樣的內容每個人都有他自己的編輯器配置你的源文件不應

  該覆蓋別人的配置

  簡而言之個字符的縮進可以讓代碼更容易閱讀還有一個好處是當你的函數嵌套太深的

  時候可以給你警告留心這個警告


From:http://tw.wingwit.com/Article/program/PHP/201311/20805.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.