Download - Solid principles

Transcript
Page 1: Solid principles

S.O.L.I.DPrinciples

Bastian [email protected]

OSIDays 2011, Bangalore21st November 2011

Page 2: Solid principles

Me, myself & I

PHP since 2001

Testing and Quality coach @ Liip Inc.

Opensource addict

PHP manual translations

FluentDOM

phpDox

Page 3: Solid principles

News from Uncle Bob

Essential principles for software development & object oriented design (OOD).

Robert C. Martin summarized those principles, but did not invent them.

Page 4: Solid principles

Which are these principles?

Single responsibility principle

Open/Close principle

Liskov substitution principle

Interface segregation principle

Dependency inversion principle

Page 5: Solid principles

Geolocation Tracker

„As a hiker I want to track where I walked and how much I climbed.“

„As a developer I want to be able to store the geo information on different devices.“

„As a developer I want to store the geo information in a unified format.“

Page 6: Solid principles

Single responsibilityprinciple (SRP)

„A class should have one, and only one, reason to change.“

Page 7: Solid principles

How to doit wrong

Page 8: Solid principles

<?phpnamespace lapis\Tracker;use lapis\Tracker\Structs;

class Geolocation extends Tracker{ public function trackPosition(Position $position) { list($langitude, $longitude, $altitude) = $this->extractCoordinatesFromPosition($position); $altitude = $this->convertFeetToMeter($altitude); $this->persistPosition($langitude, $longitude, $altitude, new DateTime()); }

public function persistPosition( $langitude, $longitude, $altitude, \DateTime $time) { try{ $conn = $this->getDatabaseConnection('write'); $conn->execute($this->generateQuery($langitude, $longitude, $altitude, $time)); } catch (Exception $e) { $this->logError($e->getMessage()); } } /** […] */}

Page 9: Solid principles

How to doit right

Page 10: Solid principles

<?php

namespace lapis\Tracker;use lapis\Tracker\Structs\Position;

class Geolocation extends Tracker{ public function __construct(Parser $parser, PersistenceManager $pm) { /** […] */ }

public function trackPosition(Position $position, \DateTime $time = null) { try { $coordinates = $this->parser->parsePosition($position); $this->pm->persistPosition($coordinates, $time); } catch (PersistanceManagerException $e) { throw new TrackerException( 'Unable to persist your position.', TrackerException::PersistError, $e ); } }}

Page 11: Solid principles

Single responsibilityprinciple

Simple to understand, very hard to get right.

Separation of responsibilities / concerns

One responsibility per class

Page 12: Solid principles

Liskov substitutionprinciple (LSP)

„Derived classes must be substitutable for their base

classes.“

Page 13: Solid principles

Where dowe start

Page 14: Solid principles

<?phpnamespace lapis\Converter;

class Distance { const FACTOR = 0.3048; // 1 foot in meters

public function feetToMeters($distance) { $this->verifyDistance($distance); return $distance * self::FACTOR; }

public function metersToFeet($distance) { $this->verifyDistance($distance); return $distance / self::FACTOR; }

protected function verifyDistance($distance) { if ($distance < 0) { throw new \OutOfRangeException( 'Distance may not be lower than zero.', DistanceException::OutOfRange ); } }}

Page 15: Solid principles

How to doit wrong

Page 16: Solid principles

<?php

namespace lapis\Converter\Distance;use lapis\Converter;

class NegativeDistance extends Distance{ protected function verifyDistance($distance) { return TRUE; }}

Page 17: Solid principles

How to doit right

Page 18: Solid principles

<?phpnamespace lapis\Converter\Distance;use lapis\Converter;

