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

Melhore a Qualidade do seu Código com Object Calisthenics

Melhore a Qualidade do seu Código com Object Calisthenics

Um código com qualidade é essencial para um projeto de sucesso e existem diversas práticas que ajudam a alcançar esse objetivo. Object Calisthenics é uma série de boas práticas que ajudarão a tornar o seu legível, manutenível, testável e compreensível. Com uma dose pequena de exercícios diários, você notará a diferença no seu código.

52711e2157a6fed933b0361cc06a6953?s=128

Marcel dos Santos

November 28, 2017
Tweet

Transcript

  1. Marcel Gonçalves dos Santos @marcelgsantos Object Calisthenics Melhore a qualidade

    do seu código com
  2. pensandonaweb.com.br desenvolvedor web full-stack Marcel Gonçalves dos Santos @marcelgsantos

  3. None
  4. @phpsp phpsp.org.br #php #phpsp #LaraconfBrasil2017

  5. @femugsp sp.femug.com

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

    OOD, design patterns, refatoração e arquitetura. bit.ly/Learning-OOP-in-PHP
  7. O que é Object Calisthenics?

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

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

  10. inventado por Jeff Bay
 e faz parte do livro The

    ThoughtWorks Antology
  11. a palavra object
 refere-se a programação orientada a objetos

  12. a palavra calisthenics
 refere-se a calistenia ou exercícios

  13. youtu.be/YShxi4iVbO0?t=472

  14. motivação
 tornar o código legível, manutenível, testável e compreensível

  15. conceitos adaptados para o PHP por Guilherme Blanco, Otavio Ferreira

    e Rafael Dohms
  16. Regra 1 somente um nível de indentação por método

  17. muitos níveis de indentação dificulta a legibilidade e manutenibilidade

  18. None
  19. function productsWithDiscount($products) { $productsWithDiscount = []; if (isset($products) !&& count($products))

    { foreach ($products as $product) { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } } return $productsWithDiscount; } Exemplo 1
  20. function productsWithDiscount($products) { $productsWithDiscount = []; if (isset($products) !&& count($products))

    { foreach ($products as $product) { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } } return $productsWithDiscount; } Exemplo 1 0 1 2 3
  21. function productsWithDiscount($products) { $productsWithDiscount = []; if (isset($products) !&& count($products))

    { foreach ($products as $product) { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } } return $productsWithDiscount; } Exemplo 1 0 1 2 3 três níveis de indentação
  22. function productsWithDiscount($products) { $productsWithDiscount = []; if (isset($products) !&& count($products))

    { foreach ($products as $product) { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } } return $productsWithDiscount; } Exemplo 1
  23. function productsWithDiscount($products) { $productsWithDiscount = []; if (isset($products) !&& count($products))

    { foreach ($products as $product) { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } } return $productsWithDiscount; } Exemplo 1 remover condições desnecessárias
  24. function productsWithDiscount($products) { $productsWithDiscount = []; foreach ($products as $product)

    { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } return $productsWithDiscount; } Exemplo 1 0 1 2
  25. recomenda-se dividir os métodos

  26. Refatoração
 utilize o padrão Extract Method

  27. function productsWithDiscount($products) { $productsWithDiscount = []; foreach ($products as $product)

    { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } return $productsWithDiscount; } Exemplo 1
  28. function productsWithDiscount($products) { $productsWithDiscount = []; foreach ($products as $product)

    { if ($product['has_discount']) { $productsWithDiscount[] = $product; } } return $productsWithDiscount; } Exemplo 1 extrai para um método utiliza função para filtragem
  29. Exemplo 1 function productsWithDiscount($products) { return array_filter($products, 'productHasDiscount'); } function

    productHasDiscount($product) { return $product['has_discount']; }
  30. Exemplo 1 function productsWithDiscount($products) { return array_filter($products, function($product) { return

    $product['has_discount']; }); } somente um nível de indentação
  31. * facilita a leitura
 * reduz a complexidade ciclomática *

    favorece o SRP e o KISS * encoraja o reuso Benefícios
  32. Regra 2 não utilizar a palavra-chave else

  33. function login($username, $password) { if ($this!->isValid($username, $password)) { return redirect('homepage');

    } else { addFlash('error', 'invalid login'); return redirect('login'); } } Exemplo 2
  34. recomenda-se utilizar a abordagem early return

  35. pode-se adotar uma abordagem defensiva ou otimista

  36. function login($username, $password) { !// defensive approach if ($this!->isValid($username, $password))

    { return redirect('homepage'); } addFlash('error', 'invalid login'); return redirect('login'); } Exemplo 2
  37. function login($username, $password) { !// optimistic approach if (! $this!->isValid($username,

    $password)) { addFlash('error', 'invalid login'); return redirect('login'); } return redirect('homepage'); } Exemplo 2
  38. * facilita a leitura
 * reduz a complexidade ciclomática *

    evita a duplicidade de código Benefícios
  39. None
  40. None
  41. Regra 3 encapsular todos tipos primitivos e strings

  42. evita o anti-pattern conhecido como primitive obsession

  43. primitive obsession é usar tipos de dados primitivos para representar

    ideias de domínio
  44. Exemplo
 ao utilizar e-mail como string ou valor monetário como

    float
  45. Quando aplicar?
 quando os tipos possuem validação, regras de negócio

    ou comportamento
  46. class User { private $name; private $email; public function !__construct(string

    $name, string $email) { $this!->name = $name; $this!->email = $email; } } $user = new User('Alice', 'alice@company.com'); !// ok $anotherUser = new User('Bob', '1122334455'); !// ok Exemplo 3
  47. class Email { private $email; public function !__construct(string $email) {

    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException('invalid format'); } $this!->email = $email; } } $user = new User(‘Alice', new Email('alice@company.com')); !// ok $anotherUser = new User('Bob', new Email('1122334455')); !// not ok Exemplo 3
  48. recomenda-se utilizar um value object no lugar do tipo primitivo

    como, por exemplo, Money
  49. os value objects são um dos building-blocks do domain- driven

    design
  50. * uso de type hinting
 * encoraja o reuso *

    evita a duplicidade de código Benefícios
  51. Regra 4 coleções de primeira classe

  52. qualquer classe que contém uma coleção não deve conter nenhum

    outro atributo
  53. permite adicionar operações relacionadas para a manipulação da coleção

  54. * facilita a leitura
 * facilita a operação sobre a

    coleção Benefícios
  55. Regra 5 um ponto por linha

  56. o ponto é o operador para a chamada de método

    em Java e C#
  57. em PHP utiliza-se a seta (->) como operador

  58. uma seta (->) por linha

  59. a regra diz para não encadear chamadas de método

  60. problema quando um método interno retorna nulo

  61. obedecer a regra é seguir a Law of Demeter

  62. Law of Demeter fale com seus amigos mais próximos e

    não fale com estranhos
  63. $objectA!->getObjectB()!->getObjectC();

  64. não se aplica a interfaces fluentes ou implementação de Method

    Chaining
  65. * facilita a leitura
 * facilita o debug * segue

    a Law of Demeter Benefícios
  66. Regra 6 não abrevie

  67. Pergunta Qual o motivo de querer abreviar?

  68. Classes com muitas responsabilidades?!

  69. Código duplicado?!

  70. There are only two hard things in Computer Science: cache

    invalidation and naming things. Phil Karlton
  71. * facilita a leitura
 * facilita a manutenção Benefícios

  72. Regra 7 mantenha todas as entidades pequenas

  73. evite God Classes

  74. God Class classe que sabe demais ou faz demais

  75. classes com 50 linhas ou menos

  76. pacotes com 10 arquivos ou menos

  77. arquivos grandes são difíceis de ler, entender e manter

  78. * encoraja o reuso * melhor segregação do código *

    favorece o SRP Benefícios
  79. Regra 8 nenhuma classe com mais de duas cinco variáveis

    de instância
  80. provavelmente a regra mais difícil de seguir

  81. promove alta coesão e melhor encapsulamento

  82. * facilita a manutenção * lista de dependências curta Benefícios

  83. Regra 9 sem getters, setters ou propriedades

  84. obedecer a regra é seguir o princípio Tell Don’t Ask

  85. Tell Don’t Ask não peça informações para fazer o seu

    trabalho, apenas diga para o objeto que possui a informação para fazer o trabalho para você
  86. !// Game class private $score; public function setScore($score) { $this!->score

    = $score; } public function getScore() { return $this!->score; } !// Usage $game!->setScore($game!->getScore() + ENEMY_DESTROYED_SCORE); Exemplo 4
  87. !// Game class private $score; public function setScore($score) { $this!->score

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

    } !// Usage $game!->addScore(ENEMY_DESTROYED_SCORE); Exemplo 4 está dizendo para o objeto realizar o trabalho para você
  89. use o encapsulamento
 a seu favor

  90. * facilita a leitura * evita violar OCP Benefícios

  91. Revisão

  92. 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 Revisão
  93. 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 Revisão (continuação)
  94. None
  95. Conclusões

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

  97. utilize aquelas que se sentir mais confortável

  98. tente utilizá-las aos poucos e em projetos paralelos

  99. Referências

  100. bit.ly/object-calisthenics-referencias

  101. Avalie!

  102. Perguntas?

  103. Obrigado. @marcelgsantos speakerdeck.com/marcelgsantos