make it solid!
DESCRIPTION
Os princípios SOLID surgiram para trazer as melhores práticas do desenvolvimento de softwares seguindo o paradigma de orientação a objetos. Nesta Palestra vamos entender de forma prática quais são estes princípios e como podemos utilizá-los no nosso dia-a-dia.TRANSCRIPT
Make itMake itSOLID!SOLID!
Luís Otávio Cobucci OblonczykLuís Otávio Cobucci Oblonczyk@lcobucci@lcobucci
Luís OtávioLuís OtávioCobucci OblonczykCobucci Oblonczyk
@lcobucci@lcobucci
PrincípiosPrincípiosee valoresvalores
PrincípiosPrincípiosee valoresvalores
“Working software is the primarymeasure of progress.”
PrincípiosPrincípiosee valoresvalores
“Welcome changing requirements,even late in development.”
PrincípiosPrincípiosee valoresvalores
“Continuous attention to technical excellence and good design enhances agility.”
NossasNossasresponsabilidades?responsabilidades?
NossasNossasresponsabilidades?responsabilidades?
Traduzir desejos
NossasNossasresponsabilidades?responsabilidades?
Escolher linguagem
Traduzir desejos
NossasNossasresponsabilidades?responsabilidades?
Escolher linguagem Libs/frameworks
Traduzir desejos
NossasNossasresponsabilidades?responsabilidades?
Escolher linguagem
Definir arquitetura
Libs/frameworks
Traduzir desejos
NossasNossasresponsabilidades?responsabilidades?
Escolher linguagem
Garantir qualidade
Definir arquitetura
Libs/frameworks
Traduzir desejos
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
Precisamos criar umUsuário com nome e idade
class UserCreator{ public function create($name, $age) { /*... */ }}
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
public function __construct() { $this->conn = new PDO( 'mysql:host=127.0.0.1;dbname=awesome', 'root', 'ImAGenius' );}
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
public function create($name, $age) { $stm = $this->conn->prepare('...'); $stm->execute([$name, $age]);}
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
Agora, temos que logar no arquivo /tmp/users.log, adicionandoo responsável pelo cadastro
class UserCreator{ public function create($name, $age, $responsible) { /*... */ }}
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
public function __construct() { // (…) $this->logger = new FileLogger();}
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
public function create($name, $age, $responsible) { $stm = $this->conn->prepare('...'); $stm->execute([$name, $age]);
$this->logger->log(/* … */);}
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
Meu, num dá pra imprimiro último usuário criado?
class UserCreator{ public function create($name, $age, $responsible) { /*... */ } public function print() { /* … */ }}
Coisas que nuncaCoisas que nuncaocorrem... né?ocorrem... né?
ResultadoResultado
ResultadoResultado
Será que “APENAS funcionar” é suficiente?
ResultadoResultado(real)(real)
Bad smellsBad smells
Bad smellsBad smells
Rigidez
Bad smellsBad smells
Rigidez
Fragilidade
Bad smellsBad smells
Rigidez
FragilidadeImobilidade
Bad smellsBad smells
Rigidez
FragilidadeImobilidade
Complexidadedesnecessária
Principles of OODPrinciples of OOD
Principles of OODPrinciples of OOD
Class design
Principles of OODPrinciples of OOD
Class designPackage cohesion
Principles of OODPrinciples of OOD
Class design
Package coupling
Package cohesion
Principles of OODPrinciples of OOD
Class design
Package coupling
Package cohesion
S.O.L.I.D.S.O.L.I.D.
Single Responsibility principle
Open/Closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
S.O.L.I.D. principlesS.O.L.I.D. principles
Single Responsibility principle
Open/Closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
S.O.L.I.D. principlesS.O.L.I.D. principles
Single ResponsibilitySingle Responsibility
One does not simplyhave more than a reasonto modify a class...
Single ResponsibilitySingle Responsibility
A class should have one,and only one, reasonto change.
Single ResponsibilitySingle Responsibility
class UserRepository{}
Single ResponsibilitySingle Responsibility
class UserRepository{ public function findByAge($age) { /* … */ } public function findByName($name) { /* … */ }}
Single ResponsibilitySingle Responsibility
class UserRepository{ public function findByAge($age) { /* … */ } public function findByName($name) { /* … */ } public function pdfReport() { /* … */ }}
Single ResponsibilitySingle Responsibilityclass UserRepository{ public function findByAge($age) { /* … */ } public function findByName($name) { /* … */ }}
class UserReport{ public function generate() { /* … */ }}
Single Responsibility principle
Open/Closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
S.O.L.I.D. principlesS.O.L.I.D. principles
Open/closedOpen/closed
Should be able to extendbehaviors, without modifyingthe class
Open/closedOpen/closed
class Authenticator{}
Open/closedOpen/closed
class Authenticator{ public function authenticate($login, $passwd) { /* … */ }}
Open/closedOpen/closed
class Authenticator{ public function authenticate($login, $passwd) { /* … */ } private function findUser($login) { /* finds on DB */ } private function matchPasswd(User $user, $passwd) { /* … */ }}
Open/closedOpen/closed
class Authenticator{ public function authenticate($login, $passwd) { /* … */ } private function findUser($login) { /* finds on DB */ } private function matchPasswd(User $user, $passwd) { /* … */ }}
E se precisarmos buscarem outro lugar?
Open/closedOpen/closed
class Authenticator{ public function authenticate($login, $passwd) { /* … */ } protected function findUser($login) { /* finds on DB */ } private function matchPasswd(User $user, $passwd) { /* … */ }}
Assim podemos sobrescrevero método de busca...
Single Responsibility principle
Open/Closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
S.O.L.I.D. principlesS.O.L.I.D. principles
Liskov substitutionLiskov substitution
Derived classes must besubstitutable for their baseclasses
Liskov substitutionLiskov substitution
class Rectangle{ public function setX($x) { /* … */ } public function setY($y) { /* … */ } public function getArea() { /* … */ }}
Liskov substitutionLiskov substitution
function getArea($x, $y, Rectangle $object){ $object->setX($x); $object->setY($y); return $object->getArea(); }
getArea(5, 10, new Rectangle());
Liskov substitutionLiskov substitution
class Square extends Rectangle{ public function setX($x) { /* also setY() */ } public function setY($y) { /* also setX() */ }}
Liskov substitutionLiskov substitution
function getArea($x, $y, Rectangle $object){ $object->setX($x); $object->setY($y); return $object->getArea(); }
getArea(5, 10, new Square());
Liskov substitutionLiskov substitution
Contravariance of method arguments in subtypesCovariance of return types in subtypes
Liskov substitutionLiskov substitution
Contravariance of method arguments in subtypesCovariance of return types in subtypes
Preconditions cannot be strengthened in subtypesPostconditions cannot be weakened in subtypes
Liskov substitutionLiskov substitution
Contravariance of method arguments in subtypesCovariance of return types in subtypes
Preconditions cannot be strengthened in subtypesPostconditions cannot be weakened in subtypes
No new exceptions! Don't violate history constraint
Single Responsibility principle
Open/Closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
S.O.L.I.D. principlesS.O.L.I.D. principles
Interface segregationInterface segregation
Make fine grained interfacesthat are client specific
Interface segregationInterface segregation
interface UserManager{}
Interface segregationInterface segregation
interface UserManager{ public function create($name, $email); public function remove($id); public function find($id); public function findByName($name);}
Interface segregationInterface segregation
class UserController{ public function find($id) { /* … */ }
/** @return UserManager */ public function getManager();}
Interface segregationInterface segregationinterface UserManager{ public function create($name, $email); public function remove($id);}
interface UserLocator{ public function find($id); public function findByName($name);}
Single Responsibility principle
Open/Closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
S.O.L.I.D. principlesS.O.L.I.D. principles
Dependency InversionDependency Inversion
Depend on abstractions,not on concretions
Dependency InversionDependency Inversion
public function __construct( DatabasePersister $persister, FileNotifier $notifier) { $this->persister = $persister; $this->notifier = $notifier;}
Dependency InversionDependency Inversion
public function __construct(Persister $persister, Notifier $notifier){ $this->persister = $persister; $this->notifier = $notifier;}
SOLID principlesSOLID principles
SOLID principlesSOLID principles
Classes mais coesas
SOLID principlesSOLID principles
Classes mais coesas
Menos acoplamento
SOLID principlesSOLID principles
Classes mais coesas
Menos acoplamento
Menos mudançasem código estável
SOLID principlesSOLID principles
Classes mais coesas
Menos acoplamento
Menos mudançasem código estável
Testes mais fáceis
Dúvidas?Dúvidas?
Obrigado!Obrigado!@lcobucci@lcobucci