Quando x + 1 == x (ou mais uma razao pra nao usar float/double)

29 de Maio de 2008 @ 08:57 por Michael Nascimento Santos

O melhor livro técnico que comprei nos últimos tempos foi o Java Puzzlers, que inspira esse post. E digo isso nem tanto pelos corner cases obscuros do Java que você fica conhecendo ao ler o livro (que são divertidíssimos e assustadores ao mesmo tempo) e sim pelos princípios de design que se pode extrair dele. Fortemente recomendado.

Um dos puzzlers do livro mostra um problema com float e double que eu despercebi por todos esses anos, já que não uso esses tipos pra nada. Código como:

float f1 = 16777216f;
float f2 = f1 + 1;
System.out.println(f1 == f2);

imprime true. Sim, true, você não leu errado. O erro na representação da parte fracionária, na verdade, não está limitado a ela; ele atinge a parte inteira e vai ficando mais grave à medida que o número cresce. Com números maiores, você pode somar 50, 100 ou mais e simplesmente ver o valor permanecer o mesmo, porque o tipo de dado não permite representar esses valores.

Eu particularmente achava que o MAX_VALUE e o MIN_VALUE ocorriam justamente antes do erro se manifestar na parte inteira, mas pude comprovar que não. Na verdade, o padrão IEEE 754 dita que isso seja assim, o que significa que toda linguagem que suporta tipos flutuantes segundo esse padrão vai apresentar o mesmo comportamento - que em tese não é um bug, mas uma limitação esperada do design.

Obviamente existem situações específicas em que estes tipos de dados são apropriados e/ou podem-se utilizar técnicas para minimizar ou compensar o erro de representação. Para a maioria das aplicações do mundo, o uso de BigDecimal - ou semelhantes, em outras linguages - é basicamente obrigatório.

Dada a aplicabilidade limitada desses tipos de dados, acho que talvez as linguagens que suportem float e double deveriam requerer que os tipos fossem explicitamente importados, para garantir que o desenvolvedor pelo menos tivesse que fazer esforço pra obter a arma antes de atirar no próprio pé…

Rapidas

29 de Abril de 2008 @ 16:10 por Michael Nascimento Santos
  • A JSR-310 está indo bem. Estamos desenvolvendo a RI e o TCK de forma aberta através do site do projeto no java.net. Muitas coisas já estão plenamente funcionais e estáveis e um Early Draft se aproxima. Contamos com a sua participação!
  • A release 3.1 do genesis deve sair nos próximos dias. Nenhum bug novo foi encontrado após a 3.1-RC2. Em breve, atualizaremos o roadmap também.
  • A sala da minha palestra com o Stephen no JavaOne encheu e vamos repetir a palestra na sexta :-)
  • Fui indicado ao JCP Awards na categoria Participant of the Year. Se vou ganhar ou não, vamos descobrir na próxima terça
  • No sábado da próxima semana, vou participar do Scala lift off , que reunirá os grandes nomes do Scala e da comunidade. Se você ainda não conhece a linguagem, recomendo.
  • Estamos contratando na Summa. Caso tenha interesse, é só me mandar o cv. Se eu te conheço mas você acha que eu talvez não lembre exatamente de você, basta refrescar minha memória ;-)

Local classes em Java

5 de Março de 2008 @ 13:41 por Michael Nascimento Santos

Acho que um dos recursos mais desconhecidos da linguagem é a existência das local classes. Local classes são classes definidas dentro de métodos ou blocos em geral, algo como:

public void umMetodo() throws InterruptedException {
    class LocalRunnable implements Runnable {
       private UmBean umBean;

       public void run() {
           umBean = variavelPrivada.fazAlgoLento();
       }

       public UmBean getUmBean() {
          return umBean;
       }
    }

    LocalRunnable lr = new LocalRunnable();
    Thread t = new Thread(lr);
    t.start();

    try {
       t.join();
    } catch (InterruptedException ie) {
       throw ie;
    }

    return lr.getUmBean();
}

No exemplo acima, criamos uma implementação de Runnable que permite obter, após a execução do método run(), o valor computado de uma operação lenta (ok, fora permitir que a thread atual possa ser interrompida enquanto o método executa, não há lá grandes vantagens em criar uma thread para esperar imediatamente pelo seu resultado).

Muitas vezes cria-se uma inner class “nomeada” apenas para ter acesso a alguns métodos adicionais, visto que não é possível chamar normalmente um método de uma anonymous inner class. As local classes resolvem justamente esse problema, como o exemplo acima demonstra.

E você, conhecia esse recurso? Mais informações na JLS.

O infame bug de self-assignment / atribuição a si mesmo

4 de Março de 2008 @ 18:16 por Michael Nascimento Santos

