PHP-FIG e as PSR: Parte 2

PHP-FIG e as PSR: Parte 2
No último post, conhecemos o PHP-FIG e o primeiro de 4 conjuntos de regras ativos que temos atualmente, conjuntos estes chamados PSR.

Já falamos sobre a PSR-1, que define um padrão básico de codificação, e agora vamos falar sobre a PSR-2.

Obs. se você não leu a primeira parte, recomendo fortemente que leia antes de continuar, pois as PSR se complementam, logo, para um domínio total dessas regras, é importante conhecer uma a uma.
 
A PSR-2 é considerada uma extensão da PSR-1, mas que trata apenas do estilo que devemos seguir ao escrever códigos PHP, e também é “um pouco” maior que a PSR-1. Então vamos lá:
 
A PSR-2, como todas as outras PSR, utiliza determinadas chaves para definir como certos elementos são aplicados no código, como vimos no post anterior:
 
“MUST” (DEVE);
“MUST NOT” (NÃO DEVE);
“REQUIRED” (OBRIGATÓRIO);
“SHALL” (TEM QUE);
“SHALL NOT” (NÃO TEM QUE);
“SHOULD” (DEVERIA);
“SHOULD NOT” (NÃO DEVERIA);
“RECOMMENDED” (RECOMENDADO);
“MAY” (PODE);
“OPTIONAL” (OPCIONAL).

PSR-2: Coding Style Guide

Esta seção estende e expande a PSR-1: padrão básico de codificação.
O objetivo deste guia é facilitar o entendimento quando se está lendo código de autores diferentes. Isto é feito enumerando uma série de regras sobre como formatar códigos PHP.
As regras de estilo definidas aqui vêm de pontos em comum de projetos de vários dos membros do PHP-FIG. Quando muitos autores colaboram em múltiplos projetos, fica mais fácil termos um conjunto de diretrizes para usarmos em todos esses projetos. Portanto, o real benefício deste guia não está nas regras, mas sim em compartilhar essas regras.

 Ou seja, essas regras foram definidas porque muitos dos desenvolvedores já utilizavam esses padrões antes de a PSR-2 existir, e como são padrões que atendem muito bem a qualquer projeto, nasceu a PSR-2. Vamos conferir o que a PSR-2 define:
 
Códigos PHP DEVEM seguir o padrão básico de codificação (PSR-1).
Nada demais aqui: como a PSR-2 é uma extensão da PSR-1, fica claro que para um código estar de acordo com a PSR-2, precisa, primeiro estar de acordo com a PSR-1.
Todos os arquivos PHP DEVEM utilizar o padrão Unix de terminação de linha.
Geralmente nós não precisamos nos preocupar com isso, a maioria dos IDEs e editores já vem preparados para isso, mas é sempre bom se certificar. O padrão Unix de terminação de linha é o LF.
Todos os arquivos PHP DEVEM terminar com uma única linha em branco.
Com exceção de arquivos HTML com a extensão .php, certifique-se de que todos os seus arquivos .php terminem com uma linha em branco. Basta pular um linha após a última linha do código.
A tag de fechamento (?>) DEVE ser omitida em arquivos de PHP puro.
Se o arquivo é apenas PHP, você não deve terminá-lo com “?>”, apenas deixe uma linha em branco no final.
NÃO DEVE existir um limite absoluto de caracteres em uma linha; O limite relativo de caracteres em uma linha DEVE ser de 120 caracteres; Verificadores de estilo de código automatizados DEVEM avisar caso uma linha ultrapasse 120 caracteres, mas NÃO DEVE acusar erro; Linhas NÃO DEVERIAM possuir mais de 80 caracteres; Linhas maiores que 80 caracteres DEVEM ser quebradas em múltiplas linhas de 80 caracteres ou menos.
Pode parecer um pouco complicado, mas é bem simples, na verdade: considere que as linhas devem ter no máximo 80 caracteres. Se em algum caso for necessário ultrapassar este limite, você tem até 120 caracteres. Não é recomendado ter linhas maiores que 120 caracteres, nos casos de linhas muito grandes, basta dividir em mais linhas de até 80 caracteres.
Linhas que não estão em branco NÃO DEVEM ter espaços após o conteúdo da mesma.
Simples: se você tem uma linha de código, tenha certeza de que o último caractere dessa linha não seja um espaço em branco.
Linhas em branco PODEM ser adicionadas caso você ache que vá facilitar a interpretação do código.
Geralmente linhas em branco são usadas para separar blocos de código, por exemplo: um arquivo possui 4 linhas que executam uma tarefa X e outras 8 linhas que executam a tarefa Y, você pode separar esses blocos por algumas linhas em branco (eu pessoalmente uso duas linhas em branco). Lembrando que não é uma prática obrigatória.
NÃO DEVE haver mais que uma declaração por linha.
Não é correto declarar mais que uma variável em uma mesma linha, nem mesmo executar mais de um comando por linha. Sempre pule uma linha antes de declarar a próxima variável, chamar a próxima função, etc.
Códigos PHP DEVEM ser indentados com 4 espaços ao invés de TAB.
Nada demais por aqui: sempre que for indentar, adicione 4 espaços. Uma dica é configurar a sua IDE para substituir automaticamente o TAB por 4 espaços, assim você não precisa ficar pressionando a barra de espaço inúmeras vezes.
Utilizando somente espaços e não misturando com tabs, ajuda a evitar problemas com diffs, patches, history e annotations em sistemas de versionamento. A utilização de espaços também torna fácil incluir sub-indentações granuladas para alinhamento inter-linhas.
As palavras-chave (e constantes) “true”, “false” e “null” DEVEM ser escritas com letras minúsculas.
Não use “TRUE”, “FALSE” ou “NULL”.
Quando um namespace for definido, DEVE haver uma linha em branco após a definição deste.
Isso facilita a leitura do código: sempre que você definir um namespace, deixe a próxima linha em branco para então continuar com seu código.
Quando existente, todas as declarações “use” DEVEM estar após a declaração do namespace.
Se você utilizar definir um namespace e precisar usar alguma Trait, sempre faça nessa ordem: primeiro o namespace, depois o “use”.
DEVE existir apenas um “use” por declaração.
Se for necessário utilizar mais de uma Trait, sempre faça em uma nova linha, ou seja:
use TraitUm, TraitDois, TraitTres;
não é correto, uma definição correta deste exemplo seria:
use TraitUm;
use TraitDois;
use TraitTres;
As palavras-chave “extends” e “implements” DEVEM ser declaradas sempre na mesma linha do nome da classe.
As palavras-chave “extends” e “implements”, quando existentes, fazem parte da definição da classe, por isso, não devem ser colocadas em outra linha, logo, ao usar essas palavras-chave, devemos fazer neste formato:
 
