Selahattin's Blog

S.O.L.I.D

It was published 21 hours ago
It was updated a few seconds ago

What is S.O.L.I.D?

Solid is an acronym for object-oriented design principles by Robert C. Martin (Uncle Bob)

They help the developers to create easily maintainable, extendable software. Because that principles appeared after a long experiences. The problems today we encountered was encountered by Robert C. Martin already. So, these principles may seems like a guide to prevent common issues.

S.O.L.I.D stands for what?

  • S: Single Responsibility
  • O: Open / Closed
  • L: Liskov substitution
  • I: Interface segregation
  • D: Dependency Inversion

Single Responsiblity

A class should have one and only one reason to change, meaning that a class should have only one job.

Open Closed

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

Liskov substitution

A sub-class must be substitutable for its super-class
class VideoPlayer {
    public function play($file)
    {
        echo 'Video playing...';
    }
}

class AviVideoPlayer extends VideoPlayer {
    public function play($file)
    {
        if (pathinfo($file, PATHINFO_EXTENSION) !== 'avi') {
            throw new Exception;
        }

        echo 'Video playing...';
    }
}

The code above violates the Liskov Substitution. Because if we use AviVideoPlayer instead of VideoPlayer in somewhere, it might behaves different in some case. But according to the principle, it should behave exactly same!

Interface Segregation

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.
interface Worker {
    public function work();
    public function sleep();
}

class Person implements Worker {
    public function work()
    {
        echo 'Person is working..';
    }

    public function sleep()
    {
        echo 'Person is sleeping...';
    }
}

class Robot implements Worker {
    public function work()
    {
        echo 'Robot is working...';
    }

    public function sleep()
    {
        //
    }
}

As you can see, robot does not need to sleep. But we’ve forced to implementing sleep method. So it violates the Interface Segregation principle. Let’s fix it.

interface Worker {
    public function work();
}

interface Sleepable {
    public function sleep();
}

class Person implements Worker, Sleepable {
    public function work()
    {
        echo 'Person is working..';
    }

    public function sleep()
    {
        echo 'Person is sleeping...';
    }
}

class Robot implements Worker {
    public function work()
    {
        echo 'Robot is working...';
    }
}

Dependency Inversion

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.

All of this is about decoupling code.

<?php

class PasswordReminder {
    __construct(MysqlConnection $connection) {
        //
    }
}

It depends directly to concrete low-level module. It violates the Dependency Inversion. Let’s fix it.

interface DatabaseConnection {
    //
}

class MysqlConnection implements DatabaseConnection {

}

class PasswordReminder {
    __construct(DatabaseConnection $connection) {
        //
    }
}

Right now, PasswordReminder depends on abstraction and also low-level module (MysqlConnection) too depends on abstraction!


Further More: