Blog and Site, BETA!
Random header image... Refresh for more!

Crie namespaces melhores em PHP

Um artigo recente de Nathan A. Good no IBM Developer Works dá algumas dicas sobre nomenclatura de namespaces, agora que eles estão pra chegar ao mundo PHP. Pra quem já programa em outra linguagem que possua namespaces  é tudo bastante natural. Pra quem só trabalhou com PHP até hoje, acho que vale a pena dar uma lida.

Fundamentos

Por que usar namespaces? Os dois objetivos principais são evitar colisões e ajudar na organização do código. Duas classes de mesmo nome podem possuir comportamentos completamente diferentes. As representações de um automóvel para uma fabricante de carros e para uma empresa de seguros são diferentes. Sem namespaces, era comum adicionar o contexto ao nome da classe: Ford_Automovel e ItauSeguros_Automovel, por exemplo (tosco, mas dá pra pegar a idéia, né?).

E agora, como é?

Para acessar uma classe Foo contida no namespace IBM, por exemplo, deve-se fazer:

<?php
$foo = new \IBM\Foo();
?>

Como pode ser percebido, o identificador de namespaces é a backslash “\“.

Notas: namespaces não correspondem a pastas no sistema de arquivos, como Java, e também podem conter funções e constantes, além de classes.

E para definir a classe acima no seu respectivo namespace?

<?php
namespace IBM;

class Foo {
...
}
?>

E como eu escolho os nomes para os meus namespaces? Em Java a convenção é utilizar o seu domínio (ou da sua empresa) ao contrário: br.eti.josericardo, por exemplo. Eu, pessoalmente, acho legal essa convenção e não vejo problema em segui-la também no PHP.

Mas como não foi estabelecida nenhuma convenção oficial neste sentido. As sugestões do Nathan são:

  1. No nível mais alto usar o nome do projeto (eg. Greeter) ou algo sobre o domínio (contexto mesmo): IBM\Greeter e IBM\MyApp\Account, respectivamente.
  2. Nos níveis mais baixos usar o nome do projeto ou da aplicação. Ele diz que tenta manter a quantidade de subnamespaces entre 5 e 9, pra facilitar a memorização.
  3. Em relação ao reuso, tomar cuidado para não criar namespaces muito especializados. Para coisas que serão reaproveitadas em outros projetos, KISS: use namespaces como Lib, Common e coisas do gênero.
  4. Utilize UpperCase camel para os namespaces: MyProduct, FooBar, etc.

Para declarar subnamespaces, faça:

namespace IBM\Greeter;

namespace IBM\MyApp\Account;

e assim por diante.

Hey! PHP tem alias também!

Pelo pouco visto acima, já deve ter gente pensando “putz, vou ter que digitar esse mundaréu de coisas só pra acessar um método ou uma classe?”.
A resposta é não! Como? Importe o namespace (use) e, opcionalmente, defina um alias para o namespace ou classe (não funciona para funções ou constantes), exemplos:

use MyCompany\Common\Validation; // acessa-se como Validation
use MyCompany\Common\Validation as Validators; // acessa-se como Validators
use MyCompany\Common\NomeDeClasseBastanteLongo as NomeCurto;

É importante notar que a definição de “imports” (use) e de aliases casam com nomes que não sejam qualificados, ou seja, que não tenham o namespace definido junto com o nome. No exemplo acima, se usarmos NomeCurto, estaremos acessando MyCompany\Common\NomeDeClasseBastanteLongo, mas se usarmos \MyCompany\Lib\NomeCurto, “NomeCurto” não será substituído por NomeDeClasseBastanteLongo e, muito menos, por MyCompany\Common\NomeDeClasseBastanteLongo. Understood?

Por fim, é possível também definir mais que um namespace em um mesmo arquivo. A recomendação é que isto não seja feito, mas, caso você queira muito, faça (note as chaves):

namespace MyProject {
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
}

namespace AnotherProject {
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
}

namespace { // código global
    session_start();
    $a = MyProject\connect();
}

Acabei saindo do escopo do post, mas eu comecei a tirar umas dúvidas enquanto lia o artigo do Nathan e achei que seria legal compartilhar com a diminuta “audiência” deste blog :)
Fontes:

http://www.ibm.com/developerworks/opensource/library/os-php-namespaces

http://br.php.net/manual/en/language.namespaces.php

June 26, 2009   2 Comments