Acabo de ajudar o pessoal do cliente a resolver um erro que é comum em linguagens de programação e que me levou a refletir um pouco.

No caso, havia uma trigger PL/SQL (Oracle 9.x.y.z) em que havia uma variável qualquer, que chamaremos aqui de exemplo. Havia também uma tabela qualquer com uma coluna EXEMPLO - levando em conta que os nomes não são case-sensitive; apenas reflito como estavam sendo usados no código. Era feito um select semelhante a:

SELECT  INTO 
FROM TABELA T
WHERE T.EXEMPLO = exemplo

E ninguém conseguia entender qual era o bendito erro. Bem, para o Oracle, o where acima é a mesma coisa que:

WHERE T.EXEMPLO = T.exemplo

também conhecido por, hmmm, true. Logo, o where não fazia nem de longe o que o desenvolvedor esperava. Foram perdidas umas 3 horas até que me contaram o problema e eu o detectei imediatamente no código - obviamente, porque também já apanhei disso antes.

A mesma coisa acontece em Java quando uma variável local tem o mesmo nome de uma variável de instância e se esquece de usar o this na atribuição. Qualquer pessoa com um pouco de experiência na linguagem já viu esse erro na vida.

Embora em Java as IDEs detectem esse tipo de erro, eu até hoje não entendo por que essas operações de self-assignment não são reportadas como erro de compilação. Alguém aí tem alguma boa razão para o compilador aceitar isso?

genesis 3.1-RC1

3 de Março de 2008 @ 13:05 por Michael Nascimento Santos

No final da semana passada, lançamos o genesis 3.1-RC1. Essa versão possui uma série de correções em relação a 3.0, além de algumas novas funcionalidades.

O genesis é um framework que facilita o desenvolvimento desktop (Swing, SWT e Thinlet) usando um modelo de programação baseado em JavaBeans e anotações que permite ao desenvolvedor focar na lógica de apresentação ao invés de lidar com a API gráfica.

A adoção no Brasil tem sido significativa: o volume de tráfego na lista de usuários em português mostra o aumento da popularidade do framework, e ainda há perguntas postadas em fóruns/comunidades como o SouJava e o GUJ. Esperamos esse ano divulgar mais o projeto e continuar trabalhando para que ele melhore ainda.

Mais informações sobre as novidades podem ser encontradas nas release notes.

Tirando a poeira

30 de Janeiro de 2008 @ 22:38 por Michael Nascimento Santos

Meu Deus, seis meses sem blogar? Pois é, sempre acontecem essas coisas.

Bem, tomei vergonha na cara e subi as palestras do JavaOne e do JustJava do ano passado. Tenho trabalhado bastante no genesis - a release 3.1 está se aproximando -, na JSR-310 - um Early Draft deve sair em breve - e experimentado muito com Scala, linguagem da qual pretendo falar bastante aqui no blog em breve.

Bem, espero que volte a postar mais aqui em breve. Ou então, até 2009 ;-)

Palestras no JustJava 2007

16 de Julho de 2007 @ 11:28 por Michael Nascimento Santos

Vou apresentar 3 palestras no JustJava 2007:

  • 02/08, 11:30 - “Closures: Modernizando a linguagem Java”, com o Rodrigo Kumpera, vulgo louds
  • 03/08, 18:00 - “Genesis 3.0: Swing, SWT e Thinlet mais simples do que nunca”, com o Michel Graciano
  • 04/08, 13:30 - “JSR-310: Uma nova forma de lidar com datas e horas”, com o Fábio Kung

A primeira faixa de preço promocional se encerra nesta sexta, 20/07, então não perca tempo e se inscreva!

Palestra do JustJava de 2005

13 de Julho de 2007 @ 11:55 por Michael Nascimento Santos

O Claudio Miranda acaba de colocar no ar um vídeo sobre a palestra que fiz com o Allan em 2005 sobre o genesis.

Embora várias coisas tenham mudado (os planos para o 3.0, o suporte Swing/SWT e afins), no geral ainda vale a pena:



Configurando o projeto vazio do genesis no NetBeans

11 de Julho de 2007 @ 16:11 por Michael Nascimento Santos

Uma das principais dúvidas que as pessoas têm ao começar a usar o genesis é como configurar o projeto vazio no NetBeans. Por isso mesmo, fiz o seguinte demo no Wink que demonstra como fazer isso:





Comentários são bem-vindos!

genesis 3.0

11 de Junho de 2007 @ 13:58 por Michael Nascimento Santos

Após 2 anos e meio de desenvolvimento, o genesis 3.0 acaba de ser lançado.

Por que você deveria usar o genesis no seu projeto desktop?

Saiba mais informações no site do projeto.