Object Oriented Programming

And S.O.L.I.D. Principles

http://slides.com/onema/oop-and-solid

Object-oriented programming (OOP) is a programming paradigm that represents concepts as "objects" that have data fields (attributes that describe the object) and associated procedures known as methods [1]

 

What is Object Oriented Programming (OOP)?

Object-oriented programming is a style of coding that allows developers to group similar tasks into classes. [2]

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

is a mnemonic acronym that stands for five basic principles of object-oriented programming and design. The principles, when applied together, intend to make it more likely that a programmer will create a system that is easy to maintain and extend over time.[3]

Who knows the difference between a class and a object?

Class Structure


class ClassName
{
    // These are variables bound to the object and can
    // only be accessed by the object
    public $classProperty01;

    public function classMethod01()
    {
        // Methods are class specific function.
        // Objects can reference themselves using $this.
    }
}

Class Name

Curly braces are required

Class Properties (variables)

Class Methods (functions)

Instantiating Classes


$myClass = new ClassName();
$myClass->classMethod01();

S

Single Responsibility Principle (SRP)

O

L

I

D

R

P

A class or module should have one, and only one, reason to change... Classes should have one responsibility—one reason to change. [4]

 

S

O

L

I

D

R

P

While SPR is one of the simplest OO design principles, it is one of the most abused.

WHY? Once the program works, I'm done!

Use SRP to neatly organize your application and code

________________________________________________________

S

Why do we want to use SRP?

O

L

I

D

R

P

Multipurpose classes prevents us from clearly understanding the original intention of the code.

S

Why do we want to use SRP?

O

L

I

D

R

P

Manage the complexity by organizing. Every sizable application will contain a large amount of code and complexity.

 

 

Pro Tip!

S

Why do we want to use SRP?

O

L

I

D

R

P

Easier to understand and update. With simpler classes we can directly affect complexity at any given time.

 

S

Why do we want to use SRP?

O

L

I

D

R

P

Better system design. Collaboration with other small classes to achieve system behavior is better than doing it all in one or few classes.

Pro Tip!

S

Why do we want to use SRP?

O

L

I

D

R

P

Easy to collaborate with other developers or teams. The likelihood of two teams working on the same part of the system is reduced; this helps prevent code and functionality conflicts.

S

Exercise 1

O

L

I

D

R

P

class Rectangle
{
    public void Draw(); 
    public void Area(double val);
}

Single or multiple responsibilities?

S

Exercise 2

O

L

I

D

R

P

interface Modem
{
    public void Dial(string phone); 
    public void Hangup();
    public void Send(char message); 
    public char Recv();
}

Single or multiple responsibilities?

S

Exercise 3

O

L

I

D

R

P

class Version 
{
    public int getMajorVersionNumber(); 
    public int getMinorVersionNumber();
    public int getPatchVersionNumber();
    public int getBuildNumber();
}

Single or multiple responsibilities?

S

Exercise 4

O

L

I

D

R

P

Design a Tic-Tac-Toe game

  1. Two player game only
  2. Users can input
  3. Single game only
  4. Must display game grid

Public, protected and private properties & Methods

  • Used to hold or add data to classes
  • Properties have visibility (more on this later)
  • Can be initialized but is not required

class Properties

class MyClass
{
    public $property = "I'm a class property!";
}
 
$obj = new MyClass();

echo $obj->property;

Defining class Properties

Public visibility

Access contained properties & methods

  • Class specific functions
  • Methods have visibility (more on this later)

class Methods

class MyClass
{
    public $property = "I'm a class property!";

    public function setProperty($newValue)
    {
        $this->property = $newValue;
    }
 
    public function getProperty()
    {
        return $this->property;
    }
}
 
$obj = new MyClass();
echo $obj->getProperty();
$obj->setProperty('New property value!');
echo $obj->getProperty();

Defining class Methods

Public visibility

class MyClass
{   
    // ...

    public function __construct()
    {
        echo 'The class ' . __CLASS__ . ' was initiated.'; 
    }

    public function __destruct()
    {
        echo 'The class ' . __CLASS__ . ' was destroyed.'; 
    }

    // ...
}
 
$obj = new MyClass();

constructors and destructors

EOF PHP releases all resources

Inheritance

Classes can inherit properties and methods from other classes

Classes can extend the behaviour of other classes by using the "extends" keyword

