Criar Sete Bons Hábitos Orientados a Objetos em PHP

Tornar seus aplicativos PHP melhores com orientação a objetos

Com recursos de linguagem orientados a objetos (OO) de PHP, se ainda não estiver criando seus aplicativos com princípios OO em mente, estes sete hábitos ajudarão a iniciar a transição entre programação processual e programação OO.

Nathan A. Good, Senior Information Engineer, Freelance Developer

Nathan A. Good mora na área Twin Cities em Minnesota. Profissionalmente, ele realiza desenvolvimento de software, arquitetura de software e administração de sistemas. Quando ele não está desenvolvendo software, ele gosta de montar PCs e servidores, ler sobre e trabalhar com novas tecnologias e tentar convencer seus amigos de começarem a usar software livre. Ele escreveu e coescreveu muitos livros e artigos, incluindo Professional Red Hat Enterprise Linux 3, Regular Expression Recipes: A Problem-Solution Approach, Regular Expression Recipes for Windows Developers: A Problem-Solution Approach, PHP 5 Recipes: A Problem-Solution Approach e Foundations of PEAR: Rapid PHP Development.



28/Out/2008

Nos primórdios da programação PHP, o código PHP limitava-se a ser de natureza processual. Código processual é caracterizado pelo uso de procedimentos para os blocos de construção do aplicativo. Os procedimentos oferecem um determinado nível de reutilização permitindo que os procedimentos sejam chamados por outros procedimentos.

No entanto, sem construções de linguagem orientadas a objetos, um programador ainda pode introduzir características OO no código PHP. É um pouco mais difícil e pode tornar o código mais difícil de ler, pois está combinando paradigmas (linguagem processual com design pseudo-OO). Construções OO em código PHP — como a capacidade de definir e usar classe, a capacidade de construir relacionamentos entre classes que usam herança e a capacidade de definir interfaces — facilitam muito mais a construção de código que segue boas práticas OO.

Apesar de designs puramente processuais sem muita modularidade serem executados muito bem, as vantagens de design OO aparecem na manutenção. Como um aplicativo típico gastará grande parte de seu tempo de vida em manutenção, a manutenção de código é um grande custo ao longo do tempo de vida de um aplicativo. Também pode ser facilmente esquecida durante o desenvolvimento. Se estiver correndo para desenvolver e implementar seu aplicativo, a capacidade de manutenção a longo prazo pode receber menor atenção do que colocar algo para funcionar.

Modularidade— uma das características chave de bom design OO — ajuda com essa manutenção. A modularidade ajuda a encapsular as mudanças, o que facilitará a extensão e modificação do aplicativo ao longo do tempo.

Apesar de haver mais de sete hábitos para construir o software OO em geral, estes sete hábitos é o que você precisa para fazer com que seu código se ajuste aos critérios básicos de design OO. Eles fornecem uma base firme na qual é possível incluir mais hábitos OO e construir software de fácil manutenção e extensão. Esses hábitos têm como alvo algumas características chave de modularidade. Para obter informações adicionais sobre os benefícios de design OO que são independentes de linguagem, consulte Recursos.

Os sete bons hábitos OO de PHP são:

  1. Seja modesto.
  2. Seja um bom vizinho.
  3. Evite olhar para a Medusa.
  4. Abrace o elo mais fraco.
  5. Você é borracha; eu sou cola.
  6. Mantenha na família.
  7. Pense em padrões.

Seja Modesto

Ser modesto é evitar expor-se em suas implementações de classes e funções. Ocultar suas informações é um hábito fundamental. Você terá dificuldades para criar qualquer um dos outros hábitos até que você tenha desenvolvido o hábito de ocultar os detalhes de suas implementações. A ocultação de informações também é conhecida como encapsulação.

Há muitas razões porque expor campos públicos diretamente é um mau hábito, a mais importante delas sendo que o deixa sem opção caso alguma coisa seja alterada em sua implementação. Você usa conceitos OO para isolar mudanças e a encapsulação tem uma função integral em assegurar que quaisquer mudanças feitas não sejam de natureza viral. Mudanças virais são aquelas que começam pequenas — como alterar uma array que contém três elementos para uma que contém somente dois. De repente, você se vê alterando mais e mais de seu código para acomodar uma mudança que deveria ter sido trivial.