class MinhaClasse extends OutraClasse implements MinhaInterface
Listas de “implements” PODEM ser divididas em múltiplas linhas, onde cada linha subsequente é indentada uma vez. Quando fazer isso, o primeiro item da lista DEVE estar na linha seguinte, e DEVE haver apenas uma interface por linha.
Uma exceção da regra anterior: caso sua classe implemente mais de uma interface, você pode quebrar uma linha a cada nova interface para facilitar a leitura, mas certifique-se de estar seguindo o padrão:
class MinhaClasse extends OutraClasse implements
    MinhaInterface,
    MinhaInterfaceDois
…
A visibilidade DEVE ser declarada em todas as propriedades.
Sempre que for definir uma propriedade em uma classe, declare sua visibilidade (public, protected ou private).
A palavra-chave “var” NÃO DEVE ser utilizada para declarar uma propriedade.
A menos que a linha comece com “const”, é certo que se trata de uma variável, então não há porque utilizar “var”.
NÃO DEVE haver mais de uma propriedade por declaração.
Se precisar declarar mais de uma propriedade, defina todas de forma separada, ou seja:
public $varUm, $varDois, $varTres;
é errado. O correto seria:
public $varUm;
public $varDois;
public $varTres;
Nomes de propriedades NÃO DEVEM iniciar com underscore (_) para indicar visibilidade “protected” ou “private”.
Escreva os nomes das propriedades do jeito que eles têm que ser. Se precisar definir visibilidade protegida ou privada, basta usar as palavras-chave reservadas para isso.
A visibilidade DEVE deve ser declarada em todos os métodos.
Assim como para as propriedades, nós devemos sempre informar se um método é public, protected ou private.
Nomes de métodos NÃO DEVEM iniciar com underscore (_) para indicar visibilidade “protected” ou “private”.
Aqui usamos exatamente a mesma regra aplicada para as propriedades: se precisar de um método protegido ou privado, utilize as palavras-chaves reservadas.
NÃO DEVE existir um espaço em branco após o nome de um método; A chave de abertura do método DEVE ficar na mesma linha do nome do método, a chave de fechamento DEVE ficar logo após o corpo do método; NÃO DEVE haver um espaço em branco após o parêntese de abertura; NÃO DEVE existir um espaço em branco antes do parêntese de fechamento.
Um método deve ser definido da seguinte forma:
public function meuMetodo($argumentoUm, $argumentoDois)...

 Ao invés de:
  
