Melhor pratica para Nullpointer

bom… lógico que da pra evitar tantas verificações mexendo nisso antes… mas dentro desse contexto que ele passou, eu deixaria assim:

[code]public String getCodMunicipio() {

String ibge = "";

try {  
    ibge = endereco.getRua().getCidade().getCodigoIbge().toString();  
} catch (NullPointerException e) {  
   // tratamento de erro comum
}  

return ibge;

} [/code]

parece mesma coisa que ele passou mas o jeito que fiz evita tratar de códigos dentro do catch… que não é considerado boa prática… catch geramente só usamos pra capturar o erro

[quote=fernandoat]Olá pessoal, tenho uma aplicação que em determinado momento é mostrado o codigo do ibge de um estado para um determinado endereço.
Para pegar ele é feito dessa maneira.

    endereco.getRua().getCidade().getCodigoIbge()

Esse código nesse caso não é obrigatório, e devo mostrar em branco minha duvida é qual a melhor pratica para isso.

[/quote]

Isto é uma clara e óbiva violação da Lei de Demeter que já foi conversado ainda ha pouco tempo aqui

O que está errado não o nullpointer, é a chamada telescopica.

A opção de usar exception não é aceitável. Exceções não servem como substituto de ifs. É uma má prática se vc fizer isso.

Existe a opção de criar um Maybe (Option em outras linguagens) como é usado no Google Guava.

Existe a opção de criar um Utils que sabe interpretar e navegar nessa estrutrua protegendo de nulls.

Mas eu ainda acho que o melhor é isto


class Endereco(){


    public String getCodigoIBGE(){
        return this.rua == null ? null : this;rua.getCodigoIBGE();
}

}

Repare como o endereço delega à rua, que delegaria à ciddade, etc…
Para isto vc tem que ter acesso às classes. Se tem, este é o jeito correto de evitar a chamada telescopica e respeita a lei de demeter.

Se não tem acesso à classe, faça com métodos (que podem staticos num utis da vida ou private na classe que está tentando ler o codigo)


public String getCodigoIBGE(Endereço endereco){

            if (endereco.getRua () != null ){

                      return getCodigoIBGE(endereco.getRua());
           }

           return null;
}

public String getCodigoIBGE(Rua rua){

            if (endereco.getcCdade() != null ){

                      return getCodigoIBGE(endereco.getcCdade());
           }

           return null;
}

Em Resumo, faça leitura recursiva controlando em cada ponto o null. Se vc ainda quer uma mensagem, em vez de retornar null, vc pode lançar um exception. E se lançar exception , ai sim, pode usar a primeira construção que colocou. mas nunca jamais faça catch de NullpointerException.

Muitas vezes parece que sou invisivel neste forum… Já deixei de tentar perceber porquê… :smiley:

oi pmim, boa haahahaah

eu vi rapidamente sua solução, porém, só consegui enxergar a ideia com a explicação do gomes, falando q poderiamos evitar alguns ifs, perdão man! vc n eh invisivel já vi varios topicos seus q me ajudaram

abrassss

Dá uma olhada no Introduce Null Object. http://sourcemaking.com/refactoring/introduce-null-object

Parece um trabalho grande mesmo esta prática, nunca experimentei mas pode ser que fique legal o resultado.

Este site em geral tem um conteúdo muito bom sobre Refactoring e Patterns.

Como já foi falado acima, isso é uma má prática…
De acordo com o Effective Java, Unchecked exceptions NÃO devem ser tratadas via try catch…

RuntimeExceptions são erros de programação e não são recuperáveis, se lançar NullPointer o programa deve parar, e não ser recuperado retornado string vazia.

Para evitar tal estado, poderia criar um método a parte para validar se o objeto está em estado consistente
e somente depois fazer a chamada ao método desejado. Igual ao se fazer a chamada à algum Iterator…

if(it.hasNext()) { objetc = it.next(); }

