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

資訊專欄INFORMATION COLUMN

PHP代碼簡(jiǎn)潔之道——SOLID原則

PrototypeZ / 1478人閱讀

摘要:是推薦的便于記憶的首字母簡(jiǎn)寫(xiě),它代表了命名的最重要的五個(gè)面對(duì)對(duì)象編碼設(shè)計(jì)原則單一職責(zé)原則開(kāi)閉原則里氏替換原則接口隔離原則依賴反轉(zhuǎn)原則單一職責(zé)原則修改一個(gè)類應(yīng)該只為一個(gè)理由。別寫(xiě)重復(fù)代碼這條原則大家應(yīng)該都是比較熟悉了。

SOLID 是Michael Feathers推薦的便于記憶的首字母簡(jiǎn)寫(xiě),它代表了Robert Martin命名的最重要的五個(gè)面對(duì)對(duì)象編碼設(shè)計(jì)原則

S: 單一職責(zé)原則 (SRP)

O: 開(kāi)閉原則 (OCP)

L: 里氏替換原則 (LSP)

I: 接口隔離原則 (ISP)

D: 依賴反轉(zhuǎn)原則 (DIP)

單一職責(zé)原則 Single Responsibility Principle (SRP)

"修改一個(gè)類應(yīng)該只為一個(gè)理由"。人們總是易于用一堆方法塞滿一個(gè)類,如同我們?cè)陲w機(jī)上只能攜帶一個(gè)行李箱(把所有的東西都塞到箱子里)。這樣做的問(wèn)題是:從概念上這樣的類不是高內(nèi)聚的,并且留下了很多理由去修改它。將你需要修改類的次數(shù)降低到最小很重要。這是因?yàn)椋?dāng)有很多方法在類中時(shí),修改其中一處,你很難知曉在代碼庫(kù)中哪些依賴的模塊會(huì)被影響到。

Bad:

class UserSettings
{
    private $user;

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

    public function changeSettings($settings)
    {
        if ($this->verifyCredentials()) {
            // ...
        }
    }

    private function verifyCredentials()
    {
        // ...
    }
}

Good:

class UserAuth 
{
    private $user;

    public function __construct($user)
    {
        $this->user = $user;
    }
    
    public function verifyCredentials()
    {
        // ...
    }
}

class UserSettings 
{
    private $user;
    private $auth;

    public function __construct($user) 
    {
        $this->user = $user;
        $this->auth = new UserAuth($user);
    }

    public function changeSettings($settings)
    {
        if ($this->auth->verifyCredentials()) {
            // ...
        }
    }
}
開(kāi)閉原則 Open/Closed Principle (OCP)

正如Bertrand Meyer所述,"軟件的實(shí)體(類, 模塊, 函數(shù),等)應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。"這個(gè)原則是在說(shuō)明應(yīng)該允許用戶在不改變已有代碼的情況下增加新的功能。

Bad:

abstract class Adapter
{
    protected $name;

    public function getName()
    {
        return $this->name;
    }
}

class AjaxAdapter extends Adapter
{
    public function __construct()
    {
        parent::__construct();

        $this->name = "ajaxAdapter";
    }
}

class NodeAdapter extends Adapter
{
    public function __construct()
    {
        parent::__construct();

        $this->name = "nodeAdapter";
    }
}

class HttpRequester
{
    private $adapter;

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

    public function fetch($url)
    {
        $adapterName = $this->adapter->getName();

        if ($adapterName === "ajaxAdapter") {
            return $this->makeAjaxCall($url);
        } elseif ($adapterName === "httpNodeAdapter") {
            return $this->makeHttpCall($url);
        }
    }

    private function makeAjaxCall($url)
    {
        // request and return promise
    }

    private function makeHttpCall($url)
    {
        // request and return promise
    }
}

在上面的代碼中,對(duì)于HttpRequester類中的fetch方法,如果我新增了一個(gè)新的xxxAdapter類并且要在fetch方法中用到的話,就需要在HttpRequester類中去修改類(如加上一個(gè)elseif 判斷),而通過(guò)下面的代碼,就可很好的解決這個(gè)問(wèn)題。下面代碼很好的說(shuō)明了如何在不改變?cè)写a的情況下增加新功能。

Good:

interface Adapter
{
    public function request($url);
}

class AjaxAdapter implements Adapter
{
    public function request($url)
    {
        // request and return promise
    }
}

class NodeAdapter implements Adapter
{
    public function request($url)
    {
        // request and return promise
    }
}

