好的代碼組織方式只是為了更好看嗎?
原創(chuàng)程序猿隊伍里面不乏【差不多】先生:代碼寫出來能用就行了;開發(fā)環(huán)境能用就行了;上線前隨便測測就行了;你要我再給你就行了...這些態(tài)度不僅惱人,而且對于產(chǎn)品質(zhì)量、團隊協(xié)作來說都是危害甚大,這在初創(chuàng)項目中結(jié)果特別明顯。今天只談代碼,為啥捏?因為有個槽它不吐不快啊!作者也算見過點世面的了,但是還是被惱到了。
話說最近作者被派到了一個活兒,需要使用NetSuite的API來自動將網(wǎng)站的客戶導(dǎo)入NetSuite系統(tǒng)里管理。NetSuite在CRM系統(tǒng)里也算個比較知名的大牌了,據(jù)說是Oracle傳授的管理經(jīng)驗,功能也著實強大。然后作者就開始研究SuiteTalk PHP Toolkit,看了半天的文檔,大概明白了一些業(yè)務(wù)流程做了一些準(zhǔn)備工作,就等著用這API進行神圣的***次Web Service交互。洋洋灑灑寫下了一些調(diào)試代碼開始試驗。結(jié)果你能想到,我瘋了。一個開源庫有3個文件,一個config,一個基礎(chǔ)類加工具函數(shù),***一個就是將近14W行代碼大小2MB多的php文件,幾乎所有的類都寫在一個文件里面了。其實這也還好,不就是看代碼會費事點么。重點是這個:
請注意這個庫是沒有命名空間的,類名也沒有任何的前綴。敢問猴兒們做的項目里,有多少個項目是沒有個Customer類?引入外部庫是為了改自家的類名么?當(dāng)然了,如果你的項目里本身就引入了命名空間,這個問題影響不大;但是大家手頭在維護的項目里,大多都有超過幾年的歷史代碼,也就是有很大幾率是沒有命名空間的。
后來作者為了解決這個命名沖突問題找到了一個樂于奉獻的程序員,他幫忙把這個API整理成了命名空間+composer安裝的方式(https://github.com/ryanwinchester/netsuite-php)。缺點就是沒有實現(xiàn)Token Based Authentication,也沒關(guān)系,繼承一下加進去。哎,上回說到不要隨便用private成員(http://zhuanlan.51cto.com/art/201606/513531.htm),這會又碰到了,為了順利繼承,不得不把所有的private成員都拷一遍到自己寫的繼承類里。
作者理解猴兒的成長需要過程,需要不斷試錯方能練成九陰白骨爪。因為自己也是這么過來的,雖然白骨爪還沒有,豉汁鳳爪倒是有一對。但是像NetSuite這樣的大品牌弄出這么青澀的庫還真是很少見。
上面的描述略帶夸張,開心呢您就笑一笑。話說回來,【差不多】先生和NetSuite都可以來看看關(guān)于代碼組織方式這件事上,是不是湊合就可以了。這就要說到現(xiàn)今流行的幾種方式了,PSR系列(PHP Standards Recomendations)。
PSR-0在2014年10月21日已經(jīng)被標(biāo)志為淘汰過時了,現(xiàn)在推薦的是PSR-4,我們看到composer里面還保留著對PSR-0的支持。
PSR-0,Autoloading Standard
文件的結(jié)構(gòu)為Vendor\(Namespace)*\ClassName.php;每個命名空間的最頂層空間一定是Vendor,例如對于NetSuite來說,NetSuite就應(yīng)該是它的最頂層命名空間;中間 可以有無數(shù)層命名空間;命名空間的分隔符會在找相應(yīng)類文件時轉(zhuǎn)換為系統(tǒng)的文件夾分隔符;類***的下劃線 _ 對應(yīng)著更深的文件夾層級,但是不影響命名空間;
PSR-4,Autoloader
這里的類指代class,interface、trait和類似的結(jié)構(gòu);命名空間與文件的對應(yīng)結(jié)構(gòu)跟PSR-0是一樣的,除了在這個標(biāo)準(zhǔn)里下劃線沒有特別的作用,并且命名空間和文件名是大小寫敏感的;Autoloader的實現(xiàn)不可以拋出異常、錯誤,也不返回任何值。
命名空間主要就是解決命名沖突的問題。合理的運用命名空間,可以讓你的項目可具有擴展性,可維護性。寥寥草草的實現(xiàn),只會讓后期的開發(fā)維護成本越來越高。甚至現(xiàn)在你都不需要自己實現(xiàn)Autoloader,運用強大的composer,和遵循相關(guān)的理念就能讓你事半功倍。
PSR-1,Basic Coding Standard
這里說的是一些代碼的普遍標(biāo)準(zhǔn),它可以使得團隊相互協(xié)作變得更為順利。
只使用<?php 和 <?= 標(biāo)簽;所有代碼文件使用UTF-8編碼格式;一個文件要么做聲明(類,接口,公共函數(shù)等),要么做執(zhí)行之類的周邊工作(view,config等),不要一個文件同時做兩樣事情;命名空間和類根據(jù)PSR-0/PSR-4來組織;類命名首字母全大寫,其他字母小寫,例如 StudlyCaps;常亮用全大寫,用下劃線做分隔符;類方法用駝峰式命名,camelCase。
規(guī)則里面沒有規(guī)定變量怎么命名,團隊可以根據(jù)自己需要制定。小小的規(guī)則,卻可以讓團隊,開源項目以一種和諧的方式相互協(xié)作,減少因為多樣性而導(dǎo)致的內(nèi)耗是很有實際意義的。如果團隊里有程序猿一定要堅持自己的風(fēng)格,這個猴子的合作精神一定是有待提高的。事實上一個團隊各顧各的,失敗就是必然的了。
PSR-2,Coding Style Guide
這是對PSR-1補充和擴展。
代碼使用4個空格來縮進,而不是tab鍵(可以在IDE里面設(shè)置tab鍵轉(zhuǎn)換為4空格);一行的長度推薦80~120字符之間;namespace聲明塊后面要有一行空白,use聲明塊后面也要有一行空白;類和函數(shù)的花括號都獨占一行;所有的類成員和函數(shù)都要顯示聲明可見性(不要省略掉public);控制結(jié)構(gòu)的關(guān)鍵字后面留一個空格,函數(shù)調(diào)用后面不要留空(if (x), test());控制結(jié)構(gòu)的起始花括號與代碼同行,結(jié)束花括號新起一行;控制結(jié)構(gòu)的括號不要留空,例如if (x)。
當(dāng)然還有其他的一些推薦標(biāo)準(zhǔn),大家可以自行參考http://www.php-fig.org/psr/
說了這么多所謂的標(biāo)準(zhǔn),目的無非就是為了更好的協(xié)作。有人說,我自己一個人做的項目我做主就好了。也沒錯,不過養(yǎng)成這些習(xí)慣也沒有傷害,你咋知道你一不小心就做出了點啥可以拿出手的東西,不要等到那個時候再來整理代碼來交代吧?
所以說,好的代碼組織方式,真的不只是為了好看而已。