O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

PHPubSP Object Calisthenics aplicado ao PHP

8.130 visualizações

Publicada em

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

Publicada em: Tecnologia

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

×