Arquivos Mensais: maio 2015


O inferno de null

As tragédias gregas são famosas… O inferno de Dante também… Mas o que mais me aflige até hoje é o inferno de null. Estou eu lá programando bunitinhu e do nada, sem aviso, NullPointerException. Devido à problemas emocionais, daqui por diante usarei apenas NPE, pois esse erro é daqueles ‘que não se pode dizer o nome’…

O que é null?

Resposta: Nada! Simples assim. Mas e?????? Bem, o ‘pobrezinhu’ do null aparece sempre que se tem uma declaração de objeto mas nenhum objeto associado! Ou seja, tu reservou uma variável (pra colocar alguma coisa), mas como ainda não colocou, o Java (C#, php) define como null ou te obriga a declarar como algo e tu coloca como null. Aí começa o inferno.

Mas qual o problema?

Resposta normal: todo!

Resposta irônica: é só mais um if!

Como por padrão, todos usam null e o próprio compilador te faz esse “favor”, a gente tem que programar com o seguinte pensamento: o que eu estou recebendo pode ser null? E a resposta é quase sempre SIM! …… só respirando ….. me acalmei……

Bem, se cada vez que vou precisar do retorno de um método eu precisar checar se o retorno é null, quantos if ( foo == null) eu vou ter que ter? 1, 2, 3, …., 50, …, 100, …. 100000, ….. NaN! Deu pra entender…..

Além disso, o maior problema de todos: a NPE estoura onde tu recebe o null e não onde tu cria o null!!!!!! (só pra garantir a ênfase: !!!!!!!!!!!!!!!!!!!!)

Como posso ajudar a salvar o mundo?

Essa é a parte legal! Todos nós podemos ajudar a resolver o problema!

Exemplos:

Collections

Esse é o mais trivial. Primeiro a pergunta: o que é uma colection? Algum tipo de lista ou algo parecido. Pensemos em semântica (significado das coisas): se tenho uma lista sem itens, então eu tenho?

  • [ ] Nada
  • [ ] Lista vazia

Pense um pouco antes de responder! ….. ….. ….. ….. A resposta certa é …… ….. ….. ……. ….. UMA LISTA VAZIA!!!! Então eu me pergunto: porquê alguém devolveria null (nada) ao invés de uma lista vazia? Não tem sentido… mas pode ser por causa do uso histórico do null.

Observemos:

List<String> lista = new LinkedList<>();

List<String> retornaLista(){
    if(lista.isEmpty()){
       return null;
    }
    return lista;
}

Essa aí em cima doeu nos rins, mas é só pra dar a idéia do que me parece quando recebo null ao invés de uma lista vazia. Observer também que listas possuem um método pra verificar se a lista é vazia. O mais natural (e lógico) seria algo:

List<String> lista = new LinkedList<>();

List<String> retornaLista(){
    return lista;
}

E é isso que eu esperaria de qualquer método que me prometesse uma lista! Promessa é dívida (programação por contrato). Se o método promete, a API promete, tem que cumprir. Claro que dá pra colocar um adendo no contrato pra dizer que uma lista vazia vai ser retornada como null, mas fica a dúvia: pra quê?

Objetos

No caso de objetos o problema é um pouco mais difícil, mas o null é também mais aceitável!

Vou direto a um exemplo:


String nome; String getNome(){ return nome; }

O que temos acima é um simples getter. Como o getter retorna o valor da variável nome, que não foi explicitamente inicializada, o Java garante que nome = null! Então, se eu não colocar nada na variável nome, o método getNome retornará null.

Os casos de objetos nulos devem ser avaliados sempre de forma semântica, o que exige entender o problema antes de vomitar o código! (Desculpe o modo). Não adiata sair escrevendo código pra resolver um problema que eu não entendo e não tenho a solução dele em mente!

Voltando ao exemplo do nome: existe algum nome que seja igual a uma String vazia, ou seja, “” (o que está entre as aspas)? Acho meio difícil (impossível). Então, semanticamente, null singifica “”, e existe um método na classe String chamado isEmpty. Dessa forma, posso testar se um nome existe ou não somente quando precisar que tenha um nome em si. Afinal, esse nome pode ser o nome próprio que alguém deu para o seu carro…. desnecessário né (homenagem a uma estagiária)! Neste caso, seria totalmente opcional!!

Para objetos customizados (criados por você), você pode adicionar um método do tipo isNull ou isEmpty ouisValid que saberá quando o objeto representa algo nulo, vazio ou inválido. Assim fica mais fácil de depurar os erros, pois lembre-se: a NPE estoura onde tu recebe o null e não onde tu cria o null!!

Ahhh, mas a bilioteca|framework|API que eu uso me devolve nulo!

Como ela é “boba, feia, chata e má”…….

Então, crie uma classe responsável por fazer a ponte entre essa bilioteca|framework|API e te devolver algo não nulo e semânticamente equivalente!

Dica: dê uma olhada no post Java/JPA: evitando null no Mapeamento de Banco

Considerações finais

Minha opinião: eu não gosto de null, odeio depurar NullPointerException e adoraria que isso deixasse de existir. Mas o mundo é cruel conosco…..

Se todos nos unirmos, poderemos livrar o mundo de tamanho mal!

Ps 1.: Mande suas dúvidas, críticas, sugestões pra mim (meus dados de contato estão na opção “Contato”, no menu =D).

Ps 2.: Pode comentar também, o registro é obrigatório só pra evitar spans nos comentários……

Ao Infinito e Além!

Ps 3.: Desnecessário, né!