class HttpRequester
{
    private $adapter;

    public function __construct(Adapter $adapter)
    {
        $this->adapter = $adapter;
    }

    public function fetch($url)
    {
        return $this->adapter->request($url);
    }
}
里氏替換原則 Liskov Substitution Principle (LSP)

對(duì)這個(gè)概念最好的解釋是:如果你有一個(gè)父類和一個(gè)子類,在不改變?cè)薪Y(jié)果正確性的前提下父類和子類可以互換。這個(gè)聽(tīng)起來(lái)讓人有些迷惑,所以讓我們來(lái)看一個(gè)經(jīng)典的正方形-長(zhǎng)方形的例子。從數(shù)學(xué)上講,正方形是一種長(zhǎng)方形,但是當(dāng)你的模型通過(guò)繼承使用了"is-a"的關(guān)系時(shí),就不對(duì)了。

Bad:

class Rectangle
{
    protected $width = 0;
    protected $height = 0;

    public function render($area)
    {
        // ...
    }

    public function setWidth($width)
    {
        $this->width = $width;
    }

    public function setHeight($height)
    {
        $this->height = $height;
    }

    public function getArea()
    {
        return $this->width * $this->height;
    }
}

class Square extends Rectangle
{
    public function setWidth($width)
    {
        $this->width = $this->height = $width;
    }

    public function setHeight(height)
    {
        $this->width = $this->height = $height;
    }
}

function renderLargeRectangles($rectangles)
{
    foreach ($rectangles as $rectangle) {
        $rectangle->setWidth(4);
        $rectangle->setHeight(5);
        $area = $rectangle->getArea(); // BAD: Will return 25 for Square. Should be 20.
        $rectangle->render($area);
    }
}

$rectangles = [new Rectangle(), new Rectangle(), new Square()];
renderLargeRectangles($rectangles);

Good:

abstract class Shape
{
    protected $width = 0;
    protected $height = 0;

    abstract public function getArea();

    public function render($area)
    {
        // ...
    }
}

class Rectangle extends Shape
{
    public function setWidth($width)
    {
        $this->width = $width;
    }

    public function setHeight($height)
    {
        $this->height = $height;
    }

    public function getArea()
    {
        return $this->width * $this->height;
    }
}

class Square extends Shape
{
    private $length = 0;

    public function setLength($length)
    {
        $this->length = $length;
    }

    public function getArea()
    {
        return pow($this->length, 2);
    }
}

function renderLargeRectangles($rectangles)
{
    foreach ($rectangles as $rectangle) {
        if ($rectangle instanceof Square) {
            $rectangle->setLength(5);
        } elseif ($rectangle instanceof Rectangle) {
            $rectangle->setWidth(4);
            $rectangle->setHeight(5);
        }

        $area = $rectangle->getArea(); 
        $rectangle->render($area);
    }
}

$shapes = [new Rectangle(), new Rectangle(), new Square()];
renderLargeRectangles($shapes);
接口隔離原則

接口隔離原則:"客戶端不應(yīng)該被強(qiáng)制去實(shí)現(xiàn)于它不需要的接口"。

有一個(gè)清晰的例子來(lái)說(shuō)明示范這條原則。當(dāng)一個(gè)類需要一個(gè)大量的設(shè)置項(xiàng),為了方便不會(huì)要求客戶端去設(shè)置大量的選項(xiàng),因?yàn)樵谕ǔK麄儾恍枰械脑O(shè)置項(xiàng)。使設(shè)置項(xiàng)可選有助于我們避免產(chǎn)生"胖接口"

Bad:

interface Employee
{
    public function work();

    public function eat();
}

class Human implements Employee
{
    public function work()
    {
        // ....working
    }

    public function eat()
    {
        // ...... eating in lunch break
    }
}

class Robot implements Employee
{
    public function work()
    {
        //.... working much more
    }

    public function eat()
    {
        //.... robot can"t eat, but it must implement this method
    }
}

上面的代碼中,Robot類并不需要eat()這個(gè)方法,但是實(shí)現(xiàn)了Emplyee接口,于是只能實(shí)現(xiàn)所有的方法了,這使得Robot實(shí)現(xiàn)了它并不需要的方法。所以在這里應(yīng)該對(duì)Emplyee接口進(jìn)行拆分,正確的代碼如下:

Good:

interface Workable
{
    public function work();
}

interface Feedable
{
    public function eat();
}