class MaxDistance extends Distance { public function feetToMeters($distance) { $distance = parent::feetToMeters($distance); $this->verifyDistance($distance, 15000); return $distance; }

protected function verifyDistance($distance, $max = 0) { if ($distance < 0) { $message = 'Distance may not be lower than the zero.'; } if ($max > 0 && $distance >= $max) { $message = 'Distance may not be greater than the maximum of ' . $max . '.'; } If (isset($message) { throw new \OutOfRangeException($message, DistanceException::OutOfRange); } }}

Page 19: Solid principles

Liskov substitutionprinciple

Design by contract

User must not distinguish between super- & subclasses

Derived class must be more strict on output, but may handle the input less strict.

Increases maintainability, robustness & resusability

Page 20: Solid principles

Dependency inversionprinciple (DIP)

„Depend on abstractions, not on concretions.“

Page 21: Solid principles

How to doit wrong

Page 22: Solid principles

<?phpnamespace lapis\Tracker;use lapis\Tracker\Structs\Position;

class PersistenceManager { public function __construct(Tracker $tracker) { /** […] */ }

public function trackPosition(Position $position) { try { $this->tracker->trackPosition($position); $this->log('Position stored successfully'); } catch (TrackerException $e) { $this->log($e->getMessage()); } }

protected function log($message) { $fh = fopen ('log.txt' , 'a'); fwrite($fh, $message); fclose($fh); } /** […] */}

Page 23: Solid principles

How to doit right

Page 24: Solid principles

<?php

namespace lapis\Tracker;use lapis\Logger, lapis\Tracker\Services;

class PersistenceManager{ public function __construct(PersistService $ps, Logger $logger) { /** […] */ }

public function persistPosition($coordinates, \DateTime $time = null) { try { $this->ps->setCoordinates($coordinates); $this->ps->setTimeStamp($time); $this->ps->persist(); $this->logger->log('Position stored successfully');

} catch (PersistServiceException $e) { $this->logger->exception($e); } }}

Page 25: Solid principles

Dependency inversionprinciple

Fundamental principle for OOD

Encapsulate low level modules in abstractions

Depend on abstractions / interfaces rather than implementations

Page 26: Solid principles

Interface segregationprinciple (ISP)

„Make fine grained interfaces that are client specific.“

Page 27: Solid principles

Where dowe start

Page 28: Solid principles

<?php

namespace lapis\Tracker;use lapis\Logger, lapis\Tracker\Services;

class PersistenceManager{ public function __construct(PersistService $ps, Logger $logger) { /** […] */ }

public function persistPosition($coordinates, \DateTime $time = null) { try { $this->ps->setCoordinates($coordinates); $this->ps->setTimeStamp($time); $this->ps->persist(); $this->logger->log('Position stored successfully');

} catch (PersistServiceException $e) { $this->logger->exception($e); } }}

Page 29: Solid principles

How to doit right

Page 30: Solid principles

<?php

namespace lapis\Tracker;use lapis\Logger, lapis\Tracker\Services;

class PersistenceManager implements PersistenceManagerPosition{ public function __construct(PersistService $ps, Logger $logger) { /** […] */ }

public function persistPosition($coordinates, \DateTime $time = null) { /** […] */ }

public function persistHeight($height, \DateTime $time = null) { /** […] */ }

public function persistLocation($height, \DateTime $time = null) { /** […] */ }}

interface PersistenceManagerPosition{ public function persistPosition($coordinates, \DateTime $time = null);}

Page 31: Solid principles

<?php

namespace lapis\Tracker;use lapis\Tracker\Structs\Position;

class Geolocation extends Tracker{ public function __construct(Parser $parser, PersistenceManagerPosition $pm) { /** […] */ }

public function trackPosition(Position $position, \DateTime $time = null) { try{ $coordinates = $this->parser->parsePosition($position); $this->pm->persistPosition($coordinates, $time); } catch (PersistanceManagerException $e) { throw new TrackerException( 'Unable to persist your position.', TrackerException::PersistError, $e ); } }}

Page 32: Solid principles

Interface segregationprinciple

Avoid „fat“ interfaces, stick to what's really needed

Ask yourself „What do I want to archieve?“

Be strict!

Page 33: Solid principles

Open/Close principle (OCP)

„You should be able to extend a classes behavior, without modifying

it.“

Page 34: Solid principles

Open/Close principle (OCP)

„It is the heard of object oriented design“

Combines the other 4 principles

Page 35: Solid principles

Where we started

Page 36: Solid principles

Where we got

Page 37: Solid principles

Questions@lapistano

[email protected]

Page 38: Solid principles

PHP5.3 Powerworkshop

New features of PHP5.3

Best Pratices using OOP

PHPUnit

PHPDocumentor

Page 39: Solid principles

License

This set of slides and the source code included in the download package is licensed under the

Creative Commons Attribution-Noncommercial-Share Alike 2.0 Generic License

http://creativecommons.org/licenses/by-nc-sa/2.0/deed.en


Top Related