Métodos
Este artigo discute vários aspectos da
criação de métodos, visando usabilidade, robustez
e flexibilidade.
Item 23: Verifique a validade dos
parâmetros
Aplicando o princípio de que um erro deve ser detectado o mais
cedo possível depois de ocorrer, valores válidos para os
parâmetros devem ser verificados logo no início do
método, evitando erros posteriores mais difíceis de serem
identificados.
Em métodos públicos, documente a restrição
e utilize a tag @throws do Javadoc
para indicar a exceção
que será lançada se ela for violada, que normalmente
será IllegalArgumentException, IndexOutOfBoundsException ou
NullPointerException.
Já
no
caso de métodos que não são exportados, o autor do
pacote deve assegurar que só serão enviados valores
corretos para o método, portanto a verificação
deve ser realizada através do mecanismo de assertions ao
invés das checagens normais.
Se a checagem da validade do parâmetro já estiver
implícita no processamento do método e for muito custoso
realizar a verificação no início, é
aceitável que ela não ocorra. No caso da
exceção lançada naturalmente pelo método
ser diferente da que seria utilizada na validação do
parâmetro, deve ser feita sua tradução, como
será descrito no item 43.
É importante ressaltar que o melhor é escrever seus
métodos de forma que consigam lidar de forma geral com os
parâmetros, colocando apenas o mínimo de
restrições necessárias para seu funcionamento
correto.
Item 24: Crie cópias defensivas
quando necessário
Apesar do Java ser uma linguagem segura, não permitindo o acesso
direto à memória, é necessário programar de
maneira defensiva, assumindo que os clientes de sua classe
tentarão destruir sua estabilidade, o que pode ocorrer
propositalmente, se alguém tentar quebrar a segurança, ou
por um simples engano de um programador.
No caso de construtores que recebem objetos mutáveis como
parâmetro, é essencial criar uma cópia do mesmo e
utilizá-la como componente da classe, evitando as
conseqüências do objeto original ser alterado. Note que a
validação dos parâmetros deve ser feita já
na cópia, não criando uma janela de vulnerabilidade entre
o tempo que são feitas a validação e a
cópia.
Além disso, não utilize o método clone para fazer
a cópia caso o parâmetro seja de uma classe não
final, e sim crie um novo objeto que contenha os mesmos valores. Outra
precaução que deve ser tomada é não
retornar os objetos internos mutáveis em métodos
accessors, e sim uma cópia dos mesmos.
Claro que se for previsto que a classe controle o objeto fornecido por
um cliente, não é feita a cópia defensiva, e sim
utilizado o original. Mas isso deve estar explícito na
documentação e deve haver confiança entre as
classes que estão compartilhando o objeto.
Item 25: Planeje a assinatura dos
métodos cuidadosamente
Alguns itens que devem ser considerados na criação de
métodos:
- Escolha os nomes cuidadosamente. Obedeça às
convenções, e deixe os nomes compreensíveis e
consistentes com os
outros nomes no mesmo pacote (e da API do Java);
- Não inclua métodos desnecessários, pois
seu excesso torna a classe mais difícil de aprender, usar,
documentar, testar e manter. Para cada ação suportada
pelo seu tipo (incluindo interfaces), inclua um método funcional;
- Evite listas de parâmetros longas. Muitos parâmetros
confundem o programador, especialmente se alguns forem do mesmo tipo.
Soluções para esse caso são dividir o
método ou utilizar uma classe auxiliar para armazenar os
parâmetros;
- Para os tipos dos parâmetros, prefira interfaces a classes,
dando mais flexibilidade ao método;
- Utilize objetos de função apenas quando houver uma
razão legítima, como no caso da
implementação de um Strategy ou Visitor;
Item 26: Utilize overloading (sobrecarga)
de forma adequada
A escolha de qual método overloaded será utilizado
é feita em tempo de compilação. Por exemplo, tendo
a seguinte array:
Collection[]
tests = new Collection[] {new HashSet(), new ArrayList(), new
HashMap().values()};
E fazendo um loop em que é chamado um método classify que
está sobrecarregado para receber Set, List ou Collection, para as
três instâncias ele irá chamar o de Collection, ainda que em
tempo de execução o tipo seja diferente É a
idéia oposta dos métodos overriden (herdados), que
são aplicados de acordo com o tipo da instância e
não da variável que a declara. Portanto, evite overloads
confusos, que aumentam a chance de um programador usando a classe tomar
uma decisão errada. A regra mais segura
é nunca exportar dois métodos overloaded com o mesmo
número de parâmetros. Se isso não for
possível, que pelo menos os tipos sejam mutuamente exclusivos
por cast. E por fim, se for possível receber o mesmo objeto em 2
métodos diferentes, eles devem ter o mesmo comportamento para
este parâmetro.
Item 27: Retorne arrays de tamanho zero,
não nulls
Não há motivo para retornar null em um método que
retorna um tipo de array. É melhor retornar uma array de tamanho
zero, evitando erros no método que recebe esse valor caso ele
esqueça de testar e tratar o null.
Item 28: Escreva comentários de
documentação (javadoc) para todos os elementos expostos
da API
O javadoc provê um meio efetivo de documentar sua API e
mantê-la sempre atualizada, devendo ser usado amplamente.
Todas as classes, interfaces, construtores, métodos ou
declaração de campos exportados devem ser precedidos por
um comentário.
A documentação de um método deve descrever
sucintamente o contrato entre o método e seu cliente. Ela deve
dizer o que o método
faz ao invés de como
faz. Deve enumerar as pré-condições
(através da @throws, @param ou
descrição), pós-condições e efeitos
colaterais. Também deve estar indicada a segurança em
relação a threads. Devem ser incluídas as tags @param para cada
parâmetro, @return se o tipo de
retorno não for void e @throws para as
exceções que podem ser lançadas (checked ou
unchecked), seguidas pela descrição do parâmetro ou
retorno ou da condição em que a exceção
é lançada.
É permitido usar HTML para uma melhor formatação
do texto no javadoc.
A primeira sentença de cada comentário de javadoc
é a descrição resumida do elemento. Tenha cuidado
para que ela não contenha um ponto (por exemplo em uma
abreviação), pois isso quebraria a sentença
antecipadamente. Se for necessário ele deve ser
substituído por "."
Há um mecanismo de reuso de documentação
automática caso ela não seja fornecida para um
método, utilizado no caso de interfaces ou superclasses. Ele
é prático para evitar manter várias cópias
de um mesmo comentário, mas não permite que seja
alterado, sendo necessário reescrever todo comentário
caso o do método da classe em questão seja mais
especializado.
Algumas vezes a API é muito complexa e a
documentação gerada pelo javadoc não é
suficiente, sendo necessário incluir um link para uma
documentação mais completa.
Bibliografia:
Bloch, Joshua. Effective Java.
Resumo por: Vanessa Sabino