成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHPer這樣寫(xiě)代碼也許更優(yōu)雅

kidsamong / 1131人閱讀

摘要:前言轉(zhuǎn)眼間成為一名已經(jīng)快整整兩年了,在這期間也對(duì)如何寫(xiě)出可讀性高,便于擴(kuò)展的代碼有了一些自己的想法。所以,我們?cè)趯?xiě)上游代碼時(shí)異常直接拋出即可。通常這樣可以很大程度的提高效率和代碼復(fù)用。

前言

轉(zhuǎn)眼間成為一名PHPer已經(jīng)快整整兩年了,在這期間也對(duì)如何寫(xiě)出可讀性高,便于擴(kuò)展的代碼有了一些自己的想法。

使用引用

場(chǎng)景一:遍歷一個(gè)數(shù)組獲取新的數(shù)據(jù)結(jié)構(gòu)

也許你會(huì)這樣寫(xiě):

// 申明一個(gè)新的數(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

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

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

接下來(lái)我們使用引用值:

foreach ($arr as &$v) {
    // 一系列判斷得到你想要的數(shù)據(jù)
    if (...) {
        // 復(fù)寫(xiě)值為你想要的
        $v["youwantbyjudge"] = "TIGERB"
    }
    ...
    // 干掉你不想要的結(jié)構(gòu)
    unset($v["youwantdel"]);
}
unset($v);
// 最后我們得到我們的目標(biāo)數(shù)組$arr

使用引用是不是使我們的代碼更加的簡(jiǎn)潔,除此之外相對(duì)于第一種寫(xiě)法,我們節(jié)省了內(nèi)存空間,尤其是再操作一個(gè)大數(shù)組時(shí)效果是及其明顯的。

場(chǎng)景二:傳遞一個(gè)值到一個(gè)函數(shù)中獲取新的值

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

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

$arr = [
    ....
];
// 調(diào)用函數(shù)
decorate($arr);
// 如上即得到新的值$arr,好處還是節(jié)省內(nèi)存空間
使用try...catch...

假如有下面一段邏輯:

class UserModel
{
    public function login($username = "", $password = "")
    {
        code...
        if (...) {
            // 用戶不存在
            return -1;
        }
        code...
        if (...) {
            // 密碼錯(cuò)誤
            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" => "密碼錯(cuò)誤"
            ];
        }
        code...
    }
}

我們用try...catch...改寫(xiě)后:

class UserModel
{
    public function login($username = "", $password = "")
    {
        code...
        if (...) {
            // 用戶不存在
            throw new Exception("用戶不存在", "404");
        }
        code...
        if (...) {
            // 密碼錯(cuò)誤
            throw new Exception("密碼錯(cuò)誤", "400");
        }
        code...
    }
}

class UserController
{
    public function login($username = "", $password = "")
    {
        try {
            $model = new UserModel();
            $res   = $model->login($username, $password);
            // 如果需要的話,我們可以在這里統(tǒng)一commit數(shù)據(jù)庫(kù)事務(wù)
            // $db->commit();
        } catch (Exception $e) {
            // 如果需要的話,我們可以在這里統(tǒng)一rollback數(shù)據(jù)庫(kù)事務(wù)
            // $db->rollback();
            return [
                "code"    => $e->getCode(),
                "message" => $e->getMessage()
            ]
        }
    }
}

通過(guò)使用try...catch...使我們的代碼邏輯更加清晰,try...里只需要關(guān)注業(yè)務(wù)正常的情況,異常的處理統(tǒng)一在catch中。所以,我們?cè)趯?xiě)上游代碼時(shí)異常直接拋出即可。

使用匿名函數(shù)

構(gòu)建函數(shù)或方法內(nèi)部的代碼塊

假如我們有一段邏輯,在一個(gè)函數(shù)或者方法里我們需要格式化數(shù)據(jù),但是這個(gè)格式化數(shù)據(jù)的代碼片段出現(xiàn)了多次,如果我們直接寫(xiě)可能會(huì)想下面這樣:

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

