Object Calisthenics Aplicado ao PHP
Object Calisthenics O palestrante @guilhermeblanco http://github.com/guilhermeblanco
Object Calisthenics Agenda ‣ Motivação ‣ Regras ‣ Aplicação
Object Calisthenics O que é Object Calisthenics? ‣ Object Calisthenics
Object Calisthenics O que é Object Calisthenics? ‣ Object Calisthenics Termo derivado do grego “exercício”, sob o contexto de ginástica.
Object Calisthenics O 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
Object Calisthenics Motivação ‣ Código legível ‣ Compreensível ‣ Testável ‣ Manutenível
Object Calisthenics Regras ‣ Nove (9) regras “bem” simples...
Object Calisthenics Regra 1: Somente um nível de indentação por método ‣ Somente um nível de indentação por método
Object Calisthenics Regra 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”.
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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; }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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; }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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; }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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();' ); } } } }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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();' ); } } } }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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();' ); } } }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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();' ); } } }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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();' ); } }
Object Calisthenics Regra 1: Somente um nível de indentação por método public 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();' ); } }
Object Calisthenics Regra 2: Não use a palavra-chave “else” ‣ Não use a palavra-chave “else”
Object Calisthenics Regra 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'); } }
Object Calisthenics Regra 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'); } }
Object Calisthenics Regra 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'); } }
Object Calisthenics Regra 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); }
Object Calisthenics Regra 3: Encapsule todos os tipos primitivos e strings ‣ Encapsule todos os tipos primitivos e strings
Object Calisthenics Regra 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
Object Calisthenics Regra 3: Encapsule todos os tipos primitivos e strings ‣ Sugestivamente, se a variável de tipo primitivo possui comportamento, ela deve ser encapsulada
Object Calisthenics Regra 3: Encapsule todos os tipos primitivos e strings class UIComponent { // ... public function repaint($animate = true) { // ... } } // ... $component->repaint(false);
Object Calisthenics Regra 3: Encapsule todos os tipos primitivos e strings class UIComponent { // ... public function repaint($animate = true) { // ... } } // ... $component->repaint(false);
Object Calisthenics Regra 3: Encapsule todos os tipos primitivos e strings class UIComponent { // ... public function repaint(Animate $animate = null) { // ... } } class Animate { public $animate = true; public function __construct($animate) { $this->animate = $animate; } } // ... $component->repaint(new Animate(false));
Object Calisthenics Regra 4: Somente um ponto por linha ‣ Somente um ponto (“arrow” para PHP) por linha
Object Calisthenics ‣ Não aplicável ao PHP...
Object Calisthenics Regra 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
Object Calisthenics Regra 4: Somente um ponto por linha ‣ Podemos adaptar à linguagem, contemplando...
Object Calisthenics Regra 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();
Object Calisthenics Regra 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());
Object Calisthenics Regra 5: Não abrevie ‣ Não abrevie
Object Calisthenics Regra 5: Não abrevie
Object Calisthenics Regra 5: Não abrevie ‣ Pense... por que não quer abreviar?
Object Calisthenics Regra 5: Não abrevie ‣ Pense... por que não quer abreviar? ‣ Escrever o mesmo nome repetidamente?
Object Calisthenics Regra 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.
Object Calisthenics Regra 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?
Object Calisthenics Regra 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
Object Calisthenics Regra 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
Object Calisthenics Regra 6: Mantenha suas entidades pequenas ‣ Mantenha suas entidades pequenas
Object Calisthenics Regra 6: Mantenha suas entidades pequenas ‣ Regra original: 50 linhas por classe
Object Calisthenics Regra 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.
Object Calisthenics Regra 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
Object Calisthenics Regra 7: Não crie classes com mais de duas variáveis de instância ‣ Objetivo: ‣ Baixa coesão ‣ Melhor encapsulamento
Object Calisthenics Regra 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
Object Calisthenics Regra 8: Use coleções de primeiro nível ‣ Use coleções de primeiro nível
Object Calisthenics Regra 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
Object Calisthenics Regra 8: Use coleções de primeiro nível ‣ Objetivo: ‣ Comportamentos específicos tem um local adequado ‣ Filtragem, combinação, mapear, ...
Object Calisthenics Regra 8: Use coleções de primeiro nível ‣ DoctrineCommonCollectionsArrayCollection ‣ Countable ‣ IteratorAggregate (herda Traversable) ‣ ArrayAccess
Object Calisthenics Regra 9: Não crie métodos getter/setter para propriedades ‣ Não crie métodos getter/setter para propriedades
Object Calisthenics Regra 9: Não crie métodos getter/setter para propriedades ‣ Não aplicável ao PHP devido à natureza da linguagem
Object Calisthenics Regra 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); } // ... }
Object Calisthenics “Regra 10”: Documente seu código! ‣ Documente seu código!!!!!!!!!!!!!!!!!!!!!!
Object Calisthenics That’s all folks! ‣ Perguntas? @guilhermeblanco http://github.com/guilhermeblanco