class Car extends Vehicle {
    public function getMakeAndModel()
    {
        echo $this->getMake() . ' ' . $this->getModel();
    }
}
class Vehicle
{
    // . . . 
    public function __construct($make, $model, $size = 5) {
        $this->make = $make;
        $this->model = $model;
        $this->size = $size;
    }
    // . . . 
    public function getMake() {
        return $this->make;
    }

    public function getModel() {
        return $this->model;
    }
}

Extends Keyword

Classes can overwrite public and protected properties and methods

class HondaCivic extends Car
{
    // . . . 
    public function getMake() {
        return 'Honda';
    }
    public function getModel() {
        return 'Civic';
    }
}

Overwriting

Bad Practice

class HondaCivic extends Car
{
    // ...
    public function getMakeAndModel($customString)
    {
        if (isset($customString)) {
            echo $customString;
        } else {
            echo $this->getMake() . ' ' . $this->getModel();
        }
    }
    // . . .
}

The " L" in S.O.L.I.D. More on this later...

O

Open Close Principle

L

Classes, modules, functions should be open for extension and close for modification

Open for Extension:

This means that the behavior of the module can be extended. [5]

Closed for Modification:

The source code of such a module is inviolate. No one is allowed to make source code changes to it. [5]

C

P

I

D

S

class Vehicle {
    // ...
}
class CarDriver {
    public function drive($car) {
        if ($car->getMake() == 'Honda') {
            // do something with Honda car 
        } elseif ($car->getMake() == 'Toyota') {
            // do something with Toyota car
        } elseif ($car->getMake() == 'Ford') {
            // do something with Ford car
        } 
    }

    // ...
}
class Car extends Vehicle {
    // ...
}

Does not conform to the open-closed principle because it cannot be closed against new kinds of vehicles

O

L

C

P

I

D

S

abstract class Car extends Vehicle {
    // ...

    abstract public function drive();
}
class Honda extends Car {
    // ...
    public function drive() {
        // implement drive 
    }
}
class Toyota extends Car {
    // ...
    public function drive() {
        // implement drive 
    }
}

PRO TIP

Use the Strategy Pattern:

Define a contract between parent and child classes

Strategy Pattern, and other design patterns can be used to extend code without internal modifications!

O

L

C

P

I

D

S

$driver = new CarDriver();
$honda = new Honda();
$driver->drive($honda);

$toyota = new Toyota();
$driver->drive($toyota);

class CarDriver {
    public function drive(Car $vehicle) {
        $vehicle->drive();
    }

    // ...
}

CarDriver can drive any type of car without having to modify the code

O

L

C

P

I

D

S

Abstraction

Working with something we know how to use without knowing how it works internally[6]

Encapsulation

Providing users with essential information about an object for manipulation... A [person] using a Laptop only knows about its screen, keyboard and mouse. Everything else is hidden internally under the cover.

Example

class Lion extends Felidae {
    private frontLeft;
    private frontRight;
    private bottomLeft;
    private bottomRight;

    public function Walk() {
        $this->MovePaw($this->frontLeft);
        $this->MovePaw($this->frontRight);
        $this->MovePaw($this->bottomLeft);
        $this->MovePaw($this->bottomRight);
    }

    private function movePaw(Paw $paw) {
        // ...
    }
    // ...
}
class Felidae {
    public function Walk() {
        echo "Felidae walks"; 
    }
}

We only need to know how to walk, how that is performed is not our concern!

L

Liskov Substitution Principle

S

I

Child classes should never break the parent class' type definitions [8]

If for each object o1  of type S there is an object o2  of type T such that for all programs P   defined in terms of T, the behavior of P is unchanged when o1  is substituted for o2  then S is a subtype of T [9]

S

P

O

D

L

S

I

D

S

P

O

o2 (T)

o1 (S)

T

S

P

If for each object o1  

there is an object o2 

such that for all programs P   defined in terms of T, 

the behavior of P is unchanged when o1  is substituted for o2  

then S is a subtype of T

of type S 

of type T 

L

S

I

S

P

O

D

Violation Example #1 

interface bird {
    public function birdSound();
    public function fly();
    public function display();
}
class Duck implements Bird {
    public function birdSound() {
        echo 'quack!';
    }
    public function fly() {
        echo 'duck is flying!';
    }
    public function display() {
        // display a duck
    }
}
class Ostrich implements Bird {
    public function birdSound() {
        echo 'Ostrich noises!';
    }
    public function fly() {
        echo "D'oh!";
    }
    public function display() {
        // display an Ostrich
    }
}

