SOLID & Design Patterns
Bom Design em
Orientação a Objetos
Mario Rezende - @mariorez
Grupo de Usuários PHPSP.org.br
Mudança , Dependência , Acoplamento
1. Evolução Continua
2. Gestão de Dependência
Bom Design em OO
1
2
3
4
5
6
7
8
9
10
class Controller
{
public function action()
{
$business = new Business();
$report = $business->report...
class ClassA { // depends Calculator }
class ClassB { // depends Calculator }
1
2
3
4
5
6
7
8
9
10
class Controller
{
publ...
class ClassA { // depends Calculator }
class ClassB { // depends Calculator }
1
2
3
4
5
6
7
8
9
10
11
class Controller
{
p...
class ClassA { // depends Calculator }
class ClassB { // depends Calculator }
1
2
3
4
5
6
7
8
9
10
11
class Controller
{
p...
Mudança , Dependência , Acoplamento
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
class BusinessTest extends PHPUnit_Framework_Test...
Mudança , Dependência , Acoplamento
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class BusinessTest extends PHPUnit_Framework_Te...
Manifesto para Desenvolvimento
ÁGIL de Software
Mudança , Dependência , Acoplamento , Ágil
Indivíduos e interações
Softwar...
Single Responsibility
Open / Closed
Liskov Substitution
I nterface Segregation
Dependency Inversion
Mudança , Dependência ...
Mudança , Dependência , Acoplamento , Ágil
Single Responsibility
Uma Classe deve ter uma única razão para mudar
(responsab...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function isAthenticate() x
{
// authenticate user in a data...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Single Responsibility
Mudança , Dependência , Acoplamento , Ágil
Conclusão
❖ SRP é o mais simples, e o mais difícil de faz...
Mudança , Dependência , Acoplamento , Ágil
Open / Closed
Entidades (classes, módulos, etc) devem ser
aberta para extensão,...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Open / Closed
Mudança , Dependência , Acoplamento , Ágil
Conclusão
❖ OCP está no coração do Design Orientado a Objetos
❖ F...
Dependency Inversion
A. Módulos de Alto nível não devem depender de módulos
de Baixo nível, ambos devem depender de Abstra...
Mudança , Dependência , Acoplamento , Ágil
class User
{
public function setEmail($email) {}
public function getEmail() {}
...
Mudança , Dependência , Acoplamento , Ágil
A. Módulos de Alto nível não devem depender de módulos
de Baixo nível, ambos de...
Mudança , Dependência , Acoplamento , Ágil
A. Módulos de Alto nível não devem depender de módulos
de Baixo nível, ambos de...
Mudança , Dependência , Acoplamento , Ágil
Policy
Mechanism
A. Módulos de Alto nível não devem depender de módulos
de Baix...
Mudança , Dependência , Acoplamento , Ágil
class User implements UserInterface
{
public function setEmail($email) {}
publi...
Mudança , Dependência , Acoplamento , Ágil
class User implements UserInterface
{
public function setEmail($email) {}
publi...
Mudança , Dependência , Acoplamento , Ágil
A. Módulos de Alto nível não devem depender de módulos
de Baixo nível, ambos de...
Mudança , Dependência , Acoplamento , Ágil
Utility
Policy
Mechanism
Dependency Inversion S.O.L.I.D
Mudança , Dependência , Acoplamento , Ágil
Utility
Policy
Mechanism
RedisClientOAuthClient
RedisInterfaceOAuthInterface
Si...
Mudança , Dependência , Acoplamento , Ágil
Utility
Policy
Mechanism
B. Abstrações não devem
depender de detalhes, Detalhes...
Mudança , Dependência , Acoplamento , Ágil
Utility
Policy
Mechanism
B. Abstrações não devem
depender de detalhes, Detalhes...
Mudança , Dependência , Acoplamento , Ágil
class User implements UserInterface
{
public function setEmail($email) {}
publi...
Mudança , Dependência , Acoplamento , Ágil
Policy
Mechanism
Utility
Dependency Inversion S.O.L.I.D
Dependency Inversion
Conclusão
❖ Regras e detalhes devem depender de abstrações,
que são definidas do ponto de vista do us...
Design Pattern
TIME
Design Pattern: Strategy
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
class SignManager implements ...
class Controller
{
public function loginAction($request)
{
$user = new User(); // set e-mail and password
$repository = ne...
class RepositoryStrategy implements Repository {
private $context;
public function __construct($context) { x
$this->contex...
Quais são os Design Patterns
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
Creational
Abstract Facto...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
❖ Solução Genérica para Problemas Recorrentes
(reutili...
SOLID & Design Patterns
através de exemplos
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
Liskov Substitution
Possibilidade de Substituir a Clas...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
1
2
3
4
5
6
7
8
9
10
11
12
13
class PaymentCalculator
...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
1
2
3
4
5
6
7
8
9
10
11
12
13
class PaymentCalculator
...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
1
2
3
4
5
6
7
8
9
10
11
12
13
class PaymentCalculator
...
1
2
3
4
5
6
7
8
9
10
11
12
13
class CreditCardCalculator extends PaymentCalculator
{
public function calculatePayday(Payme...
1
2
3
4
5
6
7
8
9
10
11
12
13
class CreditCardCalculator extends PaymentCalculator
{
public function calculatePayday(Payme...
1
2
3
4
5
6
7
8
9
10
11
12
13
class CreditCardCalculator extends PaymentCalculator
{
public function calculatePayday(Payme...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
1
2
3
4
5
6
7
8
9
10
11
12
13
class PaymentCalculator
...
Liskov Substitution
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
Conclusão
❖ LSP é o principal faci...
Design Pattern
TIME
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
1
2
3
4
5
6
7
class Payment
{
private $type; //CreditC...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
1
2
3
4
5
6
7
class Payment
{
private $type; //CreditC...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class ...
Interface Segregation
Muitas Interfaces específicas são melhores do que
uma Inferface de proposito geral
Mudança , Dependê...
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
Exemplos de Código S.O.L.I.D
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
Exemplos de Código S.O.L.I.D
Interface Segregation
Conclusão
❖ Evita a utilização de “Fat Classes”
❖ Quebra a dependência de métodos que não são
invoca...
Consolidando
Conceitos
Object Oriented Mindset
Mudança , Dependência , Acoplamento , Ágil , Composição , Interface
Injeção de Dependência
Procedu...
Agile Software Development, Principles, Patterns, and Practices (Robert Martin - 2002)
Agile Principles, Patterns, and Pra...
VALEU !!!
Mario Rezende - @mariorez
Princípios
Orientação
Objetos
Abstração
Encapsulamento
Herança
Composição
Modularidade
Polimorfismo
Princípios
de Design
d...
Princípios
Orientação
Objetos
Abstração
Encapsulamento
Herança
Composição
Modularidade
Polimorfismo
Princípios
de Design
d...
Upcoming SlideShare
Loading in …5
×

SOLID & Design Pattern: Bom Design em Orientação a Objetos

4,463 views

Published on

"SOLID" e "Design Pattern" são um conjunto de princípios e padrões a serem utilizados em Design de Software, oferecendo ao Desenvolvedor uma visão mais ampla a respeito da Programação Orientada a Objetos. Conhecer e aplicar esses conceitos promove o desacoplamento e melhor utilização dos Objetos; facilita o desenvolvimento orientado a Testes; melhora a organização código gerando maior agilidade na manutenção e evolução do Software.

Published in: Technology, Business
5 Comments
56 Likes
Statistics
Notes
No Downloads
Views
Total views
4,463
On SlideShare
0
From Embeds
0
Number of Embeds
143
Actions
Shares
0
Downloads
122
Comments
5
Likes
56
Embeds 0
No embeds

No notes for slide

SOLID & Design Pattern: Bom Design em Orientação a Objetos

  1. 1. SOLID & Design Patterns Bom Design em Orientação a Objetos Mario Rezende - @mariorez Grupo de Usuários PHPSP.org.br
  2. 2. Mudança , Dependência , Acoplamento 1. Evolução Continua 2. Gestão de Dependência Bom Design em OO
  3. 3. 1 2 3 4 5 6 7 8 9 10 class Controller { public function action() { $business = new Business(); $report = $business->report(); $this->renderPage($report); } } 1 2 3 4 5 6 7 8 9 10 1 2 3 4 class Calculator { public function calculate() { // logic } } class Business { public function report() { $calculator = new Calculator(); x $result = $calculator->calculate(); // solves some logic and returns the result } } Mudança , Dependência , Acoplamento Bom Design em OO
  4. 4. class ClassA { // depends Calculator } class ClassB { // depends Calculator } 1 2 3 4 5 6 7 8 9 10 class Controller { public function action() { $business = new Business(); $report = $business->report(); $this->renderPage($report); } } 1 2 3 4 5 6 7 8 9 10 1 2 3 4 class Calculator { public function calculate() { // logic } } class Business { public function report() { $calculator = new Calculator(); x $result = $calculator->calculate(); // solves some logic and returns the result } } Mudança , Dependência , Acoplamento Bom Design em OO
  5. 5. class ClassA { // depends Calculator } class ClassB { // depends Calculator } 1 2 3 4 5 6 7 8 9 10 11 class Controller { public function action() { $business = new Business(); $calculator = new Calculator(); x $report = $business->report($calculator); $this->renderPage($report); } } 1 2 3 4 5 6 7 8 9 1 2 3 4 class Calculator { public function calculate() { // logic } } class Business { public function report(Calculator $calculator) { $result = $calculator->calculate(); // solves some logic and returns the result } } Mudança , Dependência , Acoplamento Bom Design em OO
  6. 6. class ClassA { // depends Calculator } class ClassB { // depends Calculator } 1 2 3 4 5 6 7 8 9 10 11 class Controller { public function action() { $business = new Business(); $calculator = new DerivedClass(); $report = $business->report($calculator); $this->renderPage($report); } } 1 2 3 4 5 6 7 8 9 1 2 3 4 class Calculator { public function calculate() { // logic } } class Business { public function report(Calculator $calculator) { $result = $calculator->calculate(); // solves some logic and returns the result } } Mudança , Dependência , Acoplamento Bom Design em OO 1 2 3 4 class DerivedClass extends Calculator x { public function calculate() { // logic } }
  7. 7. Mudança , Dependência , Acoplamento 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 class BusinessTest extends PHPUnit_Framework_TestCase { public function testReport() { $business = new Business(); $this->assertEquals(100, $business->report()); x } } 1 2 3 4 class Business { public function report() { $calculator = new Calculator(); $result = $calculator->calculate(); // solves some logic and returns the result } } class Calculator { public function calculate() { // logic } } Será que esse teste vai passar ? Bom Design em OO
  8. 8. Mudança , Dependência , Acoplamento 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class BusinessTest extends PHPUnit_Framework_TestCase { public function testReportForMonthsWith31Days() { // Create a stub for the AnotherClass class. $stub = $this->getMock('Calculator'); // Configure the stub. $stub->method('calculate') ->willReturn(31); $business = new Business(); $this->assertEquals(100, $business->report($stub)); } } 1 2 3 4 5 6 7 8 9 class Business { public function report(Calculator $calculator) { $result = $calculator->calculate(); // solves some logic and returns the result } } Bom Design em OO 1 2 3 4 class Calculator { public function calculate() { // logic } }
  9. 9. Manifesto para Desenvolvimento ÁGIL de Software Mudança , Dependência , Acoplamento , Ágil Indivíduos e interações Software em funcionamento Colaboração com o cliente Responder a Mudanças Bom Design em OO
  10. 10. Single Responsibility Open / Closed Liskov Substitution I nterface Segregation Dependency Inversion Mudança , Dependência , Acoplamento , Ágil Os Princípios do SOLID
  11. 11. Mudança , Dependência , Acoplamento , Ágil Single Responsibility Uma Classe deve ter uma única razão para mudar (responsabilidade única) Exemplos de Código S.O.L.I.D
  12. 12. Mudança , Dependência , Acoplamento , Ágil class User { public function isAthenticate() x { // authenticate user in a database } public function hasRole($role) x { // checks user privileges } public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class Controller { public function loginAction($request) { $user = new User(); $user->setEmail($request->get('email')); $user->setPassword($request->get('password')); if (!$user->isAuthenticate() || !$user->hasRole('admin')) { $this->redirect('access-denied'); } $this->session->addUser($user); $this->redirect('dashboard'); } } Single Responsibility S.O.L.I.D
  13. 13. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SecurityManager { public function isAuthenticate(User $user) { // authenticate user in a database } public function hasRole(User $user, $role) { // checks user privileges } } class Controller { public function loginAction($request) { $user = new User(); $user->setEmail($request->get('email')); $user->setPassword($request->get('password')); $security = new SecurityManager(); x if (!$security->isAuthenticate($user) || !$security->hasRole($user, 'admin')) { $this->redirect('access-denied'); } $this->session->addUser($user); $this->redirect('dashboard'); } } Single Responsibility S.O.L.I.D
  14. 14. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class Controller { public function loginAction($request) { $user = new User(); $user->setEmail($request->get('email')); $user->setPassword($request->get('password')); $signManager = new SignManager(); x $grantManager = new GrantManager(); x if (!$signManager->isAuthenticate($user) || !$grantManager->hasRole($user, 'admin')) { $this->redirect('access-denied'); } $this->session->addUser($user); $this->redirect('dashboard'); } } Single Responsibility S.O.L.I.D class SignManager { public function isAuthenticate(User $user) { // authenticate user in a database } } class GrantManager { public function hasRole(User $user, $role) { // checks user privileges } }
  15. 15. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignManager { public function isAuthenticate(User $user) { // authenticate user in a database } } class GrantManager { public function hasRole(User $user, $role) { // checks user privileges } } class Controller { public function loginAction($request) { $user = new User(); $user->setEmail($request->get('email')); $user->setPassword($request->get('password')); $signManager = new SignManager(); $grantManager = new GrantManager(); if (!$signManager->isAuthenticate($user) || !$grantManager->hasRole($user, 'admin')) { $this->redirect('access-denied'); } $this->session->addUser($user); $this->redirect('dashboard'); } } Single Responsibility S.O.L.I.D
  16. 16. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignManager { public function isAuthenticate(User $user) { // authenticate user in a database } } class GrantManager { public function hasRole(User $user, $role) { // checks user privileges } } class AccessControlService x { public function __construct(SignManager $sign, GrantManager $grant) { /* save reference */ } public function login(User $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } } Single Responsibility S.O.L.I.D
  17. 17. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignManager { public function isAuthenticate(User $user) { // authenticate user in a database } } class GrantManager { public function hasRole(User $user, $role) { // checks user privileges } } class Controller { public function loginAction($request) { $user = new User(); // set e-mail and password $accessControl = new AccessControlService( x new SignManager(), new GrantManager()); x try { $accessControl->login($user); x } catch (Exception $e) { $this->redirect('access-denied'); } $this->session->addUser($user); $this->redirect('dashboard'); } } Single Responsibility S.O.L.I.D
  18. 18. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignManager { public function isAuthenticate(User $user) { // authenticate user in a database } } class GrantManager { public function hasRole(User $user, $role) { // checks user privileges } } class AccessControlService { public function __construct(SignManager $sign, GrantManager $grant) { /* save reference */ } public function login(User $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } } Single Responsibility S.O.L.I.D
  19. 19. Single Responsibility Mudança , Dependência , Acoplamento , Ágil Conclusão ❖ SRP é o mais simples, e o mais difícil de fazer certo Finding and separating those responsibilities is much of what software design is really about. Indeed, the rest of the principles we discuss come back to this issue in one way or another. (Robert Martin) S.O.L.I.D
  20. 20. Mudança , Dependência , Acoplamento , Ágil Open / Closed Entidades (classes, módulos, etc) devem ser aberta para extensão, mas fechada para modificação Exemplos de Código S.O.L.I.D
  21. 21. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignManager { public function isAuthenticate(User $user) { // authenticate user in a database } } class GrantManager { public function hasRole(User $user, $role) { // checks user privileges } } class AccessControlService { public function __construct(SignManager $sign, GrantManager $grant) { /* save reference */ } public function login(User $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } } Open / Closed S.O.L.I.D
  22. 22. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignERPManager extends SignManager x { public function isAuthenticate(User $user) { // connect to third-party server resource } } class AccessControlService { public function __construct(SignManager $sign, GrantManager $grant) { /* save reference */ } public function login(User $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } } Open / Closed S.O.L.I.D class SignManager { public function isAuthenticate(User $user) { // authenticate user in a database } }
  23. 23. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignManager { public function __construct(DBConnection $conn) x { /* save reference */ } public function isAuthenticate(User $user) { /* authenticate user in a database */ } } class SignERPManager extends SignService { public function __construct(HTTPClient $client) x { /* save reference */ } public function isAuthenticate(User $user) { /* connect to third-party server resource */ } } Open / Closed S.O.L.I.D class AccessControlService { public function __construct(SignManager $sign, GrantManager $grant) { /* save reference */ } public function login(User $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } }
  24. 24. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } interface SignInterface x { public function isAuthenticate(User $user); } class SignDatabase implements SignInterface { public function isAuthenticate(User $user) { // authenticate user in a database } } class SignWebService implements SignInterface { public function isAuthenticate(User $user) { // connect to third-party server resource } } class AccessControlService { public function __construct(SignInterface $sign, GrantManager $grant) { /* save reference */ } public function login(User $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } } Open / Closed S.O.L.I.D
  25. 25. Open / Closed Mudança , Dependência , Acoplamento , Ágil Conclusão ❖ OCP está no coração do Design Orientado a Objetos ❖ Flexibilidade, Reutilização e Manutenibilidade Nor is it a good idea to apply rampant abstraction to every part of the application… Resisting premature abstraction is as important as abstraction itself. (Robert Martin) S.O.L.I.D
  26. 26. Dependency Inversion A. Módulos de Alto nível não devem depender de módulos de Baixo nível, ambos devem depender de Abstrações B. Abstrações não devem depender de detalhes, Detalhes devem depender de Abstrações Mudança , Dependência , Acoplamento , Ágil Exemplos de Código S.O.L.I.D
  27. 27. Mudança , Dependência , Acoplamento , Ágil class User { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } interface SignInterface { public function isAuthenticate(User $user); } class SignDatabase implements SignInterface { public function isAuthenticate(User $user) { // authenticate user in a database } } class SignWebService implements SignInterface { public function isAuthenticate(User $user) { // connect to third-party server resource } } Dependency Inversion S.O.L.I.D class AccessControlService { public function __construct(SignInterface $sign, GrantManager $grant) { /* save reference */ } public function login(User $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } }
  28. 28. Mudança , Dependência , Acoplamento , Ágil A. Módulos de Alto nível não devem depender de módulos de Baixo nível, ambos devem depender de Abstrações Dependency Inversion S.O.L.I.D
  29. 29. Mudança , Dependência , Acoplamento , Ágil A. Módulos de Alto nível não devem depender de módulos de Baixo nível, ambos devem depender de Abstrações Policy Mechanism Dependency Inversion S.O.L.I.D
  30. 30. Mudança , Dependência , Acoplamento , Ágil Policy Mechanism A. Módulos de Alto nível não devem depender de módulos de Baixo nível, ambos devem depender de Abstrações Dependency Inversion S.O.L.I.D
  31. 31. Mudança , Dependência , Acoplamento , Ágil class User implements UserInterface { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } interface SignInterface { public function isAuthenticate(User $user); } class SignDatabase implements SignInterface { public function isAuthenticate(UserInterface $user) { // authenticate user in a database } } class GrantManager implements GrantInterface { public function hasRole(UserInterface $user, $role) { // checks user privileges } } interface GrantInterface x { public function hasRole(User $user, $role); } interface UserInterface { // Getter & Setters } Dependency Inversion S.O.L.I.D class AccessControlService { public function __construct(SignInterface $sign, GrantInterface $grant) { /* save reference */ } public function login(UserInterface $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } }
  32. 32. Mudança , Dependência , Acoplamento , Ágil class User implements UserInterface { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } class SignDatabase implements SignInterface { public function __construct(DBConnection $conn) { /* save reference */ } public function isAuthenticate(UserInterface $user) { /* authenticate user in a database */ } } class SignWebService implements SignInterface { public function __construct(HTTPClient $client) { /* save reference */ } public function isAuthenticate(UserInterface $user) { /* connect to third-party server resource */ } } interface UserInterface { // Getter & Setters } interface SignInterface { public function isAuthenticate(User $user); } Dependency Inversion S.O.L.I.D class AccessControlService { public function __construct(SignInterface $sign, GrantInterface $grant) { /* save reference */ } public function login(UserInterface $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } }
  33. 33. Mudança , Dependência , Acoplamento , Ágil A. Módulos de Alto nível não devem depender de módulos de Baixo nível, ambos devem depender de Abstrações Utility Policy Mechanism Dependency Inversion S.O.L.I.D
  34. 34. Mudança , Dependência , Acoplamento , Ágil Utility Policy Mechanism Dependency Inversion S.O.L.I.D
  35. 35. Mudança , Dependência , Acoplamento , Ágil Utility Policy Mechanism RedisClientOAuthClient RedisInterfaceOAuthInterface SignOAuth SignRedis Dependency Inversion S.O.L.I.D
  36. 36. Mudança , Dependência , Acoplamento , Ágil Utility Policy Mechanism B. Abstrações não devem depender de detalhes, Detalhes devem depender de Abstrações Dependency Inversion S.O.L.I.D
  37. 37. Mudança , Dependência , Acoplamento , Ágil Utility Policy Mechanism B. Abstrações não devem depender de detalhes, Detalhes devem depender de Abstrações Dependency Inversion S.O.L.I.D
  38. 38. Mudança , Dependência , Acoplamento , Ágil class User implements UserInterface { public function setEmail($email) {} public function getEmail() {} public function setPassword($password) {} public function getPassword() {} } interface UserInterface { // Getter & Setters } interface Repository { x public function findUser($email, $password); } class HTTPClient implements Repository { x public function findUser($email, $password) { /* retrieve user from remote server */ } } class DBConnection implements Repository { x public function findUser($email, $password) { /* retrieve user from DataBase */ } } class SignManager implements SignInterface { public function __construct(Repository $repository) { /* save reference */ } public function isAuthenticate(UserInterface $user) { /* authenticate user in a repository */ } } Dependency Inversion S.O.L.I.D class AccessControlService { public function __construct(SignInterface $sign, GrantInterface $grant) { /* save reference */ } public function login(UserInterface $user) { if (!$this->sign->isAuthenticate($user) || !$this->grant->hasRole($user, 'admin')) { throw new InvalidUserException(); } return $user; } }
  39. 39. Mudança , Dependência , Acoplamento , Ágil Policy Mechanism Utility Dependency Inversion S.O.L.I.D
  40. 40. Dependency Inversion Conclusão ❖ Regras e detalhes devem depender de abstrações, que são definidas do ponto de vista do uso ❖ Quando as abstrações e detalhes estão isolados, é mais fácil de dar manutenção no código ... inversion of dependencies is the hallmark of good object-oriented design. (Robert Martin) Mudança , Dependência , Acoplamento S.O.L.I.D
  41. 41. Design Pattern TIME
  42. 42. Design Pattern: Strategy Mudança , Dependência , Acoplamento , Ágil , Composição , Interface class SignManager implements SignInterface { public function __construct(Repository $repository) { /* save reference */ } public function isAuthenticate(UserInterface $user) { /* authenticate user in a repository */ } } class Controller { public function loginAction($request) { $user = new User(); // set e-mail and password $repository = new DBConnection(); x $accessControl = new AccessControlService( new SignManager($repository), new GrantManager()); try { $accessControl->login($user); } catch (Exception $e) { $this->redirect('access-denied'); } $this->session->addUser($user); } } class DBConnection implements Repository x { public function findUser($email, $password) { /* find user in Database */ } }
  43. 43. class Controller { public function loginAction($request) { $user = new User(); // set e-mail and password $repository = new DBConnection(); if (strstr($user->getEmail(), '@new.com')) { $repository = new HTTPClient(); } $accessControl = new AccessControlService( new SignManager($repository), new GrantManager()); try { $accessControl->login($user); } catch (Exception $e) { $this->redirect('access-denied'); } $this->session->addUser($user); } } Mudança , Dependência , Acoplamento , Ágil , Composição , Interface class DBConnection implements Repository { public function findUser($email, $password) { /* find user in Database */ } } class HTTPClient implements Repository { public function findUser($email, $password) { /* find user in remote server */ } } Design Pattern: Strategy
  44. 44. class RepositoryStrategy implements Repository { private $context; public function __construct($context) { x $this->context = strstr($context, '@'); } private function getRepository() { switch ($this->context) { case "@old.com": return new DBConnection(); case "@new.com": return new HTTPClient(); } } public function findUser($email, $password) { return $this->getRepository() ->findUser($email, $password); } } Mudança , Dependência , Acoplamento , Ágil , Composição , Interface class DBConnection implements Repository { public function findUser($email, $password) { /* find user in Database */ } } class HTTPClient implements Repository { public function findUser($email, $password) { /* find user in remote server */ } } Design Pattern: Strategy class Controller { public function loginAction($request) { $user = new User(); // set e-mail and password $repository = new RepositoryStrategy($user->getEmail()); $accessControl = new AccessControlService( new SignManager($repository), new GrantManager()); try { $accessControl->login($user); } catch (Exception $e) { $this->redirect('access-denied'); } $this->session->addUser($user); } }
  45. 45. Quais são os Design Patterns Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Creational Abstract Factory Builder Factory Method Prototype Singleton Domain Logic Transaction Script Domain Model Table Module Service Layer Structural Adapter Bridge Composite Decorator Facade Flyweight Proxy Data Source Architectural Table Data Gateway Row Data Gateway Active Record Data Mapper Obj-Rel. Behavioral Unit of Work Identity Map Lazy Load Object-Rel. Structural Identity Field Foreign Key Mapping Association Table Mapping Dependent Mapping Embedded Value Serialized LOB Single Table Inheritance Class Table Inheritance Concrete Table Inheritance Inheritance Mappers Obj-Rel. Metadata Mapping Metadata Mapping Query Object Repository Web Presentation Model View Controller Page Controller Front Controller Template View Transform View Two-Step View Application Controller Distribution Remote Facade Data Transfer Object Offline Concurrency Optimistic Offline Lock Pessimistic Offline Lock Coarse Grained Lock Implicit Lock Session State Client Session State Server Session State Database Session State Base Gateway Mapper Layer Supertype Separated Interface Registry Value Object Money Special Case Plugin Service Stub Record Set Behavioral Chain of Responsibility Command Interpreter Iterator Mediator Memento Observer State Strategy Template Method Visitor GoF (Gang of Four): 23 PoEAA (Martin Fowler): 51
  46. 46. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface ❖ Solução Genérica para Problemas Recorrentes (reutilizável) (comuns) ❖ Nome, Problema, Solução e Consequências ❖ Facilita a comunicação entre Desenvolvedores (linguagem) (2002)(1994) Design Patterns
  47. 47. SOLID & Design Patterns através de exemplos
  48. 48. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Liskov Substitution Possibilidade de Substituir a Classe Base pela sua Derivada, sem alterar o funcionamento correto do Software Exemplos de Código S.O.L.I.D
  49. 49. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('+1 day'); } return $payDay; } } 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } Liskov Substitution S.O.L.I.D
  50. 50. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('+1 day'); } return $payDay; } } 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } Liskov Substitution S.O.L.I.D 1 2 3 4 5 6 7 8 9 10 11 12 13 class CreditCardCalculator extends PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('-1 day'); } return $payDay; } }
  51. 51. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('+1 day'); } return $payDay; } } 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } Liskov Substitution S.O.L.I.D 1 2 3 4 5 6 7 8 9 10 11 12 13 class CreditCardCalculator extends PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('-1 day'); } return $payDay->format('Y-m-d'); } }
  52. 52. 1 2 3 4 5 6 7 8 9 10 11 12 13 class CreditCardCalculator extends PaymentCalculator { public function calculatePayday(Payment $pay, $xy) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('-1 day'); } return $payDay; } } Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('+1 day'); } return $payDay; } } 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } Liskov Substitution S.O.L.I.D
  53. 53. 1 2 3 4 5 6 7 8 9 10 11 12 13 class CreditCardCalculator extends PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+4 day'); if(false == $calendar->isWorkDay($payDay)) { throw new InvalidDateException(); } return $payDay; } } Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('+1 day'); } return $payDay; } } 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } Liskov Substitution S.O.L.I.D
  54. 54. 1 2 3 4 5 6 7 8 9 10 11 12 13 class CreditCardCalculator extends PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('-1 day'); } return $payDay; } } Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); if(false == $calendar->isWorkDay($payDay)) { throw new InvalidDateException(); } return $payDay; } } 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } Liskov Substitution S.O.L.I.D
  55. 55. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('+1 day'); } return $payDay; } } 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } Liskov Substitution S.O.L.I.D 1 2 3 4 5 6 7 8 9 10 11 12 13 class CreditCardCalculator extends PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); if(false == $calendar->isWorkDay($payDay)) { $payDay->modify('-1 day'); } return $payDay; } }
  56. 56. Liskov Substitution Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Conclusão ❖ LSP é o principal facilitador do OCP ❖ Design by Contract (não peça demais, não prometa menos) The term IS-A is too broad to act as a definition of a subtype. The true definition of a subtype is substitutable ... (Robert Martin) S.O.L.I.D
  57. 57. Design Pattern TIME
  58. 58. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } 1 2 3 4 5 6 7 8 9 10 11 12 13 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('+1 day'); } return $payDay; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 class CreditCardCalculator extends PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $payDay->modify('-1 day'); } return $payDay; } } Design Pattern: Template Method
  59. 59. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $this->resolvePayDay($payDay); } return $payDay; } protected function resolvePayDay($payDay) { return $payDay->modify('+1 day'); } } 1 2 3 4 5 6 class CreditCardCalculator extends PaymentCalculator { protected function resolvePayDay($payDay) { return $payDay->modify('-1 day'); } } Design Pattern: Template Method
  60. 60. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 abstract class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $payDay = new DateTime($pay->getCreatedAt()); $payDay->modify('+5 day'); while(false == $calendar->isWorkDay($payDay)) { $this->resolvePayDay($payDay); } return $payDay; } abstract protected function resolvePayDay($payDay); } 1 2 3 4 5 6 class CreditCardCalculator extends PaymentCalculator { protected function resolvePayDay($payDay) { return $payDay->modify('-1 day'); } } Design Pattern: Template Method 1 2 3 4 5 6 class BilletCalculator extends PaymentCalculator { protected function resolvePayDay($payDay) { return $payDay->modify('+1 day'); } } 1 2 3 class CCardPayment implements Payment { // attributes and methods } 1 interface Payment { } 1 2 3 class BilletPayment implements Payment { // attributes and methods } 1 2 3 4 5 6 7 8 9 10 11 class PaymentManager { public function __construct(PaymentCalculator $calculator) { // save reference } public function schedulePayment(Payment $payment) { $payday = $this->calculator->calculatePayday($payment); $payment->setPayday($payday); // save in database } }
  61. 61. Interface Segregation Muitas Interfaces específicas são melhores do que uma Inferface de proposito geral Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Exemplos de Código S.O.L.I.D
  62. 62. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Exemplos de Código S.O.L.I.D
  63. 63. Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Exemplos de Código S.O.L.I.D
  64. 64. Interface Segregation Conclusão ❖ Evita a utilização de “Fat Classes” ❖ Quebra a dependência de métodos que não são invocados pelos clientes ❖ Permite a independência entre clientes Mudança , Dependência , Acoplamento , Ágil , Composição , Interface S.O.L.I.D
  65. 65. Consolidando Conceitos
  66. 66. Object Oriented Mindset Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Injeção de Dependência Procedural Matriosca
  67. 67. Agile Software Development, Principles, Patterns, and Practices (Robert Martin - 2002) Agile Principles, Patterns, and Practices in C# (Robert Martin - 2006) SOLID e Design Patterns The Pragmatic Programmer (Andrew Hunt and Devid Thomas - 1999) Coesão, Acoplamento, Ortogonalidade, Design por Contrato, Lei de Deméter Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin - 2008) Lei de Deméter, Data Transfer Objects, TDD Domain-Driven Design: Tackling Complexity in the Heart of Software (Erich Evans - 2003) Design Patterns: Elements of Reusable Object-Oriented Software (Gang of Four - 1994) Patterns of Enterprise Applications Architecture (PoeAA: Martin Fowler - 2002) Apps para Android Mudança , Dependência , Acoplamento , Ágil , Composição , Interface Indicação de Livros
  68. 68. VALEU !!! Mario Rezende - @mariorez
  69. 69. Princípios Orientação Objetos Abstração Encapsulamento Herança Composição Modularidade Polimorfismo Princípios de Design de Classe Padrões de Design Arquitetura em Camadas Arquitetura Distribuída Mudança , Dependência , Acoplamento , Ágil implementação conceitual Coesão < Acoplamento Ortogonalidade Design p/ Contrato Lei de Deméter DDD Hexagonal MVC Solução Genérica Problema Recorrente Programe p/ Interface Prefira Composição Mic.Serv. SOA SaaS Onde o SOLID se “encaixa”
  70. 70. Princípios Orientação Objetos Abstração Encapsulamento Herança Composição Modularidade Polimorfismo Princípios de Design de Classe Padrões de Design Arquitetura em Camadas Arquitetura Distribuída Coesão < Acoplamento Ortogonalidade Design p/ Contrato Lei de Deméter Mudança , Dependência , Acoplamento , Ágil , Composição , Interface SOLID implementação conceitual Onde o SOLID se “encaixa” DDD Hexagonal MVC Solução Genérica Problema Recorrente Programe p/ Interface Prefira Composição Mic.Serv. SOA SaaS

×