オブジェクト指向プログラミング⭐⭐⭐⭐⭐


ソリッドは、ロバートC .マーティン(また、アンクルボブとして知られている)による最初の5つのオブジェクト指向デザイン(Of)原則の頭字語です.
これらの原則は、プロジェクトが成長するに従って維持し、拡張するための配慮をもって開発ソフトウェアを貸す実践を確立する.これらの慣行を採用することは、コードの臭い、リファクタリングコード、アジャイルまたは適応的なソフトウェア開発を避けることにも貢献することができます.
ソリッドスタンド:
s -シングル責任
オープンクローズド原理
Lskov置換原理
界面分離原理
依存性反転原理
さあ、最初の話をしましょう.
単一責任原則

"A Class Should Have One, And Only One Responsibility"


それは、我々のクラスが1つ以上の責任を負うならば、我々が高いカップリングを持つということを意味します.原因は、我々のコードがどんな変化でも壊れやすいということです.
次のようなユーザークラスがあるとします
<?php

class User {

    private $email;

    // Getter and setter...

    public function store() {
        // Store attributes into a database...
    }
}
この場合、方法store この責任は範囲外で、データベースを管理するクラスに属するべきです.
ここでの解決策はそれぞれ適切な責任を持つ2つのクラスを作成することです.
<?php

class User {

    private $email;

    // Getter and setter...
}

class UserDB {

    public function store(User $user) {
        // Store the user into a database...
    }
}
今、固体のoに移動しましょう
開放閉鎖原理

Objects or entities should be open for extension but closed for modification.


この原則によれば、ソフトウェア実体は、使用中の既存のコードを修飾しなければならないことのない新規な機能によって、容易に拡張可能でなければならない.
いくつかのオブジェクトの合計面積を計算しなければならないと仮定し、私たちはAreaCalculator 各図形領域の合計だけを行うクラス.
問題は、各図形は、独自の領域を計算するために別の方法を持っていることです.
<?php

class Rectangle {

    public $width;
    public $height;

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

class Square {

    public $length;

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


class AreaCalculator {

    protected $shapes;

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

    public function sum() {
        $area = [];

        foreach($this->shapes as $shape) {
            if($shape instanceof Square) {
                $area[] = pow($shape->length, 2);
            } else if($shape instanceof Rectangle) {
                $area[] = $shape->width * $shape->height;
            }
        }

        return array_sum($area);
    }
}
我々がaのようなもう一つの形を加えるならばCircle 私たちはAreaCalculator 新しい形状領域を計算するために、これは持続可能ではありません.
ここでの解決策は、シンプルなものを作ることですShape 領域メソッドを持ち、他のすべての図形で実装されるインターフェイスです.
<?php

interface Shape {
    public function area();
}

class Rectangle implements Shape {

    private $width;
    private $height;

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

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

class Square implements Shape {

    private $length;

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

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


class AreaCalculator {

    protected $shapes;

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

    public function sum() {
        $area = [];

        foreach($this->shapes as $shape) {
            $area[] = $shape->area();
        }

        return array_sum($area);
    }
}
このように、我々は合計を計算する1つの方法だけを使用します、そして、我々がちょうどそれを実行する新しい形を加える必要があるならばShape インターフェイス.
立体lの第3の原理は以下の通りです.
Liskov Substition王女

Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.


原則は、オブジェクトが我々のシステムの正しい機能を変えることなく彼らのサブタイプのインスタンスによって取り替え可能でなければならないと言います.
私はこれが理解するのが難しいということを知っています.
1. Child function arguments must match function arguments of parent

2. Child function return type must match parent function return type

3. Child pre-conditions cannot be greater than parent function pre-conditions

4. Child function post-conditions cannot be lesser than parent function post-conditions.

5. Exceptions thrown by child method must be the same as or inherit from an exception thrown by the parent method.
ここで完全に理解するには、以下のようなシナリオです.
コーヒーマシンの2種類を管理想像してください.ユーザープランによると、我々は基本的なまたはプレミアムコーヒーマシンを使用します、唯一の違いは、プレミアムマシンは、基本的なマシンよりも良いバニラコーヒーを作ることです.
<?php

interface CoffeeMachineInterface {
    public function brewCoffee($selection);
}


class BasicCoffeeMachine implements CoffeeMachineInterface {

    public function brewCoffee($selection) {
        switch ($selection) {
            case 'ESPRESSO':
                return $this->brewEspresso();
            default:
                throw new CoffeeException('Selection not supported');
        }
    }

