Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Marcel dos Santos

June 24, 2020
Tweet

More Decks by Marcel dos Santos

Other Decks in Programming

Transcript

  1. 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
  2. !// 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}!"; } }
  3. !// 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!
  4. !// current state of $alice object var_dump($alice); !/* class User#3

    (2) { private $name !=> string(5) "Alice" private $age !=> int(22) } !*/
  5. !// 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}!"; } }
  6. !// 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!
  7. !// current state of $alice object var_dump($alice); !/* class User#3

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

    herda características e atributos de uma classe base
  9. !// 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 } }
  10. 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
  11. !// 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
  12. a injeção de dependência é uma técnica que permite reduzir

    o acoplamento entre classes ou módulos…
  13. !// dependency injection via constructor class Car { private $engine;

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

    new Engine(); $car = new Car($engine); $car!->start(); !// Starting the engine
  15. 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
  16. 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:
  17. !// 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 } }
  18. !// 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()); } }
  19. !// geolocation services abstraction (contract) !// each concrete implementation must

    follow this contract interface GeolocationService { public function getCoordinatesFromAddress($address); }
  20. !// 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 } }
  21. !// 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()); } }
  22. !// value objects that represent 30 dollars $priceBook = new

    Money(30, new Currency('USD')); $priceMeal = new Money(30, new Currency('USD')); $priceBook!->equals($priceMeal); !// true
  23. !// 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', '[email protected]'); $bob = new User('Bob', '123456');
  24. !// 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('[email protected]')); $bob = new User('Bob', new Email('123456')); !// throws an exception
  25. recomenda-se utilizar value objects no caso de valores que possuem

    validação, regras de negócio ou comportamento
  26. 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
  27. 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ê
  28. 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
  29. 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.)
  30. Learning OOP in PHP Tutoriais, vídeos, slides, livros sobre OOP,

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