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é!


Java/JPA: evitando null no Mapeamento de Banco

Olá Pessoal

Várias vezes já passei por várias dificuldades no mapeamento de banco de dados em Java, usando tanto Hibernate puro como JPA. Os maiores problemas não são com o uso das anotações ou configurações em XML, pois estas estão documentadas. Os maiores problemas são com pequenos detalhes que podem sair causando NullPointerExceptions a varrer. E depois que apareceu o erro, fica difícil depurar, pois o maior problema desse tipo de exceção é que ela é disparada onde deveria haver um objeto não nulo, e não onde se deveria colocar o valor não nulo no objeto enviado. É quase o problema do ovo ou a galinha.

O problema do null

O Java tem suporte a referência nula, o famigerado null. Isso quer dizer que quando você escreve String str = null, você está dizendo guarda o nome str pra quando eu quiser uma String, mas não coloca nada lá ainda. O problema é que quando você for passar a variável str para algum método, ele terá que testar se o valor é null, caso contrário ele lançará uma NullPointerException quando tentar acessar qualquer método da classe String. O problema vai parecer ser o método que usa a variável, ao invés do método que criou a variável. O Java tem suporte a validação de parâmetros de métodos usando anotações (ex.: @NotNull), mas isso não impede de criar uma variável com valor nulo, só faz a validação dos parâmetros de entrada de um método em que a String vai ser usada no futuro.

Voltemos ao caso String str = null. Pense no seguinte: o que significa null? Em princípio, que a String str está vazia. Não seria o mesmo que String str = ""? Caso a resposta seja sim (e é sim!), ao invés de testar em tudo que é lugar se a String str é null, podemos simplesmente usar o método isEmpty().

Colocando agora com mais código:

// usando null
String str = null;

///

void metodoQueUsaString(String str){
    if(str != null) {
        // faz o processamento
    } else {
       // reporta algum tipo de erro, ou não faz nada
    }
}
// sem usar null
String str = "";

void metodoQueUsaString(String str){
        // faz o processamento
 }

Viu como é mais simples? (SIM!)

Sempre que possível, garanta um retorno não nulo!

O que isso tem com mapeamento de banco?

Simples! JPA/Hibernate retornam null sempre que não há resultado encontrado! E agora?

Primeiramente vamos avaliar o seguinte: sempre (quase sempre) que usamos JPA e Hibernate, usamos algum tipo de padrão, como o DAO, para encapsular as chamadas ao JPA/Hibernate e agrupar os métodos relevantes para cada tipo de entidade mapeada. Por exemplo:

class MinhaEntidadeDAO {

    public MinhaEntidade buscaPorId(Number id){
        // busca uma entidade no banco por id
    }

    public List<MinhaEntidade> listar(){
        // busca todas as entidades no banco
    }

    public void salvar(MinhaEntidade me){
        // salva/atualizar no banco
    }
}

O problema é que estamos tão acostumados com o null que não percebemos que ele permeia tudo e muitas vezes sem necessidade. Vejamos:

buscaPorId:
o método retorna a entidade encontrada ou null
listar:
o método retorna a lista de entidades, ou null

Para tudo!!!!

listar()

Primeiro: por que causa, motivo, razão ou circunstância retornar null no método listar ao invés de retornar uma lista vazia? Retornando uma lista vazia não teremos NullPointerException. Mas como saber se existe alguma coisa lá? Simples: isEmpty().

Imagine um método em que não importe quantos resultados você recupera, mas o que importa é que uma operação qualquer seja efetuada em todos os valores retornados. Por exemplo, tem um campo com valor 1 na minha tabela, e quero que todos passem para 2:


@Entity @Table(name = "minha_entidade") class MinhaEntidade { // mepeamento de id omitido por simplicidade int valor; int getValor(){ return valor; } void setValor(int valor){ this.valor = valor } }

Para mudar todos os valores de 1 para 2:


MinhaEntidadeDAO dao = new MinhaEntidadeDAO(); for(MinhaEntidade me: dao.listar()){ if(me.getValor() == 1){ me.setValor(2); dao.salvar(me); } }

Neste caso acima, se o méodo listar retornar null só porque não tem nenhum registro, então vou ter que adicionar uma checagem de nulo:

List<MinhaEntidade> lista = dao.listar();
if (lista != null){
     // código anterior
}

Teremos então um aumento de complexidade! Mas se ao invés de retornar nulo, eu retorna uma lista vazia, não preciso mais checar por nulo, e simplifico meu código.

Mas se eu precisar de uma lista NÃO vazia? Somente nestes casos testo com lista.isEmpty() e pronto!

List<MinhaEntidade> lista = dao.listar();
if (!lista.isEmpty()){
    // código que exige lista com pelo menos 1 elemento
}

buscaPorId(Number id)

Segundo: como resolver o problema de quando não encontrar um valor para uma busca por 1 elemento, como o buscaPorId, retornar algo diferente de null?

Podemos criar uma interface, por exemplo EntidadePersistida, com métodos comuns a todas as entidades:


interface EntidadePersistida { Number getId(); // minhas entidades sempre tem id numérica (int ou long) boolean isNull(); }

Ao implementar o mapeamento, devemos implementar a interface EntidadePersistida e preencher o método isNull com uma verificação de campos que indique que a entidade não está preenchida. Isso pode ser feito até por uma variável booleana!

class MinhaEntidade implements EntidadePersistida {
    // algumas omissões por simplicidade

    boolean nula = false;

    MinhaEntidade(boolean nula){
        this.nula = nula;
    }

    boolean isNull(){
        return nula;
    }
}

ou

class MinhaEntidade implements EntidadePersistida {
    // algumas omissões por simplicidade

    boolean isNull(){
        // codigo que avalia campos para ver se é nulo
        // ATENÇÃO: id da entidade é nula sempre que ela ainda não foi salva, o que não serve para o teste de isNull!!!!!
    }
}

Dessa forma, sempre que fosse ser retornado null para uma entidade, retornamos uma entidade que retorne true para o método isNull, evitando o NullPointerException.

Pode parecer mais trabalhoso criar assim, mas é muito pior tem que encontrar o maldito código que retorna nulo e não deveria, ou checar em tudo que é lugar se o maldito valor é null!!!!!!!

Vida longa e próspera!


Ecocash na mídia

Olá pessoal!

A pouco tempo atrás o projeto EcoCash despontou nas mídias! Saíram 3 reportagens sobre ele: no canal de notícias da CAIXA, no site softwarelivre.org, no Correio do Povo (jornal de Porto Alegre/RS), e na Istoé Dinheiro.

Não podemos esquecer que YouTube também é mídia, e lá estamos nós também!

Segue abaixo os links para as notícias:

Faça você também, divulgue o projeto e ajude nessa ação educacional em favor da reciclagem e do meio ambiente. Nosso futuro depende disso! Precisamos estar conscientes do que fazemos e das consequências para hoje e amanhã. O futuro não está nas nossas crianças, mas sim em nós! Nós devemos prepará-las para o futuro que deixamos a elas!

EcoCash no Correio do Povo - 14/07/2014 - Página 15

EcoCash no Correio do Povo – 14/07/2014 – Página 15

Até mais e obrigado pelos peixes!


EcoCash andou de novo: Vacaria!

Olá pessoal!

Depois do EcoCash ter sido exposto no Acampamento Farroupilha Especial da Copa, ele voltou a se mover! A E.M.E.F Juventina Morena de Oliveira de Vacaria/RS, está usufruindo dos benefícios educacionais do equipamento!

Dia 07 de agosto foi realizada uma cerimônia de recepção do EcoCash pela escola, onde foi apresentado o projeto e o equipamento. Ele deverá ficar até outubro na escola para permitir que os professores e alunos desfrutem dos recursos disponíveis, tais como vídeos educativos de diversas matérias, incluindo matemática, ciências, tradição gaúcha, reciclagem, além de textos e uma Wiki integrada!

Acompanhe o nosso projeto, assine nosso canal RSS!

Ps.: E.M.E.F = Escola municipal de Ensino Fundamental

Isso é tudo pessoal!


EcoCash no Acampamento Farroupilha da Copa!

O juíz apitou! Bola na quadra! E gol de placa no Acampamento Farroupilha especial da Copa!

Pra quem não sabia ou não pode ver ainda, pra quem não foi no FISL15 (a maioria das pessoas), chegou um nova oportunidade de ver! Você não pode perder!

A partir do dia 12/06, dia de início da Copa 2014 no Brasil, em Porto Alegre (uma das cidades sedes), aomtecerá o Acampamento Farroupilha especial da Copa. A CAIXA estará marcando presença no local, mas mais importante, estará em esposição o EcoCash!

Durante o FISL15, ele foi apresentado, com os seguintes recursos:

  • Depósito de latinhas com ranking diário e total
  • Wikipedia embarcada com suporte a pesquisas
  • Vídeos didáticos:
    • TV Escola: Matemática, Física, História, etc
    • Alumínio: origem, uso e reciclagem
    • Indíginas: um pouco sobre os Índios Guaranis, homenageados do projeto, por serem uns dos precursores da responsabilidade ambiental.

Agora no acampamento, aproveitando a temática farroupilha, temos os seguintes novos recursos:

  • Vídeos sobre a tradição gaúcha (para baixinhos e altinhos rsrsrsrsrs)
  • Textos (sim, textos) sobre a Semana Farroupilha
  • Vídeo com os principais pontos turísticos de Porto Alegre

Então, não perca a oportunidade de conhecer o projeto. Apareça e comente!

Até mais e obrigado pelos peixes!


Estatísticas EcoCash – FISL 15

Olá Pessoal

Antes tarde do que nunca!

Segue aqui as estatísticas do EcoCash no FISL15!

Número de depósitos:
391
Total de latinhas depositadas:
794
Maior depósito
31
Depósitos por dia
32 – 07/05/2014
62 – 08/09/2014
200 – 09/05/2014
97 – 10/05/2014
Quatidade depositada por dia
51 – 07/05/2014
89 – 08/09/2014
328 – 09/05/2014
326 – 10/05/2014

Quem mais depositou no total (soma de todos os depósitos):

  1. 140 latinhas – Jaqueline, 1993-12-07
  2. 50 latinhas – Hobbit, 1998-08-03
  3. 23 latinhas – Saiane, 1996-01-08
  4. 23 latinhas – Jaque, 1962-09-21
  5. 20 latinhas – Vera, 1962-10-04

Quem mais depositou de uma só vez:

  1. 31 latinhas – Jaqueline, 1993-12-07
  2. 23 latinhas – Saiane, 1996-01-08
  3. 21 latinhas – Jaque, 1975-06-13
    21 latinhas – Jaqueline, 1993-12-07
  4. 20 latinhas – Vera, 1962-10-04
    20 latinhas – Jaqueline, 1993-12-07
    20 latinhas – Jaqueline, 1993-12-07
    20 latinhas – Jaqueline, 1993-12-07
  5. 14 latinhas – Paulos, 1975-10-22
    14 latinhas – Robson, 1972-03-29

Ao infinito e além!


Libra – novo projeto de software para o EcoCash

Olá pessoal

Agora o software do EcoCash se chama oficialmente Libra. O repositório no GitHub está criado, e em breve estarei colocando código recém tirado do forno ali.

O novo projeto possui licença baseada na GPL, mas não permite uso comercial e obriga forks públicos a fazerem pull requests, a fim de maximizar a evolução deste projeto. Caso alguém tenha alguma restrição quanto às condições da licença, favor entrar em contato para melhorarmos a licença ao máximo.

Isso é tudo pessoal


Instalar o S4A no Ubuntu 14.04 amd64 (linux 64bits)

Olá Pessoal

O FISL 15 foi maravilhoso! Aproveitei bastante, e aprendi muito, principalmemte sobre Arduino. Pra quem não sabe, Arduino é uma placa de prototipação de circuitos de especificação aberta. Existem IDEs disponíveis para várias plataformas, incluindo Linux. Para mais informações sobre arduíno, consulte http://arduino.cc.

Participei de uma oficina chamada S4A. O S4A é uma aplicação onde se pode programar o Arduino usando blocos de arrastar e soltar. É super simples e divertido! Mas, infelizmente descobri que o pacote .deb (instalador do programa para Debian e seus derivados) funciona somente em distribuições 32bits, devido a um problema de dependência com o pulseaudio. Tentei resolver o problema de dependência mas não fui bem sucedido. =(

Logicamente, pesquisei um pouco na internet, e achei uma dica: use a VM do Scratch para rodar o S4A.

Seguinte essa dica, foi sucesso 100%! =D

Então aqui vai: como rodar o S4A no Ubuntu 14.04 amd64

Pra começar, e pra quem não sabe, o S4A é Scratch for Arduino, ou seja, uma modificação do Scratch original para trabalhar com o Arduino. O Scratch é escrito em Smaltalk, assim como o S4A. Smaltalk é um dos antecessores do Java. É uma linguagem compilada que precisa de uma máquina virtual para rodar. A máquina virtual disponibilizada com o Scratch é a Squeak. Assim como o java precisa da JVM, o Smaltalk precisa do Squeak. Assim como em Java rodamos arquivos .jar, em Smaltalk rodamos arquivos “.image”.

O Scratch está disponível no repositório, assim como a IDE padrão do arduíno. Então, para instalá-los no Debian ou seus derivados, como o Ubuntu, basta dar o comando:

sudo apt-get install scratch arduino

Para outras distribuições que usam o yum no lugar do apt-get, como o Fedora, entre outros, use o yum no lugar do apt-get. Quualquer problema, deixe um comentário que tentaremos resolver juntos….

Após isso feito, baixe o S4A, para linux (.deb). Esse é uma arquivo tipo ZIP. Descompacte-o onde você quiser. Você verá que haverá uma estrutura de pastas, onde o arquivo S4A.image estará na pasta usr/lib/s4a/. O squeak deverá estar disponível diretamente na linha de comando, mas não se não estiver, ele estará na seguinte pasta: /usr/lib/squeak/<versao>/squeakvm. No meu caso a versão é 4.10.2-2614, então o caminho completo ficará: /usr/lib/squeak/4.10.2-2614/squeakvm.

Vamos então rodar o dito cujo S4A

Suponhamos que você baixou o S4A na pasta Downloads, e que o arquivo .deb se chama S4A15.deb. Quando você descompactar, deverá ser criada a pasta S4A15, dentro de Downloads. Sendo assim, juntando tudo que eu falei até agora, teríamos as seguintes 2 linhas de comando possíveis:

squeak Downloads/S4A15/usr/lib/s4a/S4A.image

ou

/usr/lib/squeak/4.10.2-2614/squeakvm Downloads/S4A15/usr/lib/s4a/S4A.image

Caso você queira um script de inicialização para usar para o S4A, mova a pasta S4A15 para /opt e renomeie-a para s4a. O script necessário para iniciar é baseado no próprio script contido no pacote baixado, na pasta usr/bin:

squeak 
 -plugins /opt/s4a/usr/lib/s4a/Plugins 
 -vm-sound-pulse 
 /opt/s4a/usr/lib/s4a/S4A.image "${@}"

Por hoje é só. Qualquer coisa, deixe um comentário ou entre em contato comigo (opção contato no menu).

Ao infinito e além!


C2Al no FISL 15!

Olá pessoal.

Diretamente do FISL 15, muita coisa boa acontecendo, e o mais novo projeto sendo apresentado:

C2Al: Cash Captador de Latinhas de Alumínio

Em parceria com a CAIXA, a Perto e o Porjeto Pescar, a Azanonatec, a ONG Moradia e Cidadania, entre outros, estamos divulgando a primeira versão funcional do reaproveitamento de um ATM vandalizado! Após ter sido arrombado com massarico, o equipamento foi recuperado e transformado em um recolhedor de latinhas de alumínio para reciclagem.

O software traz vídeos educativos embarcados, formulário de depósito e consulta de ranking, relatório de depósitos, Wikipedia em português embarcada usando o Kiwix.

Acompanhe aqui a evolução do projeto, bem como links para vídeos, códigos e esquemas.

O projeto foi escrito totamente em Java, atualmente rodando em cima de um Ubuntu 12.04 Precise Pangolin.

Em breve o código fonte será liberado no github, bem como esquemas do detector de latinhas.

Até mais e obrigado pelos peixes