SlideShare uma empresa Scribd logo
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

Mais conteúdo relacionado

Mais procurados

Aula 12 Relatório - Tabelas
Aula 12   Relatório - TabelasAula 12   Relatório - Tabelas
Aula 12 Relatório - Tabelas
Dalton Martins
 
Aula 02 - Introdução ao PHP - Programação Web
Aula 02  - Introdução ao PHP - Programação WebAula 02  - Introdução ao PHP - Programação Web
Aula 02 - Introdução ao PHP - Programação Web
Dalton Martins
 

Mais procurados (20)

Java script aula 05 - funções
Java script   aula 05 - funçõesJava script   aula 05 - funções
Java script aula 05 - funções
 
Php curl - Coleta de dados na web
Php curl - Coleta de dados na webPhp curl - Coleta de dados na web
Php curl - Coleta de dados na web
 
Palestra de PDO
Palestra de PDOPalestra de PDO
Palestra de PDO
 
Aula 12 Relatório - Tabelas
Aula 12   Relatório - TabelasAula 12   Relatório - Tabelas
Aula 12 Relatório - Tabelas
 
Crawling - Coleta de dados na Web com PHP
Crawling - Coleta de dados na Web com PHP Crawling - Coleta de dados na Web com PHP
Crawling - Coleta de dados na Web com PHP
 
Curso PHP: Básico JavaScript
Curso PHP: Básico JavaScriptCurso PHP: Básico JavaScript
Curso PHP: Básico JavaScript
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
 
Geolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesGeolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e Routes
 
Evento Front End SP - Organizando o Javascript
 Evento Front End SP - Organizando o Javascript Evento Front End SP - Organizando o Javascript
Evento Front End SP - Organizando o Javascript
 
jQuery Simplificando o JavaScript
jQuery Simplificando o JavaScriptjQuery Simplificando o JavaScript
jQuery Simplificando o JavaScript
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
Introdução à JQuery
Introdução à JQueryIntrodução à JQuery
Introdução à JQuery
 
Aprenda jQuery 1.3
Aprenda jQuery 1.3Aprenda jQuery 1.3
Aprenda jQuery 1.3
 
Minicurso de jQuery
Minicurso de jQueryMinicurso de jQuery
Minicurso de jQuery
 
Java script - funções
Java script - funçõesJava script - funções
Java script - funções
 
Java script aula 08 - formulários
Java script   aula 08 - formuláriosJava script   aula 08 - formulários
Java script aula 08 - formulários
 
Aula 02 - Introdução ao PHP - Programação Web
Aula 02  - Introdução ao PHP - Programação WebAula 02  - Introdução ao PHP - Programação Web
Aula 02 - Introdução ao PHP - Programação Web
 
PHP GERAL
PHP GERALPHP GERAL
PHP GERAL
 
modernizando a arquitertura de sua aplicação
modernizando a arquitertura  de sua aplicaçãomodernizando a arquitertura  de sua aplicação
modernizando a arquitertura de sua aplicação
 
Phpex2
Phpex2Phpex2
Phpex2
 

Semelhante a PHPubSP Object Calisthenics aplicado ao PHP

Criando controle de acesso com php e my sql
Criando controle de acesso com php e my sqlCriando controle de acesso com php e my sql
Criando controle de acesso com php e my sql
Paulo Damas
 
Apresentação j query6
Apresentação j query6Apresentação j query6
Apresentação j query6
douglasgrava
 
LabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - FunçõesLabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - Funções
Carlos Santos
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
Impacta Eventos
 

Semelhante a PHPubSP Object Calisthenics aplicado ao PHP (13)

Programação web ii aulas 06 e 07
Programação web ii   aulas 06 e 07Programação web ii   aulas 06 e 07
Programação web ii aulas 06 e 07
 
Criando controle de acesso com php e my sql
Criando controle de acesso com php e my sqlCriando controle de acesso com php e my sql
Criando controle de acesso com php e my sql
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Clean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHPClean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHP
 
Apresentação j query6
Apresentação j query6Apresentação j query6
Apresentação j query6
 
LabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - FunçõesLabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - Funções
 
Menu dinâmico com kendoUI
Menu dinâmico com kendoUIMenu dinâmico com kendoUI
Menu dinâmico com kendoUI
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
 
Escrevendo plugins JQuery
Escrevendo plugins JQueryEscrevendo plugins JQuery
Escrevendo plugins JQuery
 
Design OO
Design OODesign OO
Design OO
 
Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6
 
Aula 02 - Curso PHP e MySQL
Aula 02 - Curso PHP e MySQLAula 02 - Curso PHP e MySQL
Aula 02 - Curso PHP e MySQL
 
Qualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitQualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnit
 

Mais de Guilherme Blanco

Mais de Guilherme Blanco (13)

Enterprise php
Enterprise phpEnterprise php
Enterprise php
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object Calisthenics
 
PHP 7
PHP 7PHP 7
PHP 7
 
ORM dont kill your DB, developers do
ORM dont kill your DB, developers doORM dont kill your DB, developers do
ORM dont kill your DB, developers do
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
Javascript para adultos
Javascript para adultosJavascript para adultos
Javascript para adultos
 
Dependency injection
Dependency injectionDependency injection
Dependency injection
 
Doctrine2 Seminário PHP
Doctrine2 Seminário PHPDoctrine2 Seminário PHP
Doctrine2 Seminário PHP
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
 
Doctrine 2.0: A evolução da persistência em PHP
Doctrine 2.0: A evolução da persistência em PHPDoctrine 2.0: A evolução da persistência em PHP
Doctrine 2.0: A evolução da persistência em PHP
 
PHP, Daemons e Multimedia
PHP, Daemons e MultimediaPHP, Daemons e Multimedia
PHP, Daemons e Multimedia
 
Doctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPDoctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHP
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 

PHPubSP Object Calisthenics aplicado ao PHP

  • 1. Object Calisthenics Aplicado ao PHP
  • 2. Object Calisthenics O palestrante @guilhermeblanco http://github.com/guilhermeblanco
  • 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ódigo legí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ão aplicá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
  • 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 all folks! ‣ Perguntas? @guilhermeblanco http://github.com/guilhermeblanco

Notas do Editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n