1. 統一的編碼規範
編碼規範往簡單說其實就是三個方面:
- 換行
- 空格
- 變數命名
放在 PHP 裡面,還有一些附加的地方,比如關鍵字大小寫,語法糖的使用(array()
與 []
等)的問題。之前整理過 PSR 的標準,也找過 php-cs-fixer 這樣的工具。這些都是規範程式碼的重要手段。有統一的標準,配合上工具的檢查,形成統一的編碼約束不是什麼難題。
沒有規範,不同的人甚至同一個人在空格、換行和命名上都有可能是十分隨意的。程式碼一長,回使整個檔案看起來無比雜亂。
典型的例子比如:if
和 else
的組合,可以寫出無數種風格,比如:
1 2 3 4 5 6 7 8 9 10 11 12 |
# 單語句不寫大括號 if (true) doSomething(); # else 大括號換行 十分佔篇幅 if (true) { doSomething(); } else { doElseThings(); } # 此外還有關鍵字後不帶空格,隨意縮排等等 # ... |
再比如變數函式命名的問題上,各種混搭風格層出不窮:
1 2 3 4 5 6 7 8 9 |
# 全小寫 $someparam1 = null; # 首字母下環線 $_some_param_1 = null; # 某些庫的類,下劃線和大小寫混用 class Abstract_ClassA { } |
這裡並不探討各種寫法的優缺點,只是風格需要保持統一,不要混用。
2. 良好的編碼習慣
如果你仔細看過 PSR 的標準,可能也會注意到某些地方其實是標準無法涉及到的。比如一個超長的表示式在什麼時候換行,如何縮排等。
這裡涉及到的就是編碼習慣的約束問題。
比如方法的鏈式的呼叫的問題,比如某些資料庫查詢的封裝:
1 2 3 4 5 6 7 8 9 10 |
# 不換行的情況下句子會很長 $result = $this->db->select('id')->where('a', 1) ->groupBy('a')->orderBy('id', 'DESC')->result(); # 這種情況下我建議是一個條件一行,保持縮排 $result = $this->db->select('id') ->where('a', 1) ->groupBy('a') ->orderBy('id', 'DESC') ->result(); |
還有陣列定義,某些陣列成員字串很長的情況下的寫法:
1 2 3 4 5 6 7 8 9 |
$array = ['abcdefg', 'acbdfeg', 'bcadgfe', 'cdadgef']; # 如果成員太長,我建議拆解,這樣 $array = [ 'abcdefg', 'acbdfeg', 'bcadgfe', 'cdadgef', ]; |
3. 尋找最優的寫法
寫程式碼的過程中,最優的寫法和編碼習慣又不是同一件事情。這裡要說的指的是如何遵循 PHP 的語言特性或者框架的特徵,充分發揮語言和框架的能力來減少冗餘。
比如在獲取前端傳入的引數的時候,很多時候能見到這樣的程式碼:
1 |
$param = isset($_POST['param']) ? $_POST['param'] : ''; |
更有甚者一些框架將前端傳入的引數封裝了一層,比如 $this->request->data['param']
,如果再去用 isset
或者 array_key_exists
判斷,整個獲取引數的語句就會變得很長。
某些情況下使用三元運算子的時候需要注意 ?:
是可以合併使用的。
其實我們應該去嘗試封裝這種寫法,防止同樣的變數出現在一個語句中多次的情況。對於預設值的賦予,可以調研框架是否有封裝提供,或者通過強制型別轉換的方式進行。
還有一種情況是條件和迴圈巢狀的時候。比如從陣列裡抽取某一個欄位,或者對某一個欄位的值進行處理的時候,善用 array_map
以及引用(&
)往往能節省不少工作量。但是使用的時候也要注意陣列指標最後的位置。
在根據條件返回結果時,需要善用 return
。還有就是合理的抽象與封裝。
4. review 自己的程式碼
除了以上提到的在日常開發中需要注意的一些問題。還有就是事後的工作。
我相信很多人在看自己以前的程式碼的時候都有一種其實有更好的寫法的感覺。隨著時間的推移自己總會有更豐富的閱歷,更多的想法。偶爾 review 自己的程式碼也是對過去的總結,也許會有新的感知。
5. 推廣給你的隊友
團隊專案中,隊友的配合對整個程式碼的規範起著決定性的作用。一個團隊中有一個人不遵守規範,而又要到處修改程式碼的時候,很快就能破壞到所有的約束。
有統一的標準,有良好的執行力才能完成這件工作。