    protected function brewEspresso() {
        // Brew an espresso...
    }
}


class PremiumCoffeeMachine extends BasicCoffeeMachine {

    public function brewCoffee($selection) {
        switch ($selection) {
            case 'ESPRESSO':
                return $this->brewEspresso();
            case 'VANILLA':
                return $this->brewVanillaCoffee();
            default:
                throw new CoffeeException('Selection not supported');
        }
    }

    protected function brewVanillaCoffee() {
        // Brew a vanilla coffee...
    }
}


function getCoffeeMachine(User $user) {
    switch ($user->getPlan()) {
        case 'PREMIUM':
            return new PremiumCoffeeMachine();
        case 'BASIC':
        default:
            return new BasicCoffeeMachine();
    }
}


function prepareCoffee(User $user, $selection) {
    $coffeeMachine = getCoffeeMachine($user);
    return $coffeeMachine->brewCoffee($selection);
}
メインプログラムの動作は両方のマシンで同じでなければなりません.
第四の原理は次のとおりです.
界面分離原理

A client should never be forced to implement an interface that it doesn’t use or clients shouldn’t be forced to depend on methods they do not use.


この原則は、クラスが使用に行かないインターフェイスを実装してはならないことを定義します.
その場合、我々の実装では、必要ないメソッドがあることを意味します.
解決策は汎用インタフェースの代わりに特定のインタフェースを開発することである.
ここにシナリオを想像してみましょうFutureCar それは両方を飛ぶことができます.
<?php

interface VehicleInterface {
    public function drive();
    public function fly();
}

class FutureCar implements VehicleInterface {

    public function drive() {
        echo 'Driving a future car!';
    }

    public function fly() {
        echo 'Flying a future car!';
    }
}

class Car implements VehicleInterface {

    public function drive() {
        echo 'Driving a car!';
    }

    public function fly() {
        throw new Exception('Not implemented method');
    }
}

class Airplane implements VehicleInterface {

    public function drive() {
        throw new Exception('Not implemented method');
    }

    public function fly() {
        echo 'Flying an airplane!';
    }
}
主な問題は、あなたが見ることができるように、車とAirplane 使用しないメソッドがあります.
解決策はVehicleInterface 次のように、必要なときにのみ使用される2つ以上の特定のインターフェイスに
<?php

interface CarInterface {
    public function drive();
}

interface AirplaneInterface {
    public function fly();
}

class FutureCar implements CarInterface, AirplaneInterface {

    public function drive() {
        echo 'Driving a future car!';
    }

    public function fly() {
        echo 'Flying a future car!';
    }
}

class Car implements CarInterface {

    public function drive() {
        echo 'Driving a car!';
    }
}

class Airplane implements AirplaneInterface {

    public function fly() {
        echo 'Flying an airplane!';
    }
}
最後には、少なくとも次のようなDがあります.
依存性反転原理

Entities must depend on abstractions not on concretions. It states that the high level module must not depend on the low level module, but they should depend on abstractions.


この原則は、特定のクラスが別のクラスに直接依存するべきではなく、このクラスの抽象化に依存するべきであることを意味します.
この原理は、デカップリングおよびより多くのコード再利用性を考慮に入れる.
の最初の例を見ましょうUserDB クラス.このクラスはDB接続に依存します.
<?php

class UserDB {

    private $dbConnection;

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

    public function store(User $user) {
        // Store the user into a database...
    }
}
この場合、UserDB クラスは、MySQLデータベースから直接依存します.
これは、データベースエンジンを使用する場合、このクラスを書き換える必要があることを意味します.
解決策はデータベース接続の抽象化を開発することです.
<?php

interface DBConnectionInterface {
    public function connect();
}

class MySQLConnection implements DBConnectionInterface {

    public function connect() {
        // Return the MySQL connection...
    }
}

class UserDB {

    private $dbConnection;

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

    public function store(User $user) {
        // Store the user into a database...
    }
}
このコードは、ハイレベルとローレベルの両方のモジュールが抽象化に依存することを示します.

Hurray! We are done with the 5 SOLID Principle of Object Oriented Programming! You can use these principles represent the state of the art of the code quality and following them permit you to write software that will be easily extended, reusable and refactored.

Projects that adhere to SOLID principles can be shared with collaborators, extended, modified, tested, and refactored with fewer complications.