interface Employee extends Feedable, Workable
{
}

class Human implements Employee
{
    public function work()
    {
        // ....working
    }

    public function eat()
    {
        //.... eating in lunch break
    }
}

// robot can only work
class Robot implements Workable
{
    public function work()
    {
        // ....working
    }
}
依賴反轉(zhuǎn)原則 Dependency Inversion Principle (DIP)

這條原則說(shuō)明兩個(gè)基本的要點(diǎn):

高階的模塊不應(yīng)該依賴低階的模塊,它們都應(yīng)該依賴于抽象

抽象不應(yīng)該依賴于實(shí)現(xiàn),實(shí)現(xiàn)應(yīng)該依賴于抽象

這條起初看起來(lái)有點(diǎn)晦澀難懂,但是如果你使用過(guò)php框架(例如 Symfony),你應(yīng)該見(jiàn)過(guò)依賴注入(DI)對(duì)這個(gè)概念的實(shí)現(xiàn)。雖然它們不是完全相通的概念,依賴倒置原則使高階模塊與低階模塊的實(shí)現(xiàn)細(xì)節(jié)和創(chuàng)建分離。可以使用依賴注入(DI)這種方式來(lái)實(shí)現(xiàn)它。更多的好處是它使模塊之間解耦。耦合會(huì)導(dǎo)致你難于重構(gòu),它是一種非常糟糕的的開(kāi)發(fā)模式。

Bad:

class Employee
{
    public function work()
    {
        // ....working
    }
}

class Robot extends Employee
{
    public function work()
    {
        //.... working much more
    }
}

class Manager
{
    private $employee;

    public function __construct(Employee $employee)
    {
        $this->employee = $employee;
    }

    public function manage()
    {
        $this->employee->work();
    }
}

Good:

interface Employee
{
    public function work();
}

class Human implements Employee
{
    public function work()
    {
        // ....working
    }
}

class Robot implements Employee
{
    public function work()
    {
        //.... working much more
    }
}

class Manager
{
    private $employee;

    public function __construct(Employee $employee)
    {
        $this->employee = $employee;
    }

    public function manage()
    {
        $this->employee->work();
    }
}
別寫(xiě)重復(fù)代碼 (DRY)

這條原則大家應(yīng)該都是比較熟悉了。

盡你最大的努力去避免復(fù)制代碼,它是一種非常糟糕的行為,復(fù)制代碼通常意味著當(dāng)你需要變更一些邏輯時(shí),你需要修改不止一處。

Bad:

function showDeveloperList($developers)
{
    foreach ($developers as $developer) {
        $expectedSalary = $developer->calculateExpectedSalary();
        $experience = $developer->getExperience();
        $githubLink = $developer->getGithubLink();
        $data = [
            $expectedSalary,
            $experience,
            $githubLink
        ];

        render($data);
    }
}

function showManagerList($managers)
{
    foreach ($managers as $manager) {
        $expectedSalary = $manager->calculateExpectedSalary();
        $experience = $manager->getExperience();
        $githubLink = $manager->getGithubLink();
        $data = [
            $expectedSalary,
            $experience,
            $githubLink
        ];

        render($data);
    }
}

Good:

function showList($employees)
{
    foreach ($employees as $employee) {
        $expectedSalary = $employee->calculateExpectedSalary();
        $experience = $employee->getExperience();
        $githubLink = $employee->getGithubLink();
        $data = [
            $expectedSalary,
            $experience,
            $githubLink
        ];

        render($data);
    }
}

Very good:

function showList($employees)
{
    foreach ($employees as $employee) {
        render([
            $employee->calculateExpectedSalary(),
            $employee->getExperience(),
            $employee->getGithubLink()
        ]);
    }
}

后記:雖然OOP設(shè)計(jì)需要遵守如上原則,不過(guò)實(shí)際的代碼設(shè)計(jì)一定要簡(jiǎn)單、簡(jiǎn)單、簡(jiǎn)單。在實(shí)際編碼中要根據(jù)情況進(jìn)行取舍,一味遵守原則,而不注重實(shí)際情況的話,可能會(huì)讓你的代碼變的難以理解!

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/31978.html