我相信大多數(shù)的人應(yīng)該不會(huì)像上面這么寫(xiě),可能都會(huì)像下面這樣:

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

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

上面這樣的寫(xiě)法沒(méi)有任何的問(wèn)題,最小單元化我們的代碼片段,但是如果這個(gè)format函數(shù)或者方法只是doSomething使用呢?我通常會(huì)像下面這么寫(xiě),為什么?因?yàn)槲艺J(rèn)為在這種上下文的環(huán)境中format和doSomething的一個(gè)子集。

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

實(shí)現(xiàn)類的【懶加載】和實(shí)現(xiàn)設(shè)計(jì)模式的【最少知道原則】

假如有下面這段代碼:

class One
{
    private $instance;

    // 類One內(nèi)部依賴了類Two
    // 不符合設(shè)計(jì)模式的最少知道原則
    public function __construct()
    {  
        $this->intance = new Two();
    }

    public function doSomething()
    {
        if (...) {
            // 如果某種情況調(diào)用類Two的實(shí)例方法
            $this->instance->do(...);
        }
        ...
    }
}
...

$instance = new One();
$instance->doSomething();
...

上面的寫(xiě)法有什么問(wèn)題?

不符合設(shè)計(jì)模式的最少知道原則,類One內(nèi)部直接依賴了類Two

類Two的實(shí)例不是所有的上下文都會(huì)用到,所以浪費(fèi)了資源,有人說(shuō)搞個(gè)單例,但是解決不了實(shí)例化了不用的尷尬

所以我們使用匿名函數(shù)解決上面的問(wèn)題,下面我們這么改寫(xiě):

class One
{
    private $closure;

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

    public function doSomething()
    {
        if (...) {
            // 用的時(shí)候再實(shí)例化
            // 實(shí)現(xiàn)懶加載
            $instance = $this->closure();
            $instance->do(...)
        }
        ...
    }
}
...

$instance = new One(function () {
    // 類One外部依賴了類Two
    return new Two();
});
$instance->doSomething();
...
減少對(duì)if...else...的使用

如果你碰見(jiàn)下面這種類型的代碼,那一定是個(gè)黑洞。

function doSomething() {
    if (...) {
        if (...) {
            ...
        } esle {
            ...
        }
    } else {
        if (...) {
            ...
        } esle {
            ...
        }
    }
}

提前return異常 

細(xì)心的你可能會(huì)發(fā)現(xiàn)上面這種情況,可能絕大多數(shù)else代碼里都是在處理異常情況,更有可能這個(gè)異常代碼特別簡(jiǎn)單,通常我會(huì)這么去做:

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

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

關(guān)聯(lián)數(shù)組做map 

如果我們?cè)诳蛻舳俗鰶Q策,通常我們會(huì)判斷不同的上下文在選擇不同策略,通常會(huì)像下面一樣使用if或者switch判斷:

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

上面的寫(xiě)法通常會(huì)出現(xiàn)大量的if語(yǔ)句或者switch語(yǔ)句,通常我會(huì)使用一個(gè)map來(lái)映射不同的策略,像下面這樣:

class One
{
    private $map = [
        "a" => "namespaceA", // 帶上命名空間,因?yàn)樽兞渴莿?dòng)態(tài)的
        "b" => "namespaceB",
        "c" => "namespaceC"
    ];
    public function doSomething()
    {
        ...
        $instance = new $this->map[$strategy];// $strategy是"a"或"b"或"c"
        $instance->doSomething(...);
        ...
    }
}
使用接口

為什么要使用接口?極大的便于后期的擴(kuò)展和代碼的可讀性,例如設(shè)計(jì)一個(gè)優(yōu)惠系統(tǒng),不同的商品只是在不同的優(yōu)惠策略下具備不同的優(yōu)惠行為,我們定義一個(gè)優(yōu)惠行為的接口,最后對(duì)這個(gè)接口編程即可,偽代碼如下

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

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

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

