Projetando Software Orientado a Objetos com Qualidade

Projetando Software Orientado a Objetos com Qualidade

O paradigma orientado a objetos, apesar de bastante conhecido, é muito mais difícil do que parece. Nesta palestra iremos conhecer diversas práticas e princípios de design orientado a objetos e como eles ajudam a melhorar a qualidade e robustez de seu código.

52711e2157a6fed933b0361cc06a6953?s=128

Marcel dos Santos

June 24, 2020
Tweet

Transcript

  1. Marcel Gonçalves dos Santos @marcelgsantos orientado a objetos projetando software

    com qualidade
  2. pensandonaweb.com.br desenvolvedor web full-stack Marcel Gonçalves dos Santos @marcelgsantos

  3. @phpsp phpsp.org.br

  4. Interaja nas mídias sociais!
 
 - fale sobre o evento,

    palestrantes e conteúdo - tire fotos do evento e publique
 - interaja com outros participantes do evento - tire dúvidas ou dê feedbacks para os palestrantes
  5. O que é Orientação a Objetos?

  6. é um paradigma de programação que trata da comunicação entre

    objetos através da troca de mensagens
  7. um objeto é uma representação concreta de uma abstração…

  8. …que possui características, comportamentos e estado atual

  9. a orientação a objetos pode ser baseada em classes ou

    baseada em protótipos
  10. !// class to create a User object class User {

    private string $name; private int $age; public function !__construct(string $name, int $age) { $this!->name = $name; $this!->age = $age; } public function sayName() : void { echo "Hello, my name is {$this!->name}!"; } }
  11. !// two objects representing user abstractions $alice = new User('Alice',

    22); $bob = new User('Bob', 27); $alice!->sayName(); !// Hello, my name is Alice! $bob!->sayName(); !// Hello, my name is Bob!
  12. !// current state of $alice object var_dump($alice); !/* class User#3

    (2) { private $name !=> string(5) "Alice" private $age !=> int(22) } !*/
  13. Pilares da Orientação a Objetos

  14. abstração
 trata da representação de um conceito da vida real

    dentro do sistema
  15. !// class to create a User object class User {

    private string $name; private int $age; public function !__construct(string $name, int $age) { $this!->name = $name; $this!->age = $age; } public function sayName() : void { echo "Hello, my name is {$this!->name}!"; } }
  16. !// two objects representing user abstractions $alice = new User('Alice',

    22); $bob = new User('Bob', 27); $alice!->sayName(); !// Hello, my name is Alice! $bob!->sayName(); !// Hello, my name is Bob!
  17. !// current state of $alice object var_dump($alice); !/* class User#3

    (2) { private $name !=> string(5) "Alice" private $age !=> int(22) } !*/
  18. herança
 permite o reaproveitamento de código em que uma classe

    herda características e atributos de uma classe base
  19. encapsulamento
 permite ocultar a implementação interna de um objeto

  20. polimorfismo
 consiste na alteração do funcionamento interno de um método

    herdado do pai
  21. Os maus cheiros do projeto

  22. rigidez
 tendência do software de ser difícil de alterar, mesmo

    de maneira simples
  23. fragilidade
 tendência de um programa estragar em muitos lugares quando

    uma única alteração é feita
  24. imobilidade
 quando existem partes que poderiam ser úteis em outro

    sistema…
  25. imobilidade
 …mas o trabalho e riscos na separação dessas partes

    são muito grandes (cont.)
  26. viscosidade
 característica que diz o quão difícil é de preservar

    um software
  27. complexidade desnecessária
 quando existem elementos que não serão úteis no

    momento
  28. repetição desnecessária
 é quando um mesmo código aparece inúmeras vezes,

    de formas pouco diferentes
  29. opacidade
 refere-se a dificuldade de compreensão de um módulo

  30. Princípios da Orientação a Objetos

  31. coesão
 indica o grau de relação entre os membros de

    um módulo
  32. !// is this class cohesive or not cohesive? class Cart

    { private array $items; public function !__construct() { $this!->items = []; } public function numberOfItems() : int { return count($this!->items); } public function calculateDeliveryPrice() : float { !// calculates the delivery price } }
  33. acoplamento
 indica o grau de dependência entre módulos

  34. o acoplamento ocorre quando o código de um módulo utiliza

    código de outro módulo, seja ao chamar uma função ou acessar algum dado
  35. !// class Car is coupled to Engine class class Car

    { private $engine; public function !__construct() { $this!->engine = new Engine(); } public function start() { $this!->engine!->start(); !// engine is a dependency } } $car = new Car(); $car!->start(); !// Starting the engine
  36. o acoplamento é algo desejado, porém, que deve ser controlado

  37. ao controlar o acoplamento, o software torna-se mais flexível e

    fácil de manter
  38. e como podemos reduzir o acoplamento entre classes ou módulos?

  39. Injeção de dependência

  40. a injeção de dependência é uma técnica que permite reduzir

    o acoplamento entre classes ou módulos…
  41. …e consiste em fornecer uma dependência do mundo externo para

    uma classe
  42. !// dependency injection via constructor class Car { private $engine;

    public function !__construct(Engine $engine) { $this!->engine = $engine; } public function start() { $this!->engine!->start(); } }
  43. !// inject an engine dependency into the car $engine =

    new Engine(); $car = new Car($engine); $car!->start(); !// Starting the engine
  44. utilizar injeção de dependências auxilia nos testes unitários pois tornam

    os módulos fracamente acoplados, altamente coesos e facilita o mocking de objetos
  45. “prefira classes com alta coesão e baixo acoplamento”

  46. Princípio da inversão de dependência Dependency Inversion Principle

  47. o princípio de inversão de dependência é a letra “D”

    do SOLID
  48. 3. módulos de baixo nível também devem
 depender de abstrações

    2. módulos de alto nível devem depender 
 de abstrações e não de implementações 1. módulos de alto nível não devem 
 depender de módulos de baixo nível o princípio de inversão de dependência diz:
  49. Classe A Classe B referencia

  50. !// concrete implementation in order to get coordinates !// from

    address in Google Maps and OpenStreetMap class GoogleMaps { public function getCoordinatesFromAddress($address) { !// calls Google Maps webservice } } class OpenStreetMap { public function getCoordinatesFromAddress($address) { !// calls OpenStreetMap webservice } }
  51. !// class StoreService depends on a concrete implementation !// of

    GoogleMaps geolocation service class StoreService { public function getStoreCoordinates($store) { $geolocationService = new GoogleMaps(); return $geolocationService !->getCoordinatesFromAddress($store!->getAddress()); } }
  52. StoreService GoogleMaps referencia

  53. uma classe não deve depender de um módulo de baixo

    nível
  54. Classe B referencia Classe A Interface implementa

  55. !// geolocation services abstraction (contract) !// each concrete implementation must

    follow this contract interface GeolocationService { public function getCoordinatesFromAddress($address); }
  56. !// concrete implementation must follow the contract class GoogleMaps implements

    GeolocationService { public function getCoordinatesFromAddress($address) { !// calls Google Maps webservice } } class OpenStreetMap implements GeolocationService { public function getCoordinatesFromAddress($address) { !// calls OpenStreetMap webservice } }
  57. !// the class should depends on abstraction (GeolocationService) class StoreService

    { private $geolocationService; public function !__construct(GeolocationService $geolocationService) { $this!->geolocationService = $geolocationService; } public function getStoreCoordinates($store) { return $this!->geolocationService !->getCoordinatesFromAddress($store!->getAddress()); } }
  58. GoogleMaps referencia StoreService GeolocationService implementa

  59. uma classe deve depender de um contrato, abstração ou interface

  60. ao depender de abstrações você desacopla o seu código da

    dependência
  61. Objetos de valor
 Value objects

  62. são objetos simples e pequenos em que a igualdade não

    é baseada em identidade
  63. !// value objects that represent 30 dollars $priceBook = new

    Money(30, new Currency('USD')); $priceMeal = new Money(30, new Currency('USD')); $priceBook!->equals($priceMeal); !// true
  64. um objeto de valor deve ser imutável e existir em

    um estado consistente
  65. ele permite centralizar a regra de negócio e evitar que

    ela fique espalhada pelo código
  66. !// User class accepts an invalid email class User {

    private string $name; private string $email; public function !__construct(string $name, string $email) { $this!->name = $name; $this!->email = $email; } } $alice = new User('Alice', 'alice@company.com'); $bob = new User('Bob', '123456');
  67. !// email value object class Email { private $email; public

    function !__construct(string $email) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException('invalid format'); } $this!->email = $email; } } $alice = new User('Alice', new Email('alice@company.com')); $bob = new User('Bob', new Email('123456')); !// throws an exception
  68. recomenda-se utilizar value objects no caso de valores que possuem

    validação, regras de negócio ou comportamento
  69. pele permite representar a linguagem ubíqua no seu código

  70. utilizá-los ajuda a evitar o anti-padrão conhecido como primitive obsession

  71. primitive obsession
 trata-se de utilizar tipos de dados primitivos para

    representar ideias de domínio
  72. Tell Don’t Ask

  73. não peça informações para um objeto para fazer o seu

    trabalho…
  74. …apenas diga para o objeto que possui a informação para

    fazer o trabalho para você
  75. class Game 
 { private $score; public function setScore($score) {

    $this!->score = $score; } public function getScore() { return $this!->score; } } $game!->setScore($game!->getScore() + ENEMY_DESTROYED_SCORE); está pedindo informações para realizar seu trabalho
  76. class Game { private $score; public function addScore($delta) { this!->score

    += $delta; } } $game!->addScore(ENEMY_DESTROYED_SCORE); está dizendo para o objeto realizar o trabalho para você
  77. Law of Demeter

  78. fale com seus amigos mais próximos e não fale com

    estranhos
  79. $objectA!->getObjectB()!->getObjectC();

  80. Object Calisthenics

  81. são exercícios de programação formalizados em 9 regras…

  82. … o exercício dessas regras ajudará a escrever código melhor

  83. object calisthenics
 1. somente um nível de indentação por método

    2. não utilizar a palavra-chave else 3. encapsular todos tipos primitivos e strings 4. coleções de primeira classe 5. um ponto por linha
  84. object calisthenics
 6. não abrevie
 7. mantenha todas as entidades

    pequenas 8. nenhuma classe com mais de duas variáveis de instância 9. sem getters, setters ou propriedades (cont.)
  85. None
  86. as regras não estão escritas em pedra!

  87. utilize aquelas que se sentir mais confortável

  88. Conclusão

  89. os princípios de design ajudam a projetar códigos melhores

  90. um código mau projetado é um código difícil de mudar

  91. uma classe não deve ser forçada a depender de uma

    implementação específica
  92. uma classe deve depender de um contrato, abstração ou interface

  93. prefira classes com alta coesão e baixo acoplamento

  94. Referências

  95. Learning OOP in PHP Tutoriais, vídeos, slides, livros sobre OOP,

    OOD, design patterns, refatoração e arquitetura. bit.ly/Learning-OOP-in-PHP
  96. Avalie!

  97. @marcelgsantos speakerdeck.com/marcelgsantos Obrigado. Perguntas?