摘要:前言轉眼間成為一名已經(jīng)快整整兩年了,在這期間也對如何寫出可讀性高,便于擴展的代碼有了一些自己的想法。所以,我們在寫上游代碼時異常直接拋出即可。通常這樣可以很大程度的提高效率和代碼復用。
前言
轉眼間成為一名PHPer已經(jīng)快整整兩年了,在這期間也對如何寫出可讀性高,便于擴展的代碼有了一些自己的想法。
使用引用場景一:遍歷一個數(shù)組獲取新的數(shù)據(jù)結構
也許你會這樣寫:
// 申明一個新的數(shù)組,組裝成你想要的數(shù)據(jù) $tmp = []; foreach ($arr as $k => $v) { // 取出你想要的數(shù)據(jù) $tmp[$k]["youwant"] = $v["youwant"]; ... // 一系列判斷得到你想要的數(shù)據(jù) if (...) { $tmp[$k]["youwantbyjudge"] = "TIGERB"; } ... } // 最后得要你想要的數(shù)組$tmp ------------------------------------------------------- // 也許你覺著上面的寫法不是很好,那我們下面換種寫法 foreach ($arr as $k => $v) { // 一系列判斷得到你想要的數(shù)據(jù) if (...) { // 復寫值為你想要的 $arr[$k]["youwantbyjudge"] = "TIGERB" } ... // 干掉你不想要的結構 unset($arr[$k]["youwantdel"]); } // 最后我們得到我們的目標數(shù)組$arr
接下來我們使用引用值:
foreach ($arr as &$v) { // 一系列判斷得到你想要的數(shù)據(jù) if (...) { // 復寫值為你想要的 $v["youwantbyjudge"] = "TIGERB" } ... // 干掉你不想要的結構 unset($v["youwantdel"]); } unset($v); // 最后我們得到我們的目標數(shù)組$arr
使用引用是不是使我們的代碼更加的簡潔,除此之外相對于第一種寫法,我們節(jié)省了內存空間,尤其是再操作一個大數(shù)組時效果是及其明顯的。
場景二:傳遞一個值到一個函數(shù)中獲取新的值
基本和數(shù)組遍歷一致,我們只需要聲明這個函數(shù)的這個參數(shù)為引用即可,如下:
function decorate(&$arr = []) { # code... } $arr = [ .... ]; // 調用函數(shù) decorate($arr); // 如上即得到新的值$arr,好處還是節(jié)省內存空間使用try...catch...
假如有下面一段邏輯:
class UserModel { public function login($username = "", $password = "") { code... if (...) { // 用戶不存在 return -1; } code... if (...) { // 密碼錯誤 return -2; } code... } } class UserController { public function login($username = "", $password = "") { $model = new UserModel(); $res = $model->login($username, $password); if ($res === -1) { return [ "code" => "404", "message" => "用戶不存在" ]; } if ($res === -2) { return [ "code" => "400", "message" => "密碼錯誤" ]; } code... } }
我們用try...catch...改寫后:
class UserModel { public function login($username = "", $password = "") { code... if (...) { // 用戶不存在 throw new Exception("用戶不存在", "404"); } code... if (...) { // 密碼錯誤 throw new Exception("密碼錯誤", "400"); } code... } } class UserController { public function login($username = "", $password = "") { try { $model = new UserModel(); $res = $model->login($username, $password); // 如果需要的話,我們可以在這里統(tǒng)一commit數(shù)據(jù)庫事務 // $db->commit(); } catch (Exception $e) { // 如果需要的話,我們可以在這里統(tǒng)一rollback數(shù)據(jù)庫事務 // $db->rollback(); return [ "code" => $e->getCode(), "message" => $e->getMessage() ] } } }
通過使用try...catch...使我們的代碼邏輯更加清晰,try...里只需要關注業(yè)務正常的情況,異常的處理統(tǒng)一在catch中。所以,我們在寫上游代碼時異常直接拋出即可。
使用匿名函數(shù)構建函數(shù)或方法內部的代碼塊
假如我們有一段邏輯,在一個函數(shù)或者方法里我們需要格式化數(shù)據(jù),但是這個格式化數(shù)據(jù)的代碼片段出現(xiàn)了多次,如果我們直接寫可能會想下面這樣:
function doSomething(...) { ... // 格式化代碼段 ... ... // 格式化代碼段[重復的代碼] ... }
我相信大多數(shù)的人應該不會像上面這么寫,可能都會像下面這樣:
function doSomething(...) { ... format(...); ... format(...); ... } // 再聲明一個格式花代碼的函數(shù)或方法 function format() { // 格式化代碼段 ... }
上面這樣的寫法沒有任何的問題,最小單元化我們的代碼片段,但是如果這個format函數(shù)或者方法只是doSomething使用呢?我通常會像下面這么寫,為什么?因為我認為在這種上下文的環(huán)境中format和doSomething的一個子集。
function doSomething() { ... $package = function (...) use (...) { // 同樣use后面的參數(shù)也可以傳引用 // 格式化代碼段 ... }; ... package(...); ... package(...); ... }
實現(xiàn)類的【懶加載】和實現(xiàn)設計模式的【最少知道原則】
假如有下面這段代碼:
class One { private $instance; // 類One內部依賴了類Two // 不符合設計模式的最少知道原則 public function __construct() { $this->intance = new Two(); } public function doSomething() { if (...) { // 如果某種情況調用類Two的實例方法 $this->instance->do(...); } ... } } ... $instance = new One(); $instance->doSomething(); ...
上面的寫法有什么問題?
不符合設計模式的最少知道原則,類One內部直接依賴了類Two
類Two的實例不是所有的上下文都會用到,所以浪費了資源,有人說搞個單例,但是解決不了實例化了不用的尷尬
所以我們使用匿名函數(shù)解決上面的問題,下面我們這么改寫:
class One { private $closure; public function __construct(Closure $closure) { $this->closure = $closure; } public function doSomething() { if (...) { // 用的時候再實例化 // 實現(xiàn)懶加載 $instance = $this->closure(); $instance->do(...) } ... } } ... $instance = new One(function () { // 類One外部依賴了類Two return new Two(); }); $instance->doSomething(); ...減少對if...else...的使用
如果你碰見下面這種類型的代碼,那一定是個黑洞。
function doSomething() { if (...) { if (...) { ... } esle { ... } } else { if (...) { ... } esle { ... } } }
提前return異?!?/strong>
細心的你可能會發(fā)現(xiàn)上面這種情況,可能絕大多數(shù)else代碼里都是在處理異常情況,更有可能這個異常代碼特別簡單,通常我會這么去做:
// 如果是在一個函數(shù)里面我會先處理異常的情況,然后提前return代碼,最后再執(zhí)行正常的邏輯 function doSomething() { if (...) { // 異常情況 return ...; } if (...) { // 異常情況 return ...; } // 正常邏輯 ... } // 同樣,如果是在一個類里面我會先處理異常的情況,然后先拋出異常 class One { public function doSomething() { if (...) { // 異常情況 throw new Exception(...); } if (...) { // 異常情況 throw new Exception(...); } // 正常邏輯 ... } }
關聯(lián)數(shù)組做map
如果我們在客戶端做決策,通常我們會判斷不同的上下文在選擇不同策略,通常會像下面一樣使用if或者switch判斷:
class One { public function doSomething() { if (...) { $instance = new A(); } elseif (...) { $instance = new A(); } else { $instance = new C(); } $instance->doSomething(...); ... } }
上面的寫法通常會出現(xiàn)大量的if語句或者switch語句,通常我會使用一個map來映射不同的策略,像下面這樣:
class One { private $map = [ "a" => "namespaceA", // 帶上命名空間,因為變量是動態(tài)的 "b" => "namespaceB", "c" => "namespaceC" ]; public function doSomething() { ... $instance = new $this->map[$strategy];// $strategy是"a"或"b"或"c" $instance->doSomething(...); ... } }使用接口
為什么要使用接口?極大的便于后期的擴展和代碼的可讀性,例如設計一個優(yōu)惠系統(tǒng),不同的商品只是在不同的優(yōu)惠策略下具備不同的優(yōu)惠行為,我們定義一個優(yōu)惠行為的接口,最后對這個接口編程即可,偽代碼如下
Interface Promotion { public function promote(...); } class OnePromotion implement Promotion { public function doSomething(...) { ... } } class TwoPromotion implement Promotion { public function doSomething(...) { ... } }控制器拒絕直接的DB操作
最后我想說的是永遠拒絕在你的Controller里直接操作DB,為什么?我們的程序絕大多數(shù)的操作基本都是增刪改查,可能是查詢的where條件和字段不同,所以有時候我們可以抽象的把對數(shù)據(jù)庫增刪改查的方法寫到model中,通過參數(shù)暴露我們的where,fields條件。通常這樣可以很大程度的提高效率和代碼復用。比如像下面這樣:
class DemoModel implement Model { public function getMultiDate($where = [], $fields = ["id"], $orderby = "id asc") { $this->where($where) ->field($fields) ->orderby($orderby) ->get(); } }最后
如果有寫的不對的地方,歡迎大家指正,THX~
Easy PHP:一個極速輕量級的PHP全??蚣?/pre>掃面下方二維碼關注我的技術公眾號,及時為大家推送我的原創(chuàng)技術分享
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/30605.html
摘要:大會年,我去了。小會值得一提的是,今年月份,我參加了一個的分享會。出游沙巴這是部門組織的出游,獲得了最佳團隊,拿到了一筆經(jīng)費,于是有了這次出游。于是,我的下個目的地是西藏。 轉眼間 2017 年過去了。我已經(jīng)不能說自己是去年的畢業(yè)生了,時光匆匆,感覺自己越來越老了。 這一年,我所經(jīng)歷的,讓我收獲很多,讓我懂得很多,讓我明白了很多。也許是明確了某一個目標,也許是其它的什么,我覺得,201...
摘要:大家好,推薦下我們團隊自己研發(fā)的框架為現(xiàn)代化的準備的??砂尾澹瑪U展性強。借鑒了等優(yōu)秀框架。有興趣的可以關注下。最渴望有人給我們提交。中文文檔基礎已經(jīng)寫完,剩下努力寫中。。。 大家好,推薦下我們團隊自己研發(fā)的框架:tastphp 為現(xiàn)代化的phper準備的。可拔插,擴展性強。借鑒了Symfony、Laravel、Silex等優(yōu)秀框架。 有興趣的可以關注下 tastphp。最渴望有人給...
摘要:語言行為及特征狀態(tài)看不懂任何英語技術,英語文檔,凡事沒有培訓部在搞的,只有英文文檔的東西國內一律沒大公司在用,都非主流,排斥英文文檔和新技術,以及各種超出他學習能力范圍的技術。 在撰寫此文前首先必須申明的是本人不鄙視任何一種框架,也無意于挑起PHP框架間的戰(zhàn)爭,更沒有貶低某個框架使用者的用意,本文純粹個人的看法。你可以認為我無知也好,或者裝逼也好,請不要試著在任何情況下,隨便發(fā)起言語的...
摘要:開發(fā)負責人創(chuàng)建分支,編寫單元測試腳本,編寫代碼,實現(xiàn)提案中的所有內容,最終發(fā)起交叉評審,檢查代碼,提出改進意見,反饋給開發(fā)負責人,繼續(xù)完善細節(jié)。 Swoole開源項目從2012年開始發(fā)布第一個版本,到現(xiàn)在已經(jīng)有近7年的歷史。在這七年的時間里: 提交了8821次代碼變更 發(fā)布了287個版本 收到并解決1161次issue反饋 合并了603次pull request 共有100位開發(fā)者...
摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數(shù)式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來了,總結過去的 2017,相信小伙們一定有很多收獲...
閱讀 1436·2021-09-22 15:00
閱讀 3369·2019-08-30 14:00
閱讀 1313·2019-08-29 17:27
閱讀 1294·2019-08-29 16:35
閱讀 774·2019-08-29 16:14
閱讀 2109·2019-08-26 13:43
閱讀 2194·2019-08-26 11:35
閱讀 2400·2019-08-23 15:34