public function meuMetodo ( $argumentoUm, $argumentoDois )...
Na lista de argumentos dos métodos NÃO DEVE haver espaço antes de cada vírgula, mas DEVE haver um espaço após cada vírgula.
Essa regra se assemelha ao português básico: espaço só depois da vírgula, então, sempre que for definir um método, nunca coloque espaço antes de uma vírgula na lista de argumentos.
A lista de argumentos dos métodos PODE ser dividida em múltiplas linhas, onde cada linha é indentada uma vez. Quando fazer isso, o primeiro item da lista DEVE estar na linha seguinte, DEVE haver apenas um argumento por linha e o parêntese de fechamento da lista e a chave de abertura do corpo do método DEVEM estar na mesma linha, com apenas um espaço entre eles.
Se for o caso de termos um método com muitos argumentos, podemos quebrar a lista de argumentos em novas linhas, deixando exatamente neste formato:
public function meuMetodo(
   $argumentoUm,
   $argumentoDois,
   $argumentoTres
) {
   /* corpo do método */
}
Quando presentes, as palavras-chave “abstract” e “final” DEVEM preceder a declaração de visibilidade do método ou propriedade.
Sempre que utilizar “abstract” ou “final”, certifique-se de ter essas palavras-chave antes da visibilidade, ou seja:
abstract public function meuMetodo()
está correto, enquanto:
public abstract function meuMetodo()
está errado.
Quando chamar um método ou função, NÃO DEVE haver espaços entre o nome do método/função e o parêntese de abertura, NÃO DEVE haver espaços após o parêntese de abertura e NÃO DEVE haver um espaço antes do parêntese de fechamento; Na lista de argumentos, NÃO DEVE existir espaços antes das vírgulas, mas DEVE existir um espaço após cada vírgula.
A regra é a mesma que a da definição dos métodos. Ao chamar um método ou função, devemos seguir este formato:
minhaFuncao($argumentoUm, $argumentoDois);
e evitar, por exemplo, este formato:
minhaFuncao ( $argumentoUm , $argumentoDois );
Ao chamar um método ou função, a lista de argumentos PODE ser dividida em múltiplas linhas. Quando feito isto, o primeiro argumento DEVE estar na linha seguinte, e DEVE haver apenas um argumento por linha.
Exatamente a mesma regra para a definição dos métodos. No caso da lista de argumentos ser grande, nós podemos colocar os argumentos cada um em uma linha.
Abaixo, temos uma lista autoexplicativa das principais regras para estruturas de controle:
DEVE haver um espaço após a palavra-chave da estrutura de controle;
 NÃO DEVE haver um espaço após o parêntese de abertura (quando aplicável);
 NÃO DEVE haver um espaço antes do parêntese de fechamento (quando aplicável);
 DEVE haver um espaço entre o parêntese de fechamento e a chave de abertura (quando aplicável);
 O corpo da estrutura de controle (quando aplicável) DEVE ser indentado uma vez;
 A chave de fechamento (quando aplicável) DEVE ser colocada uma linha após do corpo da estrutura de controle.

 Agora, algumas regras mais específicas:
A palavra-chave “elseif” DEVE ser usada no lugar de “else if”.
O PHP possui uma palavra-chave reservada para a condição em que o else precisa checar alguma outra condição, que é o elseif. Sendo assim, não precisamos utilizar as estruturas de controle “else” e “if” para conseguir este efeito.
A palavra-chave “case” DEVE estar indentada um nível a frente do respectivo switch, e a palavra-chave “break” DEVE estar no mesmo nível que o corpo do respectivo “case”; DEVE haver um comentário do tipo “// no break” sempre que não houver uma palavra-chave “break”.
Para compreender melhor esta regra, dê uma olhada neste exemplo de como dever ser o "switch ideal" no PHP (retirado do site oficial do PHP-FIG):

 
 
Closures (funções anônimas) DEVEM ser declaradas com um espaço após a palavra-chave “function”, e um espaço antes e depois da palavra-chave “use”;
A chave de abertura da closure DEVE estar na mesma linha, e a chave de fechamento DEVE estar na linha após o corpo da função;
 NÃO DEVE existir um espaço após o parêntese de abertura da lista de argumentos e NÃO DEVE existir um espaço antes do parêntese de fechamento;
 Na lista de argumentos NÃO DEVE haver um espaço antes de cada vírgula, mas DEVE haver um espaço após cada vírgula;
 Os argumentos que tenham um valor padrão DEVEM ser colocados no final da lista de argumentos;
As regras acima são todas sobre o formato ideal para as closures (funções anônimas), por isso achei melhor listar todas acima e depois incluir o exemplo do formato correto:
$funcao = function ($argumentoUm, $argumentoDois, $argumentoTres = “valor padrão”) {
   /* Corpo da função */
};
 
Ou, no caso de utilizar a palavra-chave “use”:
$funcao = function ($argumentoUm, $argumentoDois, $argumentoTres = “valor padrão”) use ($variavelUm, $variavelDois) {
   / * Corpo da função */
};
A lista de argumentos da closure PODE ser dividida em múltiplas linhas, onde cada linha é indentada uma vez. Quando isto for feito, o primeiro item da lista DEVE estar na próxima linha, e DEVE haver apenas um argumento por linha; Quando a lista de argumentos for dividida em várias linhas, o parêntese de fechamento e a chave de abertura DEVEM estar na mesma linha, separados por um espaço.
A regra é a mesma utilizada para os métodos/funções comuns. No caso de haver muitos argumentos, nós podemos colocar cada argumento em uma linha, seguindo o formato abaixo:
$funcao = function (
   $argumentoUm,
   $argumentoDois,
   $argumentoTres
) {
   /* Corpo da função */
};

 
 E acabamos por aqui sobre a PSR-2. Em breve falaremos da PSR-3, então não deixem de acompanhar o blog!
Lembrando que você pode sempre conferir o conteúdo original no site oficial: php-fig.org.
 
Espero que tenham gostado do conteúdo, e como sempre, se você tiver qualquer dúvida, sugestão, opinião, é só comentar aí embaixo, ficarei feliz em ler e responder todos os comentários :)