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. Marcel Gonçalves dos Santos
    @marcelgsantos
    orientado a objetos
    projetando software
    com qualidade

    View Slide

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

    View Slide

  3. @phpsp
    phpsp.org.br

    View Slide

  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

    View Slide

  5. O que é
    Orientação a Objetos?

    View Slide

  6. é um paradigma de programação que trata
    da comunicação entre objetos através da
    troca de mensagens

    View Slide

  7. um objeto é uma representação concreta
    de uma abstração…

    View Slide

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

    View Slide

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

    View Slide

  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}!";
    }
    }

    View Slide

  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!

    View Slide

  12. !// current state of $alice object
    var_dump($alice);
    !/* class User#3 (2) {
    private $name !=>
    string(5) "Alice"
    private $age !=>
    int(22)
    } !*/

    View Slide

  13. Pilares da
    Orientação a Objetos

    View Slide

  14. abstração

    trata da representação de um conceito da
    vida real dentro do sistema

    View Slide

  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}!";
    }
    }

    View Slide

  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!

    View Slide

  17. !// current state of $alice object
    var_dump($alice);
    !/* class User#3 (2) {
    private $name !=>
    string(5) "Alice"
    private $age !=>
    int(22)
    } !*/

    View Slide

  18. herança

    permite o reaproveitamento de código em
    que uma classe herda características e
    atributos de uma classe base

    View Slide

  19. encapsulamento

    permite ocultar a implementação interna de
    um objeto

    View Slide

  20. polimorfismo

    consiste na alteração do funcionamento
    interno de um método herdado do pai

    View Slide

  21. Os maus cheiros
    do projeto

    View Slide

  22. rigidez

    tendência do software de ser difícil de
    alterar, mesmo de maneira simples

    View Slide

  23. fragilidade

    tendência de um programa estragar em
    muitos lugares quando uma única alteração
    é feita

    View Slide

  24. imobilidade

    quando existem partes que poderiam ser
    úteis em outro sistema…

    View Slide

  25. imobilidade

    …mas o trabalho e riscos na separação
    dessas partes são muito grandes
    (cont.)

    View Slide

  26. viscosidade

    característica que diz o quão difícil é de
    preservar um software

    View Slide

  27. complexidade desnecessária

    quando existem elementos que não serão
    úteis no momento

    View Slide

  28. repetição desnecessária

    é quando um mesmo código aparece
    inúmeras vezes, de formas pouco diferentes

    View Slide

  29. opacidade

    refere-se a dificuldade de compreensão de
    um módulo

    View Slide

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

    View Slide

  31. coesão

    indica o grau de relação entre os membros
    de um módulo

    View Slide

  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
    }
    }

    View Slide

  33. acoplamento

    indica o grau de dependência entre módulos

    View Slide

  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

    View Slide

  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

    View Slide

  36. o acoplamento é algo desejado, porém, que
    deve ser controlado

    View Slide

  37. ao controlar o acoplamento, o software
    torna-se mais flexível e fácil de manter

    View Slide

  38. e como podemos reduzir o acoplamento
    entre classes ou módulos?

    View Slide

  39. Injeção de
    dependência

    View Slide

  40. a injeção de dependência é uma técnica
    que permite reduzir o acoplamento entre
    classes ou módulos…

    View Slide

  41. …e consiste em fornecer uma dependência
    do mundo externo para uma classe

    View Slide

  42. !// dependency injection via constructor
    class Car
    {
    private $engine;
    public function !__construct(Engine $engine)
    {
    $this!->engine = $engine;
    }
    public function start()
    {
    $this!->engine!->start();
    }
    }

    View Slide

  43. !// inject an engine dependency into the car
    $engine = new Engine();
    $car = new Car($engine);
    $car!->start(); !// Starting the engine

    View Slide

  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

    View Slide

  45. “prefira classes com alta coesão e baixo
    acoplamento”

    View Slide

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

    View Slide

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

    View Slide

  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:

    View Slide

  49. Classe A Classe B
    referencia

    View Slide

  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
    }
    }

    View Slide

  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());
    }
    }

    View Slide

  52. StoreService GoogleMaps
    referencia

    View Slide

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

    View Slide

  54. Classe B
    referencia
    Classe A
    Interface
    implementa

    View Slide

  55. !// geolocation services abstraction (contract)
    !// each concrete implementation must follow this contract
    interface GeolocationService
    {
    public function getCoordinatesFromAddress($address);
    }

    View Slide

  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
    }
    }

    View Slide

  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());
    }
    }

    View Slide

  58. GoogleMaps
    referencia
    StoreService
    GeolocationService
    implementa

    View Slide

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

    View Slide

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

    View Slide

  61. Objetos de valor

    Value objects

    View Slide

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

    View Slide

  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

    View Slide

  64. um objeto de valor deve ser imutável e
    existir em um estado consistente

    View Slide

  65. ele permite centralizar a regra de negócio e
    evitar que ela fique espalhada pelo código

    View Slide

  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', '[email protected]');
    $bob = new User('Bob', '123456');

    View Slide

  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('[email protected]'));
    $bob = new User('Bob', new Email('123456')); !// throws an exception

    View Slide

  68. recomenda-se utilizar value objects no caso
    de valores que possuem validação, regras de
    negócio ou comportamento

    View Slide

  69. pele permite representar a linguagem
    ubíqua no seu código

    View Slide

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

    View Slide

  71. primitive obsession

    trata-se de utilizar tipos de dados primitivos
    para representar ideias de domínio

    View Slide

  72. Tell Don’t Ask

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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ê

    View Slide

  77. Law of Demeter

    View Slide

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

    View Slide

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

    View Slide

  80. Object Calisthenics

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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.)

    View Slide

  85. View Slide

  86. as regras não estão escritas em pedra!

    View Slide

  87. utilize aquelas que se sentir mais
    confortável

    View Slide

  88. Conclusão

    View Slide

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

    View Slide

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

    View Slide

  91. uma classe não deve ser forçada a depender
    de uma implementação específica

    View Slide

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

    View Slide

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

    View Slide

  94. Referências

    View Slide

  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

    View Slide

  96. Avalie!

    View Slide

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

    View Slide