Melhorar seu código requer mudanças: funções, arquivos, estruturas, tudo algum dia precisa mudar de nome ou de lugar. Como mudar sem quebrar nada?
Manter uma base de código aberta (open source) tem várias vantagens, mas alguns desafios específicos. Diferente de um serviço que disponibiliza apenas uma API mais restrita, como uma API REST, por exemplo, quase todo o seu código pode ser chamado por terceiros. Por isso você precisa ter cuidado até na hora de renomear uma função simples.
Embora isso tudo pareça meio trabalhoso, não é. Manter sua base de código organizada vale muito a pena!
Faça a mudança em fases
Simplesmente renomear a função direto não é uma boa ideia: soluções que dependem dela vão quebrar de uma hora para outra. Você precisa avisar que uma mudança será necessária e, depois de tempo suficiente, realmente implementar a solução.
Para definirmos o que e quando deve ser alterado, podemos usar o versionamento semântico.
Versionamento semântico
Há algum tempo fiz um vídeo sobre versionamento semântico, ou SemVer. O SemVer dá significado aos números de versões de software, alinhando expectativas do que acontece em cada alteração nos números de versão.
Para um programa na versão 2.4.3, por exemplo, a tabela a seguir resume o que seria a versão maior, menor e correção, assim como o que podemos esperar na versão 2.4.4, 2.5.0 ou 3.0.0.
Maior (2.4.3) | Menor (2.4.3) | Correção (2.4.3) |
Mudanças que quebram a retrocompatibilidade | Introdução de melhorias que não quebram a retrocompatibilidade | Correção de falhas |
Atualizar da versão 3.0.0 requer muita atenção, pois a solução atual pode parar de funcionar | Atualizar para a versão 2.5.0 significa que tudo continua a funcionar, mas com alguma funcionalidade nova | Atualizar para a versão 2.4.4 significa somente que alguns bugs foram resolvidos |
Exemplo prático
Seguindo com o exemplo de renomear uma função do nosso software na versão 2.4.3, vamos dividir o processo em algumas etapas e definir quando lançaremos cada uma delas.
Versão 2.5.0: Implementar o código novo e alterar o código velho sem quebrar
- Implementar o código novo. Seja a função renomeada ou um método completamente novo, o código precisa estar lá para que as pessoas possam fazer a troca;
- Alterar o código velho. Em caso de uma mera troca, o código velho precisa se tornar uma mera embalagem para o código novo junto com um aviso de que aquela solução parará de funcionar em breve;
function nome_novo( $parametro ) {
// Faz alguma coisa.
}
function nome_antigo( $parametro ) {
_deprecated_function( __FUNCTION__, '2.5.0', 'nome_novo' );
nome_novo( $parametro );
}
Repare que chamar nome_antigo()
ainda vai funcionar, mas foi adicionado um aviso de que a partir da versão 2.5.0 a função nome_novo()
deve ser chamada.
Versão 3.0.0: Remover o código velho
Depois de avisar por tempo suficiente, você já pode remover o código. Atenção: essa remoção só pode acontecer em versões maiores.
Você não precisa remover o código na versão imediatamente seguinte. Dependendo da sua base de usuários e do seu calendário de lançamentos, é preferível esperar até a próxima versão maior, no nosso caso 4.0.0 ou 5.0.0.
Um projeto que só lança uma versão maior a cada ano pode ter uma abordagem ligeiramente diferente de um projeto que lança uma versão maior a cada mês, por exemplo.
Arquivos com códigos obsoletos
Uma das intenções por trás dessas mudanças é manter o código limpo e organizado. Com isso em mente, manter essas funções nos arquivos principais do seu projeto pode causar um certo incômodo e uma sensação de desorganização.
Algumas equipes de desenvolvimento movem essas funções para arquivos específicos, nomeados como deprecated.php
, por exemplo. Além de ajudar na leitura do código, essa prática também ajuda a identificar o que pode ser removido na hora de lançar a versão 3.0.0.
Quanto mais comunicação melhor
No exemplo real acima, chamamos a função _deprecated_function()
do WordPress, mas essa função só tem algum efeito se a constante WP_DEBUG
estiver ativa.
Muitas vezes avisar sobre mudanças apenas nos logs é inútil: em muitos casos ninguém está realmente prestando atenção nesses registros. Também é preciso avisar de uma forma acessível e legível para não-desenvolvedores.
Avise sobre mudanças importantes de todas as formas possíveis: avisos nos logs, itens no seu changelog, além de posts de blog e redes sociais quando possível.
Changelog (ou registro de alterações)
O melhor lugar para avisar sobre mudanças em um software é em seu changelog. No WordPress, esse registro é mantido em uma seção específica do arquivo readme.txt e é exibida tanto na página do plugin no WordPress.org quanto no Painel.
Usando o Akismet como exemplo, esse é o link para ver os detalhes da próxima versão do plugin.
Ao clicar no link, um pop-up é aberto, exibindo o changelog:
O WordPress obtém essas informações da seção == Changelog ==
do arquivo readme.txt do plugin hospedado no repositório oficial do WP.org:
Normalmente, changelogs são divididos em seções, separando o que foi adicionado, alterado, consertado, removido e tornado obsoleto. Um exemplo dessa divisão pode ser visto tanto no changelog quanto na notas de lançamento do ElasticPress.
Funções do WordPress
O WordPress tem algumas funções que ajudam a informar o uso de código obsoleto. Aqui está a lista:
_deprecated_function( $function, $version, $replacement = '' )
A função _deprecated_function() é a do nosso exemplo lá de cima. Um jeito simples de marcar uma função como obsoleta.
apply_filters_deprecated( $hook_name, $args, $version, $replacement = '', $message = '' )
Tanto a apply_filters_deprecated() quanto a próxima são envelopes para _deprecated_hook()
, que não faz parte da lista porque não deve ser chamada diretamente. Como o próprio nome diz, essa função aplica um filtro, mas também avisa que ele está obsoleto e, se disponível, fornece a alternativa atual.
do_action_deprecated( $hook_name, $args, $version, $replacement = '', $message = '' )
Similar à função anterior, a do_action_deprecated() aplica uma ação.
_doing_it_wrong( $function, $message, $version )
Embora não esteja diretamente relacionada a código obsoleto, coloquei a _doing_it_wrong() na lista porque ela é útil quando a mudança precisa de mais atenção do que uma simples mudança de nomes.
_deprecated_argument( $function, $version, $message = '' )
Como o próprio nome diz, a função _deprecated_argument() informa a mudança de uso de um argumento.
Sempre relacionada a um argumento, essa função pode ser usada em alguns cenários diferentes:
- O valor esperado de um argumento, como
'blacklist_keys'
, que passou a ser'disallowed_keys'
; - Um argumento que não existe mais;
- Um índice de um argumento que é um array. Esperava-se
$args['cat']
, por exemplo, e agora espera-se$args['taxonomy']
.
_deprecated_file( $file, $version, $replacement = '', $message = '' )
Marca um arquivo inteiro como obsoleto. Exemplos de uso da função _deprecated_file() são arquivos renomeados e arquivos desnecessários, como o wp-includes/class-json.php, que chama a função avisando que a partir da versão 5.3.0 do WordPress, a extensão JSON nativa do PHP é requisito obrigatório.
_deprecated_constructor( $class, $version, $parent_class = '' )
A função _deprecated_constructor() é relacionada a construtores de objetos. Antigamente o método construtor de uma classe em PHP tinha o mesmo nome que sua classe, mas a partir do PHP 5.4 recomenda-se usar __construct()
. Construtores com nomes da classe ficaram obsoletos a partir do PHP 7.0 e não devem mais ser usados.
Sobre os termos em português
Alguns vão notar que em todo o texto usei o termo obsoleto, quando em inglês se usaria deprecated. Não quis usar um neologismo como deprecado, nem usar a tradução errada depreciado (em inglês se teria depreciated, o que obviamente não é o caso).
Em inglês há uma distinção entre deprecated e obsolete: o primeiro se refere a um código que funciona, mas não é mais recomendado. O segundo se refere a um código que não funciona mais.
Aqui no texto, todas as referencias a código obsoleto se referem a um código que ainda funciona, mas não é mais recomendado.
Conclusão
Manter a base de código limpa e organizada é essencial. Para fazer mudanças que quebrem a retrocompatibilidade é preciso planejar a mudança em fases.
O versionamento semântico pode ajudar a planejar quais mudanças serão liberadas em quais versões, para que o usuário não seja pego de surpresa.
Comunicar mudanças através de changelogs também traz mais visibilidade para ações que os usuários precisam tomar. Seções que listam essas mudanças especificamente ajudam ainda mais.
Vimos também algumas funções do WordPress que podem ajudar a comunicar as mudanças em vários cenários diferentes.
Por fim, vimos como esses termos são usados em inglês e como a tradução para o português pode ser complicada.
Um video sobre esse tutorial seria muito legal. 😉