相關(guān)文章

  • PHP代碼簡(jiǎn)潔之道——類和對(duì)象部分

    摘要:使用和在中,通過(guò)為屬性或方法設(shè)置和關(guān)鍵字可以實(shí)現(xiàn)對(duì)屬性或方法的可見(jiàn)性控制。你的繼承表達(dá)了一個(gè)對(duì)等比如人類是動(dòng)物的關(guān)系,不是包含的關(guān)系比如用戶具有用戶詳情你能從基類中復(fù)用代碼你想通過(guò)修改全局類來(lái)對(duì)所有派生類進(jìn)行修改。 使用getter和setter 在 PHP 中,通過(guò)為屬性或方法設(shè)置 public, protected 和 private 關(guān)鍵字可以實(shí)現(xiàn)對(duì)屬性或方法的可見(jiàn)性控制。不過(guò),...

    cyixlq 評(píng)論0 收藏0
  • PHP簡(jiǎn)潔之道

    摘要:另外一個(gè)嚴(yán)重的打擊是當(dāng)你需要排序測(cè)試的時(shí)候,在單元測(cè)試中這會(huì)是一個(gè)不小的麻煩。為什么因?yàn)槊總€(gè)單元測(cè)試都應(yīng)該依賴于另外一個(gè)。對(duì)于所有子類來(lái)說(shuō),在類中修改也是相當(dāng)危險(xiǎn)的。 前言 原文地址:https://github.com/jupeter/cl... 譯文地址:https://github.com/nineyang/c...,歡迎star。 變量 使用更有意義和更加直白的命名方式 不...

    lixiang 評(píng)論0 收藏0
  • PHP代碼簡(jiǎn)潔之道——函數(shù)部分

    摘要:超過(guò)三個(gè)參數(shù)會(huì)導(dǎo)致參數(shù)之間的組合過(guò)多,你必須對(duì)每個(gè)單獨(dú)的參數(shù)測(cè)試大量不同的情況。拆分這些函數(shù),可以讓代碼可重用性更高且更易測(cè)試。 函數(shù)參數(shù)不要超過(guò)兩個(gè) 限制函數(shù)的參數(shù)數(shù)量是非常重要的,因?yàn)樗鼓愕暮瘮?shù)更容易測(cè)試。超過(guò)三個(gè)參數(shù)會(huì)導(dǎo)致參數(shù)之間的組合過(guò)多,你必須對(duì)每個(gè)單獨(dú)的參數(shù)測(cè)試大量不同的情況。 沒(méi)有參數(shù)是最理想的情況,一個(gè)或兩個(gè)參數(shù)是可以接受的,三個(gè)以上則是應(yīng)該避免的。這很重要的。如果你...

    crossoverJie 評(píng)論0 收藏0
  • JavaScript 代碼簡(jiǎn)潔之道

    摘要:代碼質(zhì)量與其整潔度成正比。它讓你的代碼簡(jiǎn)潔優(yōu)雅。是幾個(gè)單詞首字母組合而來(lái),分別表示單一功能原則開(kāi)閉原則里氏替換原則接口隔離原則以及依賴反轉(zhuǎn)原則。開(kāi)閉原則開(kāi)指的就是類模塊函數(shù)都應(yīng)該具有可擴(kuò)展性,閉指的是它們不應(yīng)該被修改。 測(cè)試代碼質(zhì)量的唯一方式:別人看你代碼時(shí)說(shuō) f * k 的次數(shù)。 代碼質(zhì)量與其整潔度成正比。干凈的代碼,既在質(zhì)量上較為可靠,也為后期維護(hù)、升級(jí)奠定了良好基礎(chǔ)。 本文并不是...

    LinkedME2016 評(píng)論0 收藏0
  • JavaScript 代碼簡(jiǎn)潔之道

    摘要:代碼質(zhì)量與其整潔度成正比。它讓你的代碼簡(jiǎn)潔優(yōu)雅。是幾個(gè)單詞首字母組合而來(lái),分別表示單一功能原則開(kāi)閉原則里氏替換原則接口隔離原則以及依賴反轉(zhuǎn)原則。開(kāi)閉原則開(kāi)指的就是類模塊函數(shù)都應(yīng)該具有可擴(kuò)展性,閉指的是它們不應(yīng)該被修改。 測(cè)試代碼質(zhì)量的唯一方式:別人看你代碼時(shí)說(shuō) f * k 的次數(shù)。 代碼質(zhì)量與其整潔度成正比。干凈的代碼,既在質(zhì)量上較為可靠,也為后期維護(hù)、升級(jí)奠定了良好基礎(chǔ)。 本文并不是...

    鄒立鵬 評(píng)論0 收藏0

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

0條評(píng)論

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