pessoalmente eu acho que não é legal mesmo você usar exceção “como se fosse um if”, mas em certos casos eu ainda acho que fica melhor… esse provavelmente é um destes. Considero melhor por que com a exceção, primeiro que o código fica mais fácil de ler, bater o olho e entender ele, segundo pro que ele ficará mais rápido na maioria dos casos, pense bem, na maioria dos casos espera-se este campo não esteja nulo, sendo assim ao invés de ficar fazendo um monte de comparação já o pega direto e o usa.

mesmo nos casos onde estiver nulo, la por exemplo nos últimos itens, precisaria do teste más desconfio que o lançamento da exceção seja mais rápido que a verificação a partir da terceira, sei la…

um ultimo comentário, se isso for utilizado em mais lugares, a lei de demeter torna-se mais interessante, então isso ficaria no endereço…

sei que isso vai contra certos princípios de códigos bem escritos, mas acho que me baseei nos motivos destes princípios (legibilidade de código, se usada a lei de demeter reaproveitamento e quando for importante, performance).

claro que isso é opinião, se eu estiver errado em algum ponto aceito criticas construtivas.

Já que a discussão está tocando nesse ponto de “as exceções devem ou não fazer parte do fluxo normal de decisão de um programa ?”.

Só existe na história desse País uma situação onde a checagem deve ser feita usando exceção. E é por uma deficiência na API, não porque é bonito.
Esse caso é quando se quer verificar se uma string é um número ou data válida. Não existe na API um método que faça essas checagens.

Por exemplo:

boolean isValidNumber(String s) { NumberFormat nf = ... // Inicializa e seta os atributos conforme o formato desejado try { nf.parse(s); return true; //Sucesso no parse } catch (NumberFormatException nfe) { return false; } }

Poderia varrer a String e fazer a checagem, dependendo do caso isso é simples (por exemplo se a String precisa ser exclusivamente numérica), mas também pode ficar complexo, com sinais de +/-, decimais, agrupamento, notação em potência de 10, etc.

O mesmo com datas, é possível verificar a formatação básica com uma regex, mas aí tem todo o trabalho de ver se o dia é válido naquele mês, se é bissexto, lidar com formatos diferentes, etc.


Para todos os outros casos, devemos testar ANTES de chamar a operação que pode causar exceção. Se der exceção no ponto onde minha checagem não esperava então ótimo, acabamos de pegar um bug :slight_smile:

[quote=maior_abandonado]pessoalmente eu acho que não é legal mesmo você usar exceção “como se fosse um if”, mas em certos casos eu ainda acho que fica melhor… esse provavelmente é um destes. Considero melhor por que com a exceção, primeiro que o código fica mais fácil de ler, bater o olho e entender ele, segundo pro que ele ficará mais rápido na maioria dos casos, pense bem, na maioria dos casos espera-se este campo não esteja nulo, sendo assim ao invés de ficar fazendo um monte de comparação já o pega direto e o usa.

mesmo nos casos onde estiver nulo, la por exemplo nos últimos itens, precisaria do teste más desconfio que o lançamento da exceção seja mais rápido que a verificação a partir da terceira, sei la…

um ultimo comentário, se isso for utilizado em mais lugares, a lei de demeter torna-se mais interessante, então isso ficaria no endereço…

sei que isso vai contra certos princípios de códigos bem escritos, mas acho que me baseei nos motivos destes princípios (legibilidade de código, se usada a lei de demeter reaproveitamento e quando for importante, performance).

claro que isso é opinião, se eu estiver errado em algum ponto aceito criticas construtivas.[/quote]

Existe um ranking de práticas, ou seja, algumas são melhores que outras. Então tempos, más práticas, práticas, boas práticas e melhores práticas.
As melhores práticas dizem que vc não deve usar try-catch para tratar nullpointer. A razão disso não é legibilidade, é que pode mascarar outros defeitos que não aquele que vc acha que vai acontecer e ai seu programa vai começar a funcionar errado, mas parecendo que funciona certo. No exemplo em estudo, se o endereço em si for null temos a mesma execeção. Mas se o endereço em si for null o erro está em outra parte do sistema que não está lendo ele direito. Mas o que vc vai ver é nenhum erro e nenhum odigo IBGE nunca. Isto é um bug mais complicado de avaliar, e pela simples razão que fez catch de nullpointer.

Existem razões lógicas e até matemáticas por baixo das melhores práticas. Não é apenas um agregado de ideias avulsas. A legibilidade também é um boa prática, mas neste caso o que vc chama de “legebilidade” signiica “escrever menos”. Escrever menos não é uma boa prática em si mesmo e não é razão que justifique coisa alguma. Legibilidade é “eu entendo o que leio”. O programador que ler o catch não vai entender porque o nullpointer está sendo capturado sem um coment que explique. Portanto, não está ajudando à legibilidade coisa nenhuma.

É comum este sentimento de “posso violar as melhores práticas se houver um boa razão” e isso é verdade, o problema é que as razões que são dadas são normalmente más.
A lei de demeter é sempre importante , como todos os principios em geral. dizer que existe uma ocasião quando ela não é importante é como dizer que às vezes a gravidade não atrai os objetos.

Vejam assim, estes princípios são forças internas ao design OO e elas operam , ou deveriam operar, para chegar num melhor modelo. Mas tem as forças externas que também operam sobre o sistema e impedem o modelo de ser o melhor que poderia. Estas forças externas são várias como custo e tempo mas temos também a indulgência do programador em achar que a sua razão é boa o suficiente para contrariar os princípios. E este é o real problema. Porque é de certa forma subjetivo e artificial. ( ou contrario do custo e do tempo que são reais ).

Então, a menos que a gente goste de apostar o design dos sistema na nossa indulgência é melhor não violar os principios. É para isso que eles foram reunidos.

Ao meu ver, se você utilizar o primeiro formato seria correto criar uma exceção para essa regra. Assim, caso ocorra o nullpointerexception, ao invés de você simplesmente receber um nullpointer sem muita informação no stack, você receberia uma exceção criada por você que seria facilmente identificada.

Não acho que o NullPointerException deve ser encarado somente como erro do programador. Muitas outras ocasiões condizem com esta condição e não precisa necessariamente ser um erro de programação.

Eu normalmente trato tudo com exceções e no ultima camada da aplicação, eu dou o tratamento adequado para cada exceção.

Pode não existir “a forma ideal” de se fazer tal coisa em java ou qq outra linguagem. Acho que a vivencia e experiencia de cada um acaba fazendo com que você chegue ao melhor modelo.

Já li aqui no fórum um tutorial, se não me engano escrito pelo CV, que trata de forma clara o tratamento de exceções. Acho que vale a pena dar uma olhada e talvez chegar a uma conclusão própria.

Boa sorte =)

Ótimos argumentos, sergiotaborda. Concordo plenamente.

Sobre exceptions tem um tutorial muito bom aqui

Sobre o NullPointer eu acho que já falaram bastante, eu também acho uma boa tratar diretamente nos Beans, um bom uso para anotações

aqui ou aqui podemos encontrar ajuda…

Sobre boas práticas, más práticas, acho que muitas acabam mudando com o tempo conforme a tecnologia vai mudando, hoje em dia não devemos (pelo menos não deveríamos) considerar mais o uso de Scriptlets em JSP’s, infelizmente é o que eu mais vejo por ai… rs

[quote=André Fonseca]Sobre exceptions tem um tutorial muito bom aqui

Sobre o NullPointer eu acho que já falaram bastante, eu também acho uma boa tratar diretamente nos Beans, um bom uso para anotações

aqui ou aqui podemos encontrar ajuda…

Sobre boas práticas, más práticas, acho que muitas acabam mudando com o tempo conforme a tecnologia vai mudando, hoje em dia não devemos (pelo menos não deveríamos) considerar mais o uso de Scriptlets em JSP’s, infelizmente é o que eu mais vejo por ai… rs[/quote]uhum.

Se não me engano o java 7 já tem até uma saída que seria algo como: cidade.getEstado?().getNome().