国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHPer這樣寫代碼也許更優雅

kidsamong / 1119人閱讀

摘要:前言轉眼間成為一名已經快整整兩年了,在這期間也對如何寫出可讀性高,便于擴展的代碼有了一些自己的想法。所以,我們在寫上游代碼時異常直接拋出即可。通常這樣可以很大程度的提高效率和代碼復用。

前言

轉眼間成為一名PHPer已經快整整兩年了,在這期間也對如何寫出可讀性高,便于擴展的代碼有了一些自己的想法。

使用引用

場景一:遍歷一個數組獲取新的數據結構

也許你會這樣寫:

// 申明一個新的數組,組裝成你想要的數據
$tmp = [];
foreach ($arr as $k => $v) {
    // 取出你想要的數據
    $tmp[$k]["youwant"] = $v["youwant"];
    ...
    // 一系列判斷得到你想要的數據
    if (...) {
        $tmp[$k]["youwantbyjudge"] = "TIGERB";
    }
    ...
}
// 最后得要你想要的數組$tmp

-------------------------------------------------------

// 也許你覺著上面的寫法不是很好,那我們下面換種寫法
foreach ($arr as $k => $v) {
    // 一系列判斷得到你想要的數據
    if (...) {
        // 復寫值為你想要的
        $arr[$k]["youwantbyjudge"] = "TIGERB"
    }
    ...
    // 干掉你不想要的結構
    unset($arr[$k]["youwantdel"]);
}
// 最后我們得到我們的目標數組$arr

接下來我們使用引用值:

foreach ($arr as &$v) {
    // 一系列判斷得到你想要的數據
    if (...) {
        // 復寫值為你想要的
        $v["youwantbyjudge"] = "TIGERB"
    }
    ...
    // 干掉你不想要的結構
    unset($v["youwantdel"]);
}
unset($v);
// 最后我們得到我們的目標數組$arr

使用引用是不是使我們的代碼更加的簡潔,除此之外相對于第一種寫法,我們節省了內存空間,尤其是再操作一個大數組時效果是及其明顯的。

場景二:傳遞一個值到一個函數中獲取新的值

基本和數組遍歷一致,我們只需要聲明這個函數的這個參數為引用即可,如下:

function decorate(&$arr = []) {
    # code...
}

$arr = [
    ....
];
// 調用函數
decorate($arr);
// 如上即得到新的值$arr,好處還是節省內存空間
使用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);
            // 如果需要的話,我們可以在這里統一commit數據庫事務
            // $db->commit();
        } catch (Exception $e) {
            // 如果需要的話,我們可以在這里統一rollback數據庫事務
            // $db->rollback();
            return [
                "code"    => $e->getCode(),
                "message" => $e->getMessage()
            ]
        }
    }
}

通過使用try...catch...使我們的代碼邏輯更加清晰,try...里只需要關注業務正常的情況,異常的處理統一在catch中。所以,我們在寫上游代碼時異常直接拋出即可。

使用匿名函數

構建函數或方法內部的代碼塊

假如我們有一段邏輯,在一個函數或者方法里我們需要格式化數據,但是這個格式化數據的代碼片段出現了多次,如果我們直接寫可能會想下面這樣:

function doSomething(...) {
    ...
    // 格式化代碼段
    ...
    ...
    // 格式化代碼段[重復的代碼]
    ...
}

我相信大多數的人應該不會像上面這么寫,可能都會像下面這樣:

function doSomething(...) {
    ...
    format(...);
    ...
    format(...);
    ...
}

// 再聲明一個格式花代碼的函數或方法
function format() {
    // 格式化代碼段
    ...
}

上面這樣的寫法沒有任何的問題,最小單元化我們的代碼片段,但是如果這個format函數或者方法只是doSomething使用呢?我通常會像下面這么寫,為什么?因為我認為在這種上下文的環境中format和doSomething的一個子集。

function doSomething() {
    ...
    $package = function (...) use (...) { // 同樣use后面的參數也可以傳引用
        // 格式化代碼段
        ...
    };
    ...
    package(...);
    ...
    package(...);
    ...
}

實現類的【懶加載】和實現設計模式的【最少知道原則】

假如有下面這段代碼:

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的實例不是所有的上下文都會用到,所以浪費了資源,有人說搞個單例,但是解決不了實例化了不用的尷尬

所以我們使用匿名函數解決上面的問題,下面我們這么改寫:

class One
{
    private $closure;

    public function __construct(Closure $closure)
    {  
        $this->closure = $closure;
    }

