Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

PHPubSP Object Calisthenics aplicado ao PHP

7,768 views

Published on

Apresentação ministrada em 27/09/2011 no Tribeca Pub em São Paulo.

Object Calisthenics são exercícios que podem ser praticados com o objetivo de melhor

Published in: Technology

PHPubSP Object Calisthenics aplicado ao PHP

  1. 1. Object Calisthenics Aplicado ao PHP
  2. 2. Object CalisthenicsO palestrante @guilhermeblanco http://github.com/guilhermeblanco
  3. 3. Object CalisthenicsAgenda‣ Motivação‣ Regras‣ Aplicação
  4. 4. Object CalisthenicsO que é Object Calisthenics?‣ Object Calisthenics
  5. 5. Object CalisthenicsO que é Object Calisthenics?‣ Object Calisthenics Termo derivado do grego “exercício”, sob o contexto de ginástica.
  6. 6. Object CalisthenicsO que é Object Calisthenics?‣ Jeff Bay em The ThoughtWorks Anthology[1] cunhou o termo Object Calisthenics para a computação, como o conjunto de exercícios para a programação Orientada a Objetos.[1] The ThoughtWorks Anthology: Essays on Software Technology and Innovation
  7. 7. Object CalisthenicsMotivação‣ Código legível‣ Compreensível‣ Testável‣ Manutenível
  8. 8. Object CalisthenicsRegras‣ Nove (9) regras “bem” simples...
  9. 9. Object CalisthenicsRegra 1: Somente um nível de indentação por método‣ Somente um nível de indentação por método
  10. 10. Object CalisthenicsRegra 1: Somente um nível de indentação por método‣ Somente um nível de indentação por método Neologismo derivado da palavra inglesa “indentatio”, que significa “recuo”.
  11. 11. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validaFormulario($filters=, $validators=, $options=){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ($input->hasInvalid() || $input->hasMissing()) { foreach ($input->getMessages() as $campo => $message) { foreach ($message as $mensagem) { if (strpos($mensagem, "empty")) { throw new Tss_FormException( "O campo {$campo} não pode ser vazio!", 3, javascript:history.back(); ); } else { throw new Tss_FormException( "{$mensagem}", 3, javascript:history.back(); ); } } } } return $input;}
  12. 12. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validaFormulario($filters=, $validators=, $options=){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); 0 ($input->hasInvalid() || $input->hasMissing()) { $message) { if 1 ($message as $mensagem) { foreach ($input->getMessages() as $campo => 2 3 foreach if (strpos($mensagem, "empty")) { 4 throw new Tss_FormException( "O campo {$campo} não pode ser vazio!", 3, javascript:history.back(); ); } else { throw new Tss_FormException( "{$mensagem}", 3, javascript:history.back(); ); } } } } return $input;}
  13. 13. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validaFormulario($filters=, $validators=, $options=){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); 0 ($input->hasInvalid() || $input->hasMissing()) { $message) { if 1 ($message as $mensagem) { foreach ($input->getMessages() as $campo => 2 3 foreach if (strpos($mensagem, "empty")) { 4 throw new Tss_FormException( "O campo {$campo} não pode ser vazio!", 3, javascript:history.back(); ); } else { throw new Tss_FormException( "{$mensagem}", 3, javascript:history.back(); ); } } } } return $input;}
  14. 14. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validaFormulario($filters = array(), $validators = array(), $options = null){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } foreach ($input->getMessages() as $campo => $message) { foreach ($message as $mensagem) { if (strpos($mensagem, "empty")) { throw new Tss_FormException( "O campo {$campo} não pode ser vazio!", 3, javascript:history.back(); ); } else { throw new Tss_FormException( "{$mensagem}", 3, javascript:history.back(); ); } } }}
  15. 15. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validaFormulario($filters = array(), $validators = array(), $options = null){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } 0 foreach ($message as $mensagem) { => $message) { foreach ($input->getMessages() as $campo 1 (strpos($mensagem, "empty")) { if 2 3 throw new Tss_FormException( "O campo {$campo} não pode ser vazio!", 3, javascript:history.back(); ); } else { throw new Tss_FormException( "{$mensagem}", 3, javascript:history.back(); ); } } }}
  16. 16. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validaFormulario($filters = array(), $validators = array(), $options = null){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } foreach ($input->getMessages() as $campo => $message) { foreach ($message as $mensagem) { $errorMessage = (strpos($mensagem, "empty") === false) ? "O campo {$campo} não pode ser vazio!" : "{$mensagem}"; throw new Tss_FormException( $errorMessage, 3, javascript:history.back(); ); } }}
  17. 17. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validaFormulario($filters = array(), $validators = array(), $options = null){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } 0 foreach ($message as $mensagem) { => $message) { foreach ($input->getMessages() as $campo 1 2 $errorMessage = (strpos($mensagem, "empty") === false) ? "O campo {$campo} não pode ser vazio!" : "{$mensagem}"; throw new Tss_FormException( $errorMessage, 3, javascript:history.back(); ); } }}
  18. 18. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validatePost($filters = array(), $validators = array(), $options = null){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } foreach ($input->getMessages() as $field => $message) { $messageKey = key($message); $message = $message[$messageKey]; $errorMessage = (strpos($message, "empty") === false) ? "O campo {$field} não pode ser vazio!" : "{$mensagem}"; throw new Tss_FormException( $errorMessage, 3, javascript:history.back(); ); }}
  19. 19. Object CalisthenicsRegra 1: Somente um nível de indentação por métodopublic function validatePost($filters = array(), $validators = array(), $options = null){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data, $options); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } foreach ($input->getMessages() as $field => $message) { $messageKey = key($message); $message = $message[$messageKey]; $errorMessage = (strpos($message, "empty") === false) ? "O campo {$field} não pode ser vazio!" : "{$mensagem}"; throw new Tss_FormException( $errorMessage, 3, javascript:history.back(); ); }}
  20. 20. Object CalisthenicsRegra 2: Não use a palavra-chave “else”‣ Não use a palavra-chave “else”
  21. 21. Object CalisthenicsRegra 2: Não use a palavra-chave “else”function login() { $login = $this->input->post(email, true); $password = $this->input->post(password, true); $referencia = $this->input->post(referencia, true); if ($this->clientes_model->login($login, $password)) { redirect($referencia); } else { $this->session->set_flashdata(erro, Usuário ou senha inválidos.); $this->session->set_flashdata(referencia, $referencia); redirect(clientes); }}
  22. 22. Object CalisthenicsRegra 2: Não use a palavra-chave “else”function login() { $login = $this->input->post(email, true); $password = $this->input->post(password, true); $referencia = $this->input->post(referencia, true); if ($this->clientes_model->login($login, $password)) { redirect($referencia); } else { $this->session->set_flashdata(erro, Usuário ou senha inválidos.); $this->session->set_flashdata(referencia, $referencia); redirect(clientes); }}
  23. 23. Object CalisthenicsRegra 2: Não use a palavra-chave “else”function login() { $login = $this->input->post(email, true); $password = $this->input->post(password, true); $referencia = $this->input->post(referencia, true); if ($this->clientes_model->login($login, $password)) { redirect($referencia); } else { $this->session->set_flashdata(erro, Usuário ou senha inválidos.); $this->session->set_flashdata(referencia, $referencia); redirect(clientes); }}
  24. 24. Object CalisthenicsRegra 2: Não use a palavra-chave “else”function login() { $login = $this->input->post(email, true); $password = $this->input->post(password, true); $referencia = $this->input->post(referencia, true); if ( ! ($this->clientes_model->login($login, $password))) { $this->session->set_flashdata(erro, Usuário ou senha inválidos.); $this->session->set_flashdata(referencia, $referencia); $referencia = clientes; } redirect($referencia);}
  25. 25. Object CalisthenicsRegra 3: Encapsule todos os tipos primitivos e strings‣ Encapsule todos os tipos primitivos e strings
  26. 26. Object CalisthenicsRegra 3: Encapsule todos os tipos primitivos e strings‣ Esta regra não pode ser completamente portada ao PHP, pois a linguagem não possui boa performance com um código completamente Orientado a Objetos
  27. 27. Object CalisthenicsRegra 3: Encapsule todos os tipos primitivos e strings‣ Sugestivamente, se a variável de tipo primitivo possui comportamento, ela deve ser encapsulada
  28. 28. Object CalisthenicsRegra 3: Encapsule todos os tipos primitivos e stringsclass UIComponent{ // ... public function repaint($animate = true) { // ... }}// ...$component->repaint(false);
  29. 29. Object CalisthenicsRegra 3: Encapsule todos os tipos primitivos e stringsclass UIComponent{ // ... public function repaint($animate = true) { // ... }}// ...$component->repaint(false);
  30. 30. Object CalisthenicsRegra 3: Encapsule todos os tipos primitivos e stringsclass UIComponent{ // ... public function repaint(Animate $animate = null) { // ... }}class Animate{ public $animate = true; public function __construct($animate) { $this->animate = $animate; }}// ...$component->repaint(new Animate(false));
  31. 31. Object CalisthenicsRegra 4: Somente um ponto por linha‣ Somente um ponto (“arrow” para PHP) por linha
  32. 32. Object Calisthenics‣ Não aplicável ao PHP...
  33. 33. Object CalisthenicsRegra 4: Somente um ponto por linha‣ ...mas múltiplas chamadas aninhadas... ‣ tendem a expor um problema de encapsulamento ‣ dificultam o debug ou tratamento de exceção ‣ não simbolizam uma ação atômica
  34. 34. Object CalisthenicsRegra 4: Somente um ponto por linha‣ Podemos adaptar à linguagem, contemplando...
  35. 35. Object CalisthenicsRegra 4: Somente um ponto por linha‣ Um chain de objetos diferentes, desde que a execução só inclua getters e setters $user->getLocationPoint()->getCountry()->getName();
  36. 36. Object CalisthenicsRegra 4: Somente um ponto por linha‣ Um chain do próprio objeto através de uma interface fluente $filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
  37. 37. Object CalisthenicsRegra 5: Não abrevie‣ Não abrevie
  38. 38. Object CalisthenicsRegra 5: Não abrevie
  39. 39. Object CalisthenicsRegra 5: Não abrevie‣ Pense... por que não quer abreviar?
  40. 40. Object CalisthenicsRegra 5: Não abrevie‣ Pense... por que não quer abreviar? ‣ Escrever o mesmo nome repetidamente?
  41. 41. Object CalisthenicsRegra 5: Não abrevie‣ Pense... por que não quer abreviar? ‣ Escrever o mesmo nome repetidamente? ‣ Então seu método é reutilizado muitas vezes, sinalizando duplicidade de código.
  42. 42. Object CalisthenicsRegra 5: Não abrevie‣ Pense... por que não quer abreviar? ‣ Escrever o mesmo nome repetidamente? ‣ Então seu método é reutilizado muitas vezes, sinalizando duplicidade de código. ‣ Nome do método muito longo?
  43. 43. Object CalisthenicsRegra 5: Não abrevie‣ Pense... por que não quer abreviar? ‣ Escrever o mesmo nome repetidamente? ‣ Então seu método é reutilizado muitas vezes, sinalizando duplicidade de código. ‣ Nome do método muito longo? ‣ Sinal de uma classe com múltiplas responsabilidades ou a falta de uma classe auxiliar
  44. 44. Object CalisthenicsRegra 5: Não abrevie‣ Pense... por que não quer abreviar? ‣ Escrever o mesmo nome repetidamente? ‣ Então seu método é reutilizado muitas vezes, sinalizando duplicidade de código. ‣ Nome do método muito longo? ‣ Sinal de uma classe com múltiplas responsabilidades ou a falta de uma classe auxiliar
  45. 45. Object CalisthenicsRegra 6: Mantenha suas entidades pequenas‣ Mantenha suas entidades pequenas
  46. 46. Object CalisthenicsRegra 6: Mantenha suas entidades pequenas‣ Regra original: 50 linhas por classe
  47. 47. Object CalisthenicsRegra 6: Mantenha suas entidades pequenas‣ Adaptado ao PHP: 100 linhas por classe e não mais de 15 classes por pacote.‣ A mudança se deve ao fato que não há regra quando à documentação, que pode ocupar até 50% das linhas.
  48. 48. Object CalisthenicsRegra 7: Não crie classes com mais de duas variáveis de instância‣ Não crie classes com mais de duas variáveis de instância
  49. 49. Object CalisthenicsRegra 7: Não crie classes com mais de duas variáveis de instância‣ Objetivo: ‣ Baixa coesão ‣ Melhor encapsulamento
  50. 50. Object CalisthenicsRegra 7: Não crie classes com mais de duas variáveis de instância‣ A regra original aponta 2 variáveis de instância‣ Para o PHP, a sugestão são 5 variáveis de instância
  51. 51. Object CalisthenicsRegra 8: Use coleções de primeiro nível‣ Use coleções de primeiro nível
  52. 52. Object CalisthenicsRegra 8: Use coleções de primeiro nível‣ A regra é bem simples: Qualquer classe que contenha uma coleção (array para o PHP), não deve conter outras propriedades
  53. 53. Object CalisthenicsRegra 8: Use coleções de primeiro nível‣ Objetivo: ‣ Comportamentos específicos tem um local adequado ‣ Filtragem, combinação, mapear, ...
  54. 54. Object CalisthenicsRegra 8: Use coleções de primeiro nível‣ DoctrineCommonCollectionsArrayCollection ‣ Countable ‣ IteratorAggregate (herda Traversable) ‣ ArrayAccess
  55. 55. Object CalisthenicsRegra 9: Não crie métodos getter/setter para propriedades‣ Não crie métodos getter/setter para propriedades
  56. 56. Object CalisthenicsRegra 9: Não crie métodos getter/setter para propriedades‣ Não aplicável ao PHP devido à natureza da linguagem
  57. 57. Object CalisthenicsRegra 9: Não crie métodos getter/setter para propriedades/** * THIS CLASS WAS GENERATED BY THE DOCTRINE ORM. DO NOT EDIT THIS FILE. */class ApplicationCoreDomainUserModelUserProxy extends ApplicationCoreDomainUserModelUser implements DoctrineORMProxyProxy{ // ... public function getId() { $this->__load(); return parent::getId(); } public function setId($id) { $this->__load(); return parent::setId($id); } // ...}
  58. 58. Object Calisthenics“Regra 10”: Documente seu código!‣ Documente seu código!!!!!!!!!!!!!!!!!!!!!!
  59. 59. Object CalisthenicsThat’s all folks!‣ Perguntas? @guilhermeblanco http://github.com/guilhermeblanco

×