最后我想說(shuō)的是永遠(yuǎn)拒絕在你的Controller里直接操作DB,為什么?我們的程序絕大多數(shù)的操作基本都是增刪改查,可能是查詢的where條件和字段不同,所以有時(shí)候我們可以抽象的把對(duì)數(shù)據(jù)庫(kù)增刪改查的方法寫(xiě)到model中,通過(guò)參數(shù)暴露我們的where,fields條件。通常這樣可以很大程度的提高效率和代碼復(fù)用。比如像下面這樣:

class DemoModel implement Model
{
    public function getMultiDate($where = [], $fields = ["id"], $orderby = "id asc")
    {
        $this->where($where)
             ->field($fields)
             ->orderby($orderby)
             ->get();
    }
}
最后

如果有寫(xiě)的不對(duì)的地方,歡迎大家指正,THX~

Easy PHP:一個(gè)極速輕量級(jí)的PHP全??蚣?/pre>

掃面下方二維碼關(guān)注我的技術(shù)公眾號(hào),及時(shí)為大家推送我的原創(chuàng)技術(shù)分享

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30605.html

相關(guān)文章

  • 我的 2017 —— 一個(gè) PHPer 的自白

    摘要:大會(huì)年,我去了。小會(huì)值得一提的是,今年月份,我參加了一個(gè)的分享會(huì)。出游沙巴這是部門(mén)組織的出游,獲得了最佳團(tuán)隊(duì),拿到了一筆經(jīng)費(fèi),于是有了這次出游。于是,我的下個(gè)目的地是西藏。 轉(zhuǎn)眼間 2017 年過(guò)去了。我已經(jīng)不能說(shuō)自己是去年的畢業(yè)生了,時(shí)光匆匆,感覺(jué)自己越來(lái)越老了。 這一年,我所經(jīng)歷的,讓我收獲很多,讓我懂得很多,讓我明白了很多。也許是明確了某一個(gè)目標(biāo),也許是其它的什么,我覺(jué)得,201...

    BenCHou 評(píng)論0 收藏0
  • tastphp,為現(xiàn)代化的 phper 準(zhǔn)備的 PHP 框架

    摘要:大家好,推薦下我們團(tuán)隊(duì)自己研發(fā)的框架為現(xiàn)代化的準(zhǔn)備的。可拔插,擴(kuò)展性強(qiáng)。借鑒了等優(yōu)秀框架。有興趣的可以關(guān)注下。最渴望有人給我們提交。中文文檔基礎(chǔ)已經(jīng)寫(xiě)完,剩下努力寫(xiě)中。。。 大家好,推薦下我們團(tuán)隊(duì)自己研發(fā)的框架:tastphp 為現(xiàn)代化的phper準(zhǔn)備的??砂尾澹瑪U(kuò)展性強(qiáng)。借鑒了Symfony、Laravel、Silex等優(yōu)秀框架。 有興趣的可以關(guān)注下 tastphp。最渴望有人給...

    meteor199 評(píng)論0 收藏0
  • 轉(zhuǎn):從框架看PHP的五種境界及各自的薪資待遇

    摘要:語(yǔ)言行為及特征狀態(tài)看不懂任何英語(yǔ)技術(shù),英語(yǔ)文檔,凡事沒(méi)有培訓(xùn)部在搞的,只有英文文檔的東西國(guó)內(nèi)一律沒(méi)大公司在用,都非主流,排斥英文文檔和新技術(shù),以及各種超出他學(xué)習(xí)能力范圍的技術(shù)。 在撰寫(xiě)此文前首先必須申明的是本人不鄙視任何一種框架,也無(wú)意于挑起PHP框架間的戰(zhàn)爭(zhēng),更沒(méi)有貶低某個(gè)框架使用者的用意,本文純粹個(gè)人的看法。你可以認(rèn)為我無(wú)知也好,或者裝逼也好,請(qǐng)不要試著在任何情況下,隨便發(fā)起言語(yǔ)的...

    Godtoy 評(píng)論0 收藏0
  • Swoole 2019 :化繁為簡(jiǎn)、破繭成蝶

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

    adam1q84 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.40 - 2018,來(lái)學(xué)習(xí)一門(mén)新的編程語(yǔ)言吧!

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

    caspar 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<