PHPubSP Object Calisthenics aplicado ao PHP

  • 1.
    Object Calisthenics Aplicado ao PHP
  • 2.
    Object Calisthenics O palestrante @guilhermeblanco http://github.com/guilhermeblanco
  • 3.
  • 4.
    Object Calisthenics O queé Object Calisthenics? ‣ Object Calisthenics
  • 5.
    Object Calisthenics O queé Object Calisthenics? ‣ Object Calisthenics Termo derivado do grego “exercício”, sob o contexto de ginástica.
  • 6.
    Object Calisthenics O 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.
    Object Calisthenics Motivação ‣ Códigolegível ‣ Compreensível ‣ Testável ‣ Manutenível
  • 8.
    Object Calisthenics Regras ‣ Nove(9) regras “bem” simples...
  • 9.
    Object Calisthenics Regra 1:Somente um nível de indentação por método ‣ Somente um nível de indentação por método
  • 10.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 1:Somente um nível de indentação por método public 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.
    Object Calisthenics Regra 2:Não use a palavra-chave “else” ‣ Não use a palavra-chave “else”
  • 21.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 3:Encapsule todos os tipos primitivos e strings ‣ Encapsule todos os tipos primitivos e strings
  • 26.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 3:Encapsule todos os tipos primitivos e strings ‣ Sugestivamente, se a variável de tipo primitivo possui comportamento, ela deve ser encapsulada
  • 28.
    Object Calisthenics Regra 3:Encapsule todos os tipos primitivos e strings class UIComponent { // ... public function repaint($animate = true) { // ... } } // ... $component->repaint(false);
  • 29.
    Object Calisthenics Regra 3:Encapsule todos os tipos primitivos e strings class UIComponent { // ... public function repaint($animate = true) { // ... } } // ... $component->repaint(false);
  • 30.
    Object Calisthenics Regra 3:Encapsule todos os tipos primitivos e strings class 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.
    Object Calisthenics Regra 4:Somente um ponto por linha ‣ Somente um ponto (“arrow” para PHP) por linha
  • 32.
    Object Calisthenics ‣ Nãoaplicável ao PHP...
  • 33.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 4:Somente um ponto por linha ‣ Podemos adaptar à linguagem, contemplando...
  • 35.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 5:Não abrevie ‣ Não abrevie
  • 38.
  • 39.
    Object Calisthenics Regra 5:Não abrevie ‣ Pense... por que não quer abreviar?
  • 40.
    Object Calisthenics Regra 5:Não abrevie ‣ Pense... por que não quer abreviar? ‣ Escrever o mesmo nome repetidamente?
  • 41.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 6:Mantenha suas entidades pequenas ‣ Mantenha suas entidades pequenas
  • 46.
    Object Calisthenics Regra 6:Mantenha suas entidades pequenas ‣ Regra original: 50 linhas por classe
  • 47.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 7:Não crie classes com mais de duas variáveis de instância ‣ Objetivo: ‣ Baixa coesão ‣ Melhor encapsulamento
  • 50.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 8:Use coleções de primeiro nível ‣ Use coleções de primeiro nível
  • 52.
    Object Calisthenics Regra 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.
    Object Calisthenics Regra 8:Use coleções de primeiro nível ‣ Objetivo: ‣ Comportamentos específicos tem um local adequado ‣ Filtragem, combinação, mapear, ...
  • 54.
    Object Calisthenics Regra 8:Use coleções de primeiro nível ‣ DoctrineCommonCollectionsArrayCollection ‣ Countable ‣ IteratorAggregate (herda Traversable) ‣ ArrayAccess
  • 55.
    Object Calisthenics Regra 9:Não crie métodos getter/setter para propriedades ‣ Não crie métodos getter/setter para propriedades
  • 56.
    Object Calisthenics Regra 9:Não crie métodos getter/setter para propriedades ‣ Não aplicável ao PHP devido à natureza da linguagem
  • 57.
    Object Calisthenics Regra 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.
    Object Calisthenics “Regra 10”:Documente seu código! ‣ Documente seu código!!!!!!!!!!!!!!!!!!!!!!
  • 59.
    Object Calisthenics That’s allfolks! ‣ Perguntas? @guilhermeblanco http://github.com/guilhermeblanco