baik hati


Gunakan lebih sedikit warisan dan lebih banyak kombinasi

Sama seperti Geng Seperti yang dinyatakan sebelum ini dalam Corak Reka Bentuk oleh Empat, kita harus cuba mengutamakan komposisi daripada warisan. Terdapat banyak faedah untuk menggunakan kedua-dua warisan dan komposisi. Perkara utama garis panduan ini ialah apabila anda secara naluri menggunakan warisan, cuba fikirkan sama ada komposisi mungkin memodelkan keperluan anda dengan lebih baik. Dalam sesetengah kes, ini adalah benar. Perkara seterusnya yang mungkin anda fikirkan ialah, "Jadi bilakah saya harus menggunakan warisan?" Jawapannya bergantung pada soalan anda, tetapi berikut adalah beberapa arahan apabila warisan lebih baik daripada komposisi:

Warisan anda menyatakan "Ya" a" bukannya "mempunyai hubungan" (manusia -> haiwan, pengguna -> butiran pengguna) Anda boleh menggunakan semula kod kelas asas (manusia boleh bergerak seperti haiwan)

Anda ingin mengubah suai kelas asas untuk semua kelas Terbitan buat pengubahsuaian global (ubah suai penggunaan tenaga haiwan apabila mereka bergerak)

Buruk:

 class Employee
{
    private $name;
    private $email;
 
    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
 
    // ...
}
 
 
// 不好,因为 Employees "有" taxdata
// 而 EmployeeTaxData 不是 Employee 类型的
 
 
class EmployeeTaxData extends Employee
{
    private $ssn;
    private $salary;
    
    public function __construct(string $name, string $email, string $ssn, string $salary)
    {
        parent::__construct($name, $email);
 
        $this->ssn = $ssn;
        $this->salary = $salary;
    }
 
    // ...
}
Baik:

class EmployeeTaxData
{
    private $ssn;
    private $salary;
 
    public function __construct(string $ssn, string $salary)
    {
        $this->ssn = $ssn;
        $this->salary = $salary;
    }
 
    // ...
}
 
class Employee
{
    private $name;
    private $email;
    private $taxData;
 
    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
 
    public function setTaxData(string $ssn, string $salary)
    {
        $this->taxData = new EmployeeTaxData($ssn, $salary);
    }
 
    // ...
}

2. Elakkan antara muka lancar ialah corak reka bentuk API yang direka untuk meningkatkan kebolehbacaan kod dalam pengaturcaraan berorientasikan objek Ia berdasarkan kaedah rantaian Perantaian kaedah

Jika terdapat konteks, kerumitan kod boleh dikurangkan, seperti PHPUnit Mock Builder dan. Pembina Pertanyaan Doktrin, walaupun terdapat beberapa konteks, sering membina objek, di mana corak ini mengurangkan verbositi kod (contohnya PHPUnit Mock Builder atau Doctrine Query Builder), lebih kerap ia datang pada beberapa kos:

1. Ia memecahkan enkapsulasi objek

2 Ia memecahkan corak penghias

3 Sukar untuk melakukan olok-olok dalam komponen ujian

4. perbezaan yang diserahkan ialah. tidak mudah dibaca

5. Untuk mengetahui lebih lanjut, sila baca Mengapa antara muka yang koheren buruk, oleh Marco Pivetta.

Buruk:
class Car
{
    private $make = 'Honda';
    private $model = 'Accord';
    private $color = 'white';
 
    public function setMake(string $make): self
    {
        $this->make = $make;
 
        // NOTE: Returning this for chaining
        return $this;
    }
 
    public function setModel(string $model): self
    {
        $this->model = $model;
 
        // NOTE: Returning this for chaining
        return $this;
    }
 
    public function setColor(string $color): self
    {
        $this->color = $color;
 
        // NOTE: Returning this for chaining
        return $this;
    }
 
    public function dump(): void
    {
        var_dump($this->make, $this->model, $this->color);
    }
}
 
$car = (new Car())
  ->setColor('pink')
  ->setMake('Ford')
  ->setModel('F-150')
  ->dump();

Baik:Fluent interface是一种 旨在提高面向对象编程时代码可读性的API设计模式,他基于方法链Method chaining

有上下文的地方可以降低代码复杂度,例如PHPUnit Mock Builder 和Doctrine Query Builder ,更多的情况会带来较大代价:

While there can be some contexts, frequently builder objects, where this pattern reduces the verbosity of the code (for example the PHPUnit Mock Builder or the Doctrine Query Builder), more often it comes at some costs:

1. 破坏了 对象封装

2. 破坏了 装饰器模式

3. 在测试组件中不好做mock

4. 导致提交的diff不好阅读

5. 了解更多请阅读 连贯接口为什么不好 ,作者 Marco Pivetta.

坏:

 class Car
{
    private $make = 'Honda';
    private $model = 'Accord';
    private $color = 'white';
 
    public function setMake(string $make): void
    {
        $this->make = $make;
    }
 
    public function setModel(string $model): void
    {
        $this->model = $model;
    }
 
    public function setColor(string $color): void
    {
        $this->color = $color;
    }
 
    public function dump(): void
    {
        var_dump($this->make, $this->model, $this->color);
    }
}
 
$car = new Car();
$car->setColor('pink');
$car->setMake('Ford');
$car->setModel('F-150');
$car->dump();

好:

final class Car
{
    private $color;
    
    public function __construct($color)
    {
        $this->color = $color;
    }
    
    /**
     * @return string The color of the vehicle
     */
    public function getColor()
    {
        return $this->color;
    }
}

3. 推荐使用 final 类

能用时尽量使用 final

 interface Vehicle
{
    /**
     * @return string The color of the vehicle
     */
    public function getColor();
}
 
final class Car implements Vehicle
{
    private $color;
    
    public function __construct($color)
    {
        $this->color = $color;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getColor()
    {
        return $this->color;
    }
}

. Adalah disyorkan untuk menggunakan kelas akhir

Gunakan kata kunci akhir apabila boleh:

1 Cegah rantaian warisan yang tidak terkawal

2

4. Galakkan pembangun menggunakan kaedah awam anda dan bukannya mendapatkan akses kepada kaedah yang dilindungi melalui kelas yang diwarisi.

5 Jadikan kelas anda boleh digunakan tanpa melanggar aplikasi Satu-satunya syarat ialah kelas anda harus melaksanakan antara muka dan bukan yang lain kaedah awam ditakrifkan.

Untuk maklumat lanjut, anda boleh membaca catatan blog mengenai topik ini yang ditulis oleh Marco Pivetta (Ocramius

Bad:

rrreee

Baik:

rrreee

).