quinta-feira, dezembro 15, 2005

Por um codigo melhor I

Se vc é programador, mesmo sem nunca ter lido algum livro sobre refactoring[1], é bem provável que já tenha reescrito algum trecho de código para melhorá-lo, torná-lo mais legível, rápido, ou seja lá o que for. Refactoring é uma das práticas mais comuns em metodologias ágeis[2] porque, geralmente, metodologias ágeis estão preocupadas com a qualidade dos artefatos mais importantes e imprescindíveis. E, claro, em desenvolvimento de software, pouca coisa é realmente mais imprescindível do que o próprio código, afinal, código é o artefato sempre presente. Daí haver a necessidade de torná-lo tão legível quanto o possível para que ele represente um "documento" sobre o sistema. Refactoring também entra aí: arrumar a casa e fazer todos entenderem o propósito do código - ou seja, como citei logo acima, fazer um punhado de instruções funcionarem como um "documento" do sistema. Mas, nesse posts, não vou falar especificamente sobre um catalogo de refactoring, se quiser ler algum, nada mais recomendado do que o livro do Fowler[3]. Também vou passar ao largo de definições mais aprumadas sobre o refatoração de código ou explicações de como test unitários[4] permitem reescrever o código de maneira segura.

Minha intenção com esse post é citar algumas dicas para evitar código ruim logo de primeira. Isso não vai lhe eximir completamente de reescrever uma parte ou outra enquanto o sistema evolui, isso é natural. Minha pretensão é evitar que vc pense em trucidar alguém - talvez vc mesmo, talvez eu - quando precisa refatorar partes do software. Vamos as dicas:

1. Dê nomes entendíveis a seus pacotes, classes, métodos e variáveis. Nomes entendíveis também passam pelo conhecimento comum entre os desenvolvedores[5]. Se for costume chamar um método que soma valores de "add", não tente usar algo como "xyz". Em suma essa dica se resume a fazer as pessoas com conhecimento do domínio reconhecerem o propósito da classe/metodo/variavel apenas pelo nome. Exemplos bobos - em Java - de como não fazer:

public void copy(File x, File y);
public long diff(Date d1, Date d2);

Dã, essa ficou fácil copia um arquivo para outro e vê a diferença entre as datas. Não? Não estava tão claro assim. Hum, e se eu tentar assim:

public void copy(File source, File destination);
public long diffInSeconds(Date inicio, Date fim);

Melhor, agora vc sabe qual arquivo é copiado para onde, sabe qual é a data de origem e qual a final e sabe que a diferença é em segundos. Mesmo em um exemplo tão trivial dá para perceber como escolher bem os nomes ajuda a tornar o código mais legível.

2. Transforme operações pouco claras em métodos com nomes - ah, os nomes - que identifiquem melhor a operação. Mesmo em alguns casos aparentemente simples isso pode ajudar um bocado. Por exemplo:

String id = "A@1232143245547657465";
...
if(id.charAt(0) == 'A') {
// algumas linhas antes - bastam 5
Permissoes p = getPermissoesAdmin();
}

Nessa situação vc pode perceber que 1) a operação é simples mas não está clara para quem bate o olho sobre o código e 2) eu sou péssimo para dar exemplos. Deixe-me tentar novamente:

double precoFinal = preco + preco * (17/100) - 10;

Tá, desisto de dar bons exemplos, vamos ao que interessa: tornar os dois trechos mais fáceis de entender. Primeiro, vamos transformar a operação do if em um método e depois usar a dica 1 para facilitar ainda mais a minha vida no futuro. Então, o código será:

String userId = "A@1232143245547657465";
...
if(isAdministrador(userId)) {
// algumas linhas antes - bastam 5
Permissoes permissoes = getPermissoesAdministrativas();
}

private boolean isAdminitrador(String userId) {
return id.charAt(0) == 'A';
}

Talvez vc ache que estou forçando a escrita de mais código, mas, na verdade, melhorei a legibilidade e permiti que a operação para indicar permissões administrativas seja tratada em um único ponto. Já o segundo exemplo, ficaria melhor assim:

double precoFinal = precoComTaxasDescontos(preco);

private double precoComTaxasDescontos(double preco) {
double imposto = preco * (17/100);
double desconto = 10;
return (preco + imposto - desconto);
}

Você até pode ter pensado no aumento de código, mas há, em sistemas reais, vantagens menos perceptíveis, ao menos nesses exemplos, como aplicar o conceito de DRY[6].

3. Remova a complexidade das classes clientes para os métodos que elas usam. Isso faz com que o código nas classes clientes esteja preocupado com suas próprias operações, e não em dar suporte as operações dos métodos que elas usam. Exemplo bobo - mas (quase) real dessa vez:

int idBah = bah.getId();
int numBah = bah.getNum();
String name = foo.getName();
long somethingId = foo.getSomething().getId();

facaAlgo(idBah, numBah, name, somethingId);

Ruim, muito ruim. Imagine 10 classes clientes, pense na repetição de código e... ...isso mesmo, refatore para trazer a complexidade para o método assim:

public void facaAlgo(Bah bah, Foo foo) {

int idBah = bah.getId();
int numBah = bah.getNum();
String name = foo.getName();
long somethingId = foo.getSomething().getId();

// faz o treco

}

E a classe cliente, bem mais aliviada:

facaAlgo(bah, foo);

Bom, sem mais dicas por enquanto. Alias, eu gostaria de ouvir as de vcs. Quais as dicas, bastante práticas, se possível, para tornar meu código um pouco menos fedorento?

Referências:

[1] - Refactorings in Alphabetical Order
[2] - Google - Agile Methodologies
[3] - Refactoring: Improving the Design of Existing Code - Martin Fowler
[4] - JUnit, Testing Resources for Extreme Programming
[5] - Code Conventions for the Java Programming Language
[6] - Don't Repeat Yourseft
[7] - Making Wrong Code Look Wrong
[8] - Padrões de Nomenclatura - Forum GUJ

valeuz...

1 Comentarios:

Anonymous Anônimo disse...

Hey Guys

Well this is my introduction to all of you here at www.blogger.com[url=http://susportsnews.info/].[/url] I just hope I can manage to contribute something to the awesome discussions that take place here[url=http://learnnewthingsic.info/].[/url][url=http://aslearnnewthings.info/bookmarks].[/url]

I lokk forward to participating in the awesome community[url=http://sportsnewsly.info/forum].[/url][url=http://cesportsnews.info/].[/url]

11:03 AM  

Postar um comentário

<< Home