Introduces new behavior,

NON-FLYING BIRD!!!

L

S

I

S

P

O

D

Violation Example #2

class Ostrich implements Bird {
    public function birdSound() {
        echo 'Ostrich noises!';
    }
    public function fly($jetPack) {
        echo "Attach jetpack to Ostrich and FLY!";
    }
    public function display() {
        // display an Ostrich
    }
}

WRONG!

L

S

I

S

P

O

D

Violation Example #2

class BirdSimulator {
    private $bird;

    public function setBird(Bird $bird) {
        $this->bird = $bird;
    }

    public function main() {
        if (isset($this->bird)) {
            echo 'This bird says '.$this->bird->birdSound(); 
            echo 'And this bird can also Fly '.$this->bird->fly();
        }
    }
}

$birdSim = new BirdSimulator();

$birdSim->setBird(new Duck());
$birdSim->main();

$birdSim->setBird(new Ostrich());
$birdSim->main();
class Ostrich implements Bird {
    public function birdSound() {
        echo 'Ostrich noises!';
    }
    public function fly($jetPack) {
        echo "Attach jetpack to Ostrich and FLY!";
    }
    public function display() {
        // display an Ostrich
    }
}

What would happen here?

Declaration of Ostrich::fly() must be compatible with bird::fly() 

L

S

I

D

S

P

O

If it looks like a duck

Quacks like a duck

But needs batteries

You probably have the wrong abstraction

Subtypes must be substitutable for their base types.

 

L

S

I

S

P

O

D

So what is the point?

The Liskov Substitution Principle (A.K.A Design by Contract) is an important feature of all programs that conform to the Open-Closed principle.

It is only when derived types are completely substitutable for their base types that functions which use those base types can be reused with impunity, and the derived types can be changed with impunity. 

L

S

I

S

P

O

D

Exercise

Create an abstraction for the Bird class

Polymorphism

Describes a pattern in which classes have different behavior but share common interface [10].

Interfaces

Interfaces are a key part of polymorphism, they describe behaviors, without implementing them. 

Classes implementing the interfaces must build the functionality for all the methods defined in the interface.

Example

class Lion implements Felidae {
    private frontLeft;
    private frontRight;
    private bottomLeft;
    private bottomRight;

    public function Walk() {
        $this->MovePaw($this->frontLeft);
        $this->MovePaw($this->frontRight);
        $this->MovePaw($this->bottomLeft);
        $this->MovePaw($this->bottomRight);
    }

    private function movePaw(Paw $paw) {
        // ...
    }
    // ...
}
interface Felidae {
    public function Walk(); 
}

An interface is declared using the keyword interface

To implement the interface the  implements operator is used

I

S

L

S

P

O

D

Interface Segregation Principle

The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use. [11]

Classes that implement interfaces should not be forced to implement methods they do not use. [12]

I

S

L

S

P

O

D

Interface Segregation Principle

This principle deals with disadvantages of interface pollution


interface Vehicle {
    public function startEngine();
    public function accelerate();
    public function brake();
    public function lightsOn();
    public function signalLeft();
    public function signalRight();
    public function changeGear($gear);
    public function stopRadio();
    public function ejectCD();
}

I

S

L

S

P

O

D

Interface Segregation Principle

Each interface should be grouped into methods that serve a different set of clients

I

S

L

S

P

O

D

Interface Segregation Principle

program to an interface not an implementation

I

S

L

S

P

O

D

Excercise

interface PlayerInterface 
{
    // Mount to player: weapons, potions, bags, etc
    public function mountItem($item);
    public function unMountItem();

    // Add to player inventory
    public function setItem($item);
    public function getItem($itmeName);
    public function hasItem($itemName);
    public function removeItem($itemName);

    // Health 
    public function damage($amount);
    public function heal($amount);
    public function getHealth();

    // User information
    public function setName($name);
    public function getName();

    // User stats
    public function setStats($stats);
    public function getStat($key);

    public function isDead();
}

D

S

L

I

P

O

I

Dependency Inversion Principle

THE END

BY Juan Manuel Torres / onema.io / @onema / kinojman@gmail.com

References

References

Object Oriented Programming and SOLID concepts

By Juan Manuel Torres

Object Oriented Programming and SOLID concepts

  • 2,750