    public function doSomething()
    {
        if (...) {
            // 用的時候再實例化
            // 實現懶加載
            $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異常 

細心的你可能會發現上面這種情況,可能絕大多數else代碼里都是在處理異常情況,更有可能這個異常代碼特別簡單,通常我會這么去做:

// 如果是在一個函數里面我會先處理異常的情況,然后提前return代碼,最后再執行正常的邏輯
function doSomething() {
    if (...) {
        // 異常情況
        return ...;
    }
    if (...) {
        // 異常情況
        return ...;
    }
    // 正常邏輯
    ...
}

// 同樣,如果是在一個類里面我會先處理異常的情況,然后先拋出異常
class One
{
    public function doSomething()
    {
        if (...) {
            // 異常情況
            throw new Exception(...);
        }
        if (...) {
            // 異常情況
            throw new Exception(...);
        }
        // 正常邏輯
        ...
    }
}

關聯數組做map 

如果我們在客戶端做決策,通常我們會判斷不同的上下文在選擇不同策略,通常會像下面一樣使用if或者switch判斷:

class One
{
    public function doSomething()
    {
        if (...) {
            $instance = new A();
        } elseif (...) {
            $instance = new A();
        } else {
            $instance = new C();
        }
        $instance->doSomething(...);
        ...
    }
}

上面的寫法通常會出現大量的if語句或者switch語句,通常我會使用一個map來映射不同的策略,像下面這樣:

class One
{
    private $map = [
        "a" => "namespaceA", // 帶上命名空間,因為變量是動態的
        "b" => "namespaceB",
        "c" => "namespaceC"
    ];
    public function doSomething()
    {
        ...
        $instance = new $this->map[$strategy];// $strategy是"a"或"b"或"c"
        $instance->doSomething(...);
        ...
    }
}
使用接口

為什么要使用接口?極大的便于后期的擴展和代碼的可讀性,例如設計一個優惠系統,不同的商品只是在不同的優惠策略下具備不同的優惠行為,我們定義一個優惠行為的接口,最后對這個接口編程即可,偽代碼如下

Interface Promotion
{
    public function promote(...);
}

class OnePromotion implement Promotion
{
    public function doSomething(...)
    {
        ...
    }
}

class TwoPromotion implement Promotion
{
    public function doSomething(...)
    {
        ...
    }
}
控制器拒絕直接的DB操作

最后我想說的是永遠拒絕在你的Controller里直接操作DB,為什么?我們的程序絕大多數的操作基本都是增刪改查,可能是查詢的where條件和字段不同,所以有時候我們可以抽象的把對數據庫增刪改查的方法寫到model中,通過參數暴露我們的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全棧框架

掃面下方二維碼關注我的技術公眾號,及時為大家推送我的原創技術分享

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30605.html

相關文章

  • 我的 2017 —— 一個 PHPer 的自白

    摘要:大會年,我去了。小會值得一提的是,今年月份,我參加了一個的分享會。出游沙巴這是部門組織的出游,獲得了最佳團隊,拿到了一筆經費,于是有了這次出游。于是,我的下個目的地是西藏。 轉眼間 2017 年過去了。我已經不能說自己是去年的畢業生了,時光匆匆,感覺自己越來越老了。 這一年,我所經歷的,讓我收獲很多,讓我懂得很多,讓我明白了很多。也許是明確了某一個目標,也許是其它的什么,我覺得,201...

    BenCHou 評論0 收藏0
  • tastphp,為現代化的 phper 準備的 PHP 框架

    摘要:大家好,推薦下我們團隊自己研發的框架為現代化的準備的。可拔插,擴展性強。借鑒了等優秀框架。有興趣的可以關注下。最渴望有人給我們提交。中文文檔基礎已經寫完,剩下努力寫中。。。 大家好,推薦下我們團隊自己研發的框架:tastphp 為現代化的phper準備的。可拔插,擴展性強。借鑒了Symfony、Laravel、Silex等優秀框架。 有興趣的可以關注下 tastphp。最渴望有人給...

    meteor199 評論0 收藏0
  • 轉:從框架看PHP的五種境界及各自的薪資待遇

    摘要:語言行為及特征狀態看不懂任何英語技術,英語文檔,凡事沒有培訓部在搞的,只有英文文檔的東西國內一律沒大公司在用,都非主流,排斥英文文檔和新技術,以及各種超出他學習能力范圍的技術。 在撰寫此文前首先必須申明的是本人不鄙視任何一種框架,也無意于挑起PHP框架間的戰爭,更沒有貶低某個框架使用者的用意,本文純粹個人的看法。你可以認為我無知也好,或者裝逼也好,請不要試著在任何情況下,隨便發起言語的...

    Godtoy 評論0 收藏0
  • Swoole 2019 :化繁為簡、破繭成蝶

    摘要:開發負責人創建分支,編寫單元測試腳本,編寫代碼,實現提案中的所有內容,最終發起交叉評審,檢查代碼,提出改進意見,反饋給開發負責人,繼續完善細節。 Swoole開源項目從2012年開始發布第一個版本,到現在已經有近7年的歷史。在這七年的時間里: 提交了8821次代碼變更 發布了287個版本 收到并解決1161次issue反饋 合并了603次pull request 共有100位開發者...

    adam1q84 評論0 收藏0
  • SegmentFault 技術周刊 Vol.40 - 2018,來學習一門新的編程語言吧!

    摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經到來了,總結過去的 2017,相信小伙們一定有很多收獲...

    caspar 評論0 收藏0

發表評論

0條評論

kidsamong

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<