Uma maneira simples de começar a ocultar suas informações é manter os campos privados e expô-los com acessadores públicos, que são como janelas em sua casa. Em vez de ter uma parede inteira aberta para fora, você tem somente uma ou duas janelas. (Falo mais sobre acessadores em "Bom Hábito: Usar Acessadores Públicos.")

Além de permitir que sua implementação nos bastidores seja alterada, o uso de acessadores públicos em vez de a exposição direta dos campos permite estender sua implementação base substituindo a implementação de um acessador para fazer algo ligeiramente diferente do comportamento do pai. Também permite construir uma implementação abstrata que adia a implementação real para classes que substituem a base.

Mau Hábito: Expor Campos Públicos

No exemplo de código inválido na Lista 1, os campos do objeto Person estão expostos diretamente como campos públicos em vez de com acessadores. Apesar de esse comportamento ser tentador, principalmente para objetos de dados leves, ele o limita.

Lista 1. Mau Hábito de Expor Campos Públicos
<?php class Person {
    public $prefix;
    public $givenName;
    public $familyName;
    public $suffix; }
$person = new Person(); $person->prefix = "Mr."; $person->givenName = "John";
echo($person->prefix); echo($person->givenName);
?>

Se alguma coisa for alterada no objeto, qualquer código que o usar precisa ser alterado também. Por exemplo, se o nome, sobrenome e outros nomes da pessoa devessem estar encapsulados em um objeto PersonName , seria necessário modificar todo o seu código para acomodar a mudança.

Bom Hábito: Usar Acessadores Públicos

Ao usar bons hábitos OO (consulte Lista 2), o mesmo objeto agora tem campos privados em vez de campos públicos e os campos privados são expostos cuidadosamente para o mundo externo por métodos públicos get e set , chamados acessadores. Esses acessadores agora fornecem uma maneira pública de obter informações de sua classe PHP de forma que se alguma coisa for alterada em sua implementação, a probabilidade de ser necessário alterar todo o código que usa sua classe é reduzida.

Lista 2. Bom Hábito de Usar Acessadores Públicos
<?php class Person {
    private $prefix;
    private $givenName;
    private $familyName;
    private $suffix;

    public function setPrefix($prefix)
    {
        $this->prefix = $prefix;
    }

    public function getPrefix()
    {
        return $this->prefix;
    }

    public function setGivenName($gn)
    {
        $this->givenName = $gn;
    }

    public function getGivenName()
    {
        return $this->givenName;
    }

    public function setFamilyName($fn)
    {
        $this->familyName = $fn;
    }

    public function getFamilyName()
    {
        return $this->familyName;
    }

    public function setSuffix($suffix)
    {
        $this->suffix = $suffix;
    }

    public function getSuffix()
    {
        return $suffix;
    }
 }
$person = new Person(); $person->setPrefix("Mr."); $person->setGivenName("John");
echo($person->getPrefix()); echo($person->getGivenName());
?>

A primeira vista, isso pode parecer muito mais trabalho e, na verdade, pode ser muito mais trabalho inicialmente. No entanto, geralmente, usar bons hábitos OO vale a pena a longo prazo, já que as mudanças futuras são altamente solidificadas.

Na versão do código mostrada na Lista 3, alterei a implementação interna para usar uma array associativa para as partes do nome. O ideal seria ter mais manipulação de erros e ser mais cuidadoso na verificação de se o elemento existe, mas a finalidade deste exemplo é mostrar como o código que usa a minha classe não precisa ser alterado — felizmente não está ciente das mudanças da minha classe. Lembre-se de que a razão para adotar hábitos OO é encapsular cuidadosamente a mudança de forma que seu código seja mais extensível e fácil de manter.

Lista 3. Outra Mudança nesse Bom Hábito com uma Implementação Interna Diferente
<?php
class Person
{
    private $personName = array();
    
    public function setPrefix($prefix)
    {
        $this->personName['prefix'] = $prefix;
    }
    
    public function getPrefix()
    {
        return $this->personName['prefix'];
    }
    
    public function setGivenName($gn)
    {
        $this->personName['givenName'] = $gn;
    }
    
    public function getGivenName()
    {
        return $this->personName['givenName'];
    }

    /* etc... */
}

/*
 * Even though the internal implementation changed, the code here stays exactly
 * the same. The change has been encapsulated only to the Person class.
 */
$person = new Person();
$person->setPrefix("Mr.");
$person->setGivenName("John");

echo($person->getPrefix());
echo($person->getGivenName());

?>

Seja um Bom Vizinho

Ao construir uma classe, ela deve tratar de seus próprios erros conforme necessário. Se a classe não souber como tratar dos erros, ela deve empacotá-los em um formato que seu responsável pela chamada entenda. Além disso, evite retornar objetos nulos ou em estado inválido. Muitas vezes, você pode fazer isso simplesmente verificando argumentos e emitindo exceções específicas que indicam porque os argumentos fornecidos são inválidos. Com a criação desse hábito, é possível economizar muito tempo para você — e para as pessoas que fazem a manutenção de seu código ou usam seus objetos— .

Mau Hábito: Não Tratar de Erros

Considere o exemplo mostrado na Lista 4, que aceita alguns argumentos e retorna um objeto Person com alguns dos valores preenchidos. No entanto, no método parsePersonName() , não há nenhuma validação para ver se a variável $val fornecida é nula, uma string de comprimento zero ou, possivelmente, uma string em um formato não analisável. O método parsePersonName() não retorna um objeto Person , mas retorna null. Os administradores ou programadores que usam esse método podem ficar confusos e — no mínimo — chegarem a um ponto onde precisam começar a configurar pontos de interrupção e depurar o script PHP.

Lista 4. Mau Hábito de Não Emitir nem Tratar Erros
class PersonUtils {
    public static function parsePersonName($format, $val)
    {
        if (strpos(",", $val) > 0) {
            $person = new Person();
            $parts = split(",", $val); // Assumir que o valor é o último, primeiro
            $person->setGivenName($parts[1]);
            $person->setFamilyName($parts[0]);
        }
        return $person;
    } }

O método parsePersonName() na Lista 4 poderia ser modificado para inicializar o objeto Person fora da condição if , assegurando que você sempre obtenha um objeto Person válido. No entanto, você obtém Person sem propriedades configuradas, o que não o deixa em posição muito melhor.

Bom Hábito: Cada Módulo Trata de seus Próprios Erros

Em vez de deixar os responsáveis pelas chamadas adivinhando, seja proativo em relação à validação de argumentos. Se uma variável não configurada não puder produzir um resultado válido, verifique a variável e emita uma InvalidArgumentException. Se a string não puder estar vazia ou precisar estar em um formato específico, verifique o formato e emita uma exceção. A Lista 5 demonstra como criar suas próprias exceções, assim como algumas novas condições no método parsePerson() , que demonstram algumas validações rudimentares.

Lista 5. Bom Hábito e Emissão de Erros
<?php class InvalidPersonNameFormatException extends LogicException {}
class PersonUtils {
    public static function parsePersonName($format, $val)
    {
        if (! $format) {
            throw new InvalidPersonNameFormatException("Invalid PersonName format.");
        }

        if ((! isset($val)) || strlen($val) == 0) {
            throw new InvalidArgumentException("Must supply a non-null value to parse.");
        }


    }
}
?>

O ponto principal é que você quer que as pessoas sejam capazes de usar seu curso sem que precisem conhecer os funcionamentos internos dele. Se usarem-no incorretamente ou de maneira indevida, não precisarão adivinhar o por quê de não ter funcionado. Como um bom vizinho, você entende que as pessoas que estão reutilizando sua classe não são videntes e, portanto, você elimina a adivinhação.


Evite Olhar para a Medusa

Quando estava começando a aprender sobre conceitos OO, tinha minhas dúvidas de se interfaces eram realmente úteis. Um colega fez a analogia de que não usar interfaces é como olhar para a cabeça de Medusa. Na mitologia grega, Medusa era um personagem feminino com cobras no lugar do cabelo. Qualquer pessoa que olhasse diretamente para ela seria transformada em pedra. Perseus, que matou Medusa, pôde confrontá-la olhando para o reflexo da mesma em seu escudo, evitando assim virar pedra.

As interfaces são seu espelho para lidar com Medusa. Ao usar uma implementação concreta específica, seu código deve ser alterado se o código de sua implementação for alterado. Usar implementações diretamente limita muitas de suas opções, já que você, essencialmente, transformou suas classes em pedra.

Mau Hábito: Não Usar Interfaces

A Lista 6 mostra um exemplo que carrega o objeto Person de um banco de dados. Pega o nome da pessoa e retorna o objeto Person no banco de dados correspondente.

Lista 6. Mau Hábito de Não Usar Interfaces
<?php class DBPersonProvider {
    public function getPerson($givenName, $familyName)
    {
        /* ir para o banco de dados, obter a pessoa... */
        $person = new Person();
        $person->setPrefix("Mr.");
        $person->setGivenName("John");
        return $person;
    } }
/* Preciso obter dados da pessoa... */ $provider = new DBPersonProvider(); $person =
$provider->getPerson("John", "Doe");
echo($person->getPrefix()); echo($person->getGivenName());
?>

O código para carregar Person do banco de dados está bem até que algo seja alterado no ambiente. Por exemplo, carregar Person do banco de dados pode não ter problemas para a primeira versão do aplicativo, mas para a segunda versão, pode ser necessário incluir a capacidade de carregar uma pessoa de um serviço da Web. Na essência, a classe virou pedra porque está usando a classe de implementação diretamente e agora é difícil de alterar.

Bom Hábito: Usar Interfaces

A Lista 7 mostra um exemplo de código que não é alterada à medida que novas maneiras de carregar usuários são disponibilizadas e implementadas. O exemplo mostra uma interface chamada PersonProvider, que declara um único método. Se algum código usar PersonProvider, o código evita usar as classes de implementação diretamente. Em vez disso, usa PersonProvider como se fosse um objeto real.

Lista 7. Bom Hábito de Usar Interfaces
<?php
interface PersonProvider
{
    public function getPerson($givenName, $familyName);
}

class DBPersonProvider implements PersonProvider 
{
    public function getPerson($givenName, $familyName)
    {
        /* pretend to go to the database, get the person... */
        $person = new Person();
        $person->setPrefix("Mr.");
        $person->setGivenName("John");
        return $person;
    }
}

class PersonProviderFactory
{
    public static function createProvider($type)
    {
        if ($type == 'database')
        {
            return new DBPersonProvider();
        } else {
            return new NullProvider();
        }
    }
}

$config = 'database';
/* I need to get person data... */
$provider = PersonProviderFactory::createProvider($config);
$person = $provider->getPerson("John", "Doe");

echo($person->getPrefix());
echo($person->getGivenName());
?>

Ao usar interfaces, tente evitar fazer referência direta às classes de implementação. Em vez disso, use algo externo a seu objeto para fornecer a implementação correta. Se sua classe carregar a implementação baseada em alguma lógica, ainda precisa das definições de todas as classes de implementação e isso não o leva a lugar nenhum.

Você pode usar um padrão de Fábrica para criar uma instância de uma classe de implementação que implementa sua interface. Um método factory , por convenção, começa com create e retorna a interface. Pode aceitar os argumentos necessários para seu factory para descobrir qual classe de implementação é a correta a ser retornada.

Na Lista 7, o método createProvider() simplesmente usa um $type. Se $type for configurado para database, o factory retorna uma instância de DBPersonProvider. Qualquer nova implementação para carregar pessoas de um armazenamento não requer nenhuma alteração na classe que usa o factory e a interface. O DBPersonProvider implementa a interface PersonProvider e possui a implementação real do método getPerson() na mesma.


O acoplamento fraco de seus módulos é uma boa coisa; é uma das propriedades que permite encapsular a mudança. Dois dos outros hábitos — "Seja modesto" e "Evite olhar para a Medusa" — ajudam você a trabalhar para a construção de módulos acoplados de forma fraca. Para acoplar suas classes de forma fraca, desenvolva a característica final criando o hábito de reduzir as dependências de suas classes.

Mau Hábito: Acoplamento Forte

Na Lista 8, a redução das dependências não é necessariamente a redução das dependências para o cliente que está usando um objeto. Em vez disso, o exemplo demonstra a redução de suas dependências da classe correta e a minimização das mesmas em outros locais.

Lista 8. Mau Hábito de Acoplamento Forte de Address
<?php

require_once "./AddressFormatters.php";

class Address
{
    private $addressLine1;
    private $addressLine2;
    private $city;
    private $state; // or province...
    private $postalCode;
    private $country;

    public function setAddressLine1($line1)
    {
        $this->addressLine1 = $line1;
    }

		/* accessors, etc... */

    public function getCountry()
    {
        return $this->country;
    }

    public function format($type)
    {
        if ($type == "inline") {
            $formatter = new InlineAddressFormatter();
        } else if ($type == "multiline") {
            $formatter = new MultilineAddressFormatter();
        } else {
            $formatter = new NullAddressFormatter();
        }
        return $formatter->format($this->getAddressLine1(), 
            $this->getAddressLine2(), 
            $this->getCity(), $this->getState(), $this->getPostalCode(), 
            $this->getCountry());
    }
}

$addr = new Address();
$addr->setAddressLine1("123 Any St.");
$addr->setAddressLine2("Ste 200");
$addr->setCity("Anytown");
$addr->setState("AY");
$addr->setPostalCode("55555-0000");
$addr->setCountry("US");

echo($addr->format("multiline"));
echo("\n");

echo($addr->format("inline"));
echo("\n");

?>

O código que chama o método format() no objeto Address pode parecer ótimo — tudo o que faz é usar a classe Address , chamar format() e está pronto. Em contraste, a classe Address não tem tanta sorte. Precisa saber sobre os diversos formatadores usados para formatá-la corretamente, o que pode não tornar o objeto Address muito reutilizável para outra pessoa, principalmente se essa pessoa não estiver interessada em usar as classes do formatador no método format() . Apesar de o código que está usando Address não tem muitas dependências, a classe Address tem muitas quando, provavelmente, deveria ser um objeto de dados simples.

A classe Address tem um acoplamento forte às classes de implementação que sabem como formatar o objeto Address .

Bom Hábito: Acoplamento Fraco entre Objetos

Ao construir bons designs OO, é necessário considerar um conceito chamado Separation of Concerns (SoC). SoC significa que você tenta separar objetos pelo o que eles deveriam realmente estar relacionados, reduzindo, assim, o acoplamento. Na classe Address original, precisava ser em relação a como se formatar. Esse, provavelmente, não é um bom design. Em vez disso, uma classe Address deve considerar as partes de Address, enquanto que algum tipo de formatador deve considerar como formatar o endereço corretamente.

Na Lista 9, o código que formatou o endereço é movido para interfaces, classes de implementação e um factory — criando o hábito de "usar interfaces". Agora, a classe AddressFormatUtils é responsável por criar um formatador e formatar um Address. Qualquer outro objeto agora pode usar um Address sem precisar se preocupar sobre também requerer as definições dos formatadores.

Lista 9. Bom Hábito de Acoplamento Fraco entre Objetos
<?php

interface AddressFormatter
{
    public function format($addressLine1, $addressLine2, $city, $state, 
        $postalCode, $country);
}

class MultiLineAddressFormatter implements AddressFormatter 
{
    public function format($addressLine1, $addressLine2, $city, $state, 
        $postalCode, $country)
    {
        return sprintf("%s\n%s\n%s, %s %s\n%s", 
            $addressLine1, $addressLine2, $city, $state, $postalCode, $country);
    }
}

class InlineAddressFormatter implements AddressFormatter 
{
    public function format($addressLine1, $addressLine2, $city, $state, 
        $postalCode, $country)
    {
        return sprintf("%s %s, %s, %s %s %s", 
            $addressLine1, $addressLine2, $city, $state, $postalCode, $country);
    }
}

class AddressFormatUtils 
{
    public static function formatAddress($type, $address)
    {
        $formatter = AddressFormatUtils::createAddressFormatter($type);
        
        return $formatter->format($address->getAddressLine1(), 
            $address->getAddressLine2(), 
            $address->getCity(), $address->getState(), 
            $address->getPostalCode(), 
            $address->getCountry());
    }
    
    private static function createAddressFormatter($type)
    {
        if ($type == "inline") {
            $formatter = new InlineAddressFormatter();
        } else if ($type == "multiline") {
            $formatter = new MultilineAddressFormatter();
        } else {
            $formatter = new NullAddressFormatter();
        }
        return $formatter;
    }
}

$addr = new Address();
$addr->setAddressLine1("123 Any St.");
$addr->setAddressLine2("Ste 200");
$addr->setCity("Anytown");
$addr->setState("AY");
$addr->setPostalCode("55555-0000");
$addr->setCountry("US");

echo(AddressFormatUtils::formatAddress("multiline", $addr));
echo("\n");

echo(AddressFormatUtils::formatAddress("inline", $addr));
echo("\n");
?>

A desvantagem, é claro, é que sempre que padrões forem usados, isso frequentemente significa que a quantidade de artefatos (classes, arquivos) aumenta. No entanto, esse aumento é compensado pela redução de manutenção em cada classe e pode ser reduzido ainda mais quando a capacidade de reutilização apropriada é obtida.


Você É Borracha; Eu Sou Cola

Designs OO altamente coesivos são focados e organizados em módulos relacionados. Aprender sobre "interesses" é importante na determinação de como organizar funções e classes para serem fortemente coesivo.

Mau Hábito: Baixa Coesão

Quando um design tem baixa coesão, ele possui classes e métodos que não estão bem agrupados. O termo código espaguete é frequentemente usado para descrever classes e métodos agrupados com baixa coesão. A Lista 10 fornece um exemplo de código espaguete. A classe Utils relativamente genérica usa muitos objetos diferentes e possui muitas dependências. Faz um pouco de tudo, dificultando a reutilização.

Lista 10. Mau Hábito de Baixa Coesão
<?php
class Utils {
    public static function formatAddress($formatType, $address1,
        $address2, $city, $state)
    {
        return "some address string";
    }
    public static function formatPersonName($formatType, $givenName,
        $familyName)
    {
        return "some person name";
    }
    public static function parseAddress($formatType, $val)
    {
        // implementação real configuraria valores, etc...
        return new Address();
    }
    public static function parseTelephoneNumber($formatType, $val)
    {
        // implementação real configuraria valores, etc...
        return new TelephoneNumber();
    } }
?>

Bom Hábito: Abraça a Coesão Alta

Coesão alta significa que classes e métodos relacionados uns aos outros são agrupados. Se métodos e classes forem altamente coesivos, será possível separar facilmente grupos inteiros sem afetar o design. Designs com alta coesão oferecem a oportunidade para acoplamento mais baixo. A Lista 11 mostra dois dos métodos que são melhor organizados em classes. A classe AddressUtils contém métodos para lidar com as classes Address e mostra coesão alta entre os métodos relacionados a endereço. De forma semelhante, PersonUtils contém métodos que lidam especificamente com objetos Person . Essas duas novas classes com seus métodos altamente coesivos possuem baixo acoplamento, pois podem ser usadas de forma totalmente independente uma da outra.

Lista 11. Bom Hábito de Coesão Alta
<?php
class AddressUtils {
    public static function formatAddress($formatType, $address1,
        $address2, $city, $state)
    {
        return "some address string";
    }
    public static function parseAddress($formatType, $val)
    {
        // implementação real configuraria valores, etc...
        return new Address();
    } }
class PersonUtils {
    public static function formatPersonName($formatType, $givenName,
        $familyName)
    {
        return "some person name";
    }
    public static function parsePersonName($formatType, $val)
    {
        // implementação real configuraria valores, etc...
        return new PersonName();
    } }
?>

Mantenha na Família

Frequentemente, digo as pessoas das equipes de software das quais fui líder técnico ou arquiteto que o maior inimigo de linguagens OO é uma operação copiar e colar. Quando usada na falta de um design OO direto, nada causa mais devastação do que copiar código de um arquivo para o outro. Sempre que estiver tentado a copiar código de uma classe para a próxima, pare e considere como pode usar hierarquias de classes para obter uma funcionalidade semelhante ou idêntica. Você descobrirá que na maioria dos casos, com um bom design, copiar código é completamente desnecessário.

Mau Hábito: Não Usar Hierarquias de Classes

A Lista 12 mostra um exemplo simples de classes parciais. Elas começam com campos e métodos duplicados — isso não é bom a longo prazo quando o aplicativo pode precisar ser alterado. Se houver um defeito na classe Person , muito provavelmente haverá um defeito na classe Employee também, pois parece que a implementação foi copiada entre as duas.

Lista 12. Mau Hábito de Não Usar Hierarquias
<?php class Person {
    private $givenName;
    private $familyName; }
class Employee {
    private $givenName;
    private $familyName; }
?>

Herança é um hábito difícil de começar a usar, pois, frequentemente, a análise para construir modelos de herança apropriados pode levar muito tempo. Por outro lado, usar Ctrl+C e Ctrl+V para construir novas implementações leva somente segundos. Mas o tempo é geralmente compensado bem rapidamente na manutenção, onde o aplicativo realmente passará a maior parte de seu tempo.

Bom Hábito: Usar Herança

Na Lista 13, a nova classe Employee estende a classe Person . Agora herda todos os métodos comuns e não reimplementa os mesmos. Além disso, a Lista 13 mostra o uso de um método abstrato para demonstrar como a funcionalidade básica pode ser colocada em uma classe base e a funcionalidade específica pode ser detida em uma classe de implementação.

Lista 13. Bom Hábito de Usar Herança
<?php abstract class Person {
    private $givenName;
    private $familyName;

    public function setGivenName($gn)
    {
        $this->givenName = $gn;
    }

    public function getGivenName()
    {
        return $this->givenName;
    }

    public function setFamilyName($fn)
    {
        $this->familyName = $fn;
    }

    public function getFamilyName()
    {
        return $this->familyName;
    }

    public function sayHello()
    {
        echo("Hello, I am ");
        $this->introduceSelf();
    }

    abstract public function introduceSelf();
 }
class Employee extends Person {
    private $role;

    public function setRole($r)
    {
        $this->role = $r;
    }

    public function getRole()
    {
        return $this->role;
    }

    public function introduceSelf()
    {
        echo($this->getRole() . " " . $this->getGivenName() . " " . 
            $this->getFamilyName());
    } } ?>

Pense em Padrões

Os padrões de design são interações comuns de objetos e métodos que foram comprovados ao longo do tempo para resolver determinados problemas. Quando você pensa em padrões de design, você está se forçando a estar ciente de como as classes interagem umas com as outras. É uma maneira fácil de construir classes e suas interações sem precisar cometer os mesmos erros que outras pessoas no passado e se beneficiar de designs comprovados.

Mau Hábito: Considerar um Objeto por Vez

Na verdade, não há nenhum exemplo de código adequado que demonstre o pensamento em padrões (apesar de haver muitos bons exemplos mostrando implementações de padrão). No entanto, em linhas gerais, você sabe que está considerando somente um objeto por vez quando os seguintes critérios são atendidos:

  • Você não faz um diagrama de um modelo de objeto antecipadamente.
  • Você começa a codificar a implementação de métodos únicos sem que o modelo seja danificado.
  • Você não usa nomes de padrão de design ao conversar e preferiria falar sobre implementação.

Bom Hábito: Incluindo Objetos, Conjuntamente, Compostos em Padrões

Em geral, você está pensando em padrões quando você:

  • Modela classes e suas interações antecipadamente.
  • Determina o estereótipo das classes de acordo com seus padrões.
  • Usa nomes de padrões, como Factory, Singleton e Facade.
  • Efetua stub de grandes partes do modelo e, em seguida, começa a incluir implementação.

Conclusão

Criar bons hábitos OO em PHP ajuda você a construir aplicativos mais estáveis, de fácil manutenção e mais facilmente extensíveis. Lembre-se:

  • Seja modesto.
  • Seja um bom vizinho.
  • Evite olhar para a Medusa.
  • Abrace o elo mais fraco.
  • Você é borracha, eu sou cola.
  • Mantenha na família.
  • Pense em padrões.

À medida que você cria e obtém esses hábitos, provavelmente, ficará surpreso das mudanças de qualidade de seus aplicativos.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=382611
ArticleTitle=Criar Sete Bons Hábitos Orientados a Objetos em PHP
publish-date=10282008