5 de agosto de 2013

Infectado por exceções

Acredito que códigos infectados por exceções sejam ruins. Imagine o seguinte código inofensivo:

public static Foo newFoo(int bar) {
  switch (bar) {
    case 1: 
      return new FooOne();

    case 2: 
      return new FooTwo();

    default: 
      throw new IllegalArgumentException("invalid bar code: " + bar);
  }
}

Você utiliza ele no meio da sua regra de negócio, com a maior tranquilidade. O código compila e tudo:

public static List<BazFoo> getAllBazFoo() {
  List<BazFoo> result = new ArrayList<>();
  List<Baz> allBaz = BazDAO.getAllBaz();
  for (Baz baz : allBaz) {
    int id = baz.getId();
    int bar = baz.getBar();
    Foo foo = Foo.newFoo(bar);
    BazFoo e = new BazFoo(id, foo);
    result.add(e);
  }
  return result;
}

O problema é que a chamada Foo.newFoo(bar) pode lançar um IllegalArgumentException e quando isto ocorrer você não terá pista nenhuma de qual Baz está com a informação inválida.

Para tratar isto e tornar a mensagem mais útil, temos que lembrar de adicionar um try/catch no código:

public static List<BazFoo> getAllBazFoo() {
  List<BazFoo> result = new ArrayList<>();
  List<Baz> allBaz = BazDAO.getAllBaz();
  for (Baz baz : allBaz) {
    int id = baz.getId();
    int bar = baz.getBar();
    Foo foo;
    try {
      foo = Foo.newFoo(bar);
    } catch (IllegalArgumentException e) {
      throw new IllegalArgumentException("invalid baz: " + id, e);
    }
    BazFoo e = new BazFoo(id, foo);
    result.add(e);
  }
  return result;
}

Adicione várias camadas de abstração à sua aplicação e pronto: espagueti sabor excepcional. Ao adicionar exceção em algum ponto, você terá que revisar toda a pilha de abstrações que você tem e garantir que a exceção não faça mal a ninguém e que tenha uma mensagem útil para futuras manutenções.

Haskell resolve boa parte da necessidade de exceções com retornos que simbolizam falhas, e.g. Maybe e Either, e o uso de Monad elimina a necessidade de verificar os retornos a cada passo.

Porém, ainda existem exceções em Haskell, por quê? Não consigo entender o motivo para preferir exceções ao invés de retornos especiais. Em quais situações usar exceções é melhor? Mais me parecem um goto modernizado.

6 de julho de 2013

Livro: Code Simplicity

Acabei de ler o livro "Code Simplicity: The Fundamentals of Software" (em português: "As Leis Fundamentais do Projeto de Software").

O autor tenta criar uma ciência em cima do desenvolvimento de software. São cerca de 90 páginas que falam sobre detalhes importantes desta engenharia sem mostrar nenhuma linha de código.

Entre os assuntos citados pelo autor, o que mais me impressionou foi a fórmula do custo de uma alteração em um software.

Esta fórmula, quando aplicada ao tempo, deixa claro que o valor futuro e o custo da manutenção de uma alteração tem um peso muito maior do que o custo e o valor imediato gerado por uma alteração. Pois com o passar do tempo, o valor investido para manter a funcionalidade supera muito o valor investido inicialmente para codificá-la. Não vou entrar em muitos detalhes, se ficou curioso: vá ler o livro.

Foi uma leitura muito prazerosa. Apenas fico triste pois cheguei neste livro por um acaso, não recebi nenhuma indicação. Meu sentimento é que se tivesse lido este livro antes, teria poupado boa parte das frustrações que vivi nestes anos como desenvolvedor. As explicações detalhadas do autor parece que se encaixam perfeitamente com os sentimentos e realizações que presenciei escrevendo e mantendo código.

Deixo aqui minha indicação para todos que trabalham na área de software: você precisa ler este livro! Independente de ser desenvolvedor ou não, você terá uma base muito melhor para tomar decisões que afetam o seu produto.

Se você já leu, deixe seus comentários sobre o que achou.

12 de junho de 2013

Cantinho da Criança

Está pronto e publicado no Google Play o jogo infantil Cantinho da Criança!

O objetivo do jogo é ajudar crianças a reconhecer algumas coisas do dia-a-dia, auxiliando no aprendizado e no desenvolvimento. Indicado para crianças de 0 a 3 anos.

Colocamos imagens bem coloridas e uma música bem animada para ensinar e divertir ao mesmo tempo.

Se tiver filhos nessa faixa etária, não deixe de conferir: Google Play - Apps by Haeres

5 de junho de 2013

Abrace Android

Já faz um tempo que não escrevo neste blog. As minhas aventuranças no mundo Haskell pararam um pouco depois do último post que fiz ("C, C++, Java, Haskell?").

Dediquei um bom pedaço deste tempo ausente para tentar fazer um jogo em C. Tive um bom começo: fiz um personagem se movimentar, pular e colidir com outros objetos. Comecei a perceber onde estava me metendo quando estas perguntas surgiram na minha mente:

  • Como vou distribuir meu jogo?
  • Como vou lançar uma atualização?
  • Como vou comercializar?

Neste momento estava com uma conexão carinhosa com o projeto e foi difícil aceitar que estas dificuldades poderiam ser maiores do que meu esforço disponível. Passada esta fase de aceitação, decidi que precisava tirar todas estas preocupações da cabeça para conseguir me dedicar ao desenvolvimento do jogo. Para isto precisava de uma plataforma que me oferecesse todos os itens que coloquei na lista acima.

Android

Escolhi a plataforma Android por conseguir acesso a um ambiente de desenvolvimento de forma mais fácil, pois poderia continuar utilizando meu notebook rodando Windows para programar e realizar testes no meu celular Samsung Galaxy 5. Sem chance de investir em um ambiente para iOS no momento.

Para garantir que a plataforma atendia a todos os itens que listei acima, fiz o processo do começo ao fim:

  1. Criei um aplicativo de exemplo
  2. Testei no meu celular
  3. Publiquei o aplicativo (Como vou distribuir meu jogo?)
  4. Alterei algumas coisas e lancei atualizações para ele (Como vou lançar uma atualização?)
  5. Criei uma versão free com propagandas e uma paga sem propagandas (Como vou comercializar?)

O resultado disto tudo foi muito agradável. Agora não me restam dúvidas sobre o ambiente Android, basta continuar meu aprendizado na plataforma e o desenvolvimento do projeto em paralelo. Espero que em breve eu consiga postar no blog um link para o resultado do projeto publicado. :)

20 de janeiro de 2013

C, C++, Haskell, Java?

Estou empolgado e agoniado com meu aprendizado sobre OpenGL. Ao mesmo tempo em que aprender OpenGL me deixa muito satisfeito, também me deixa inquieto: dediquei muito tempo aprendendo Haskell e fui envolvido de uma forma a gostar muito da linguagem e da comunidade. Porém, fazer algo em OpenGL se mostrou muito difícil e até mesmo solitário. Existem pouquíssimos materiais sobre isso e a maioria deles estão obsoletos.

Tive que largar Haskell por um tempo e religar os neurônios da linguagem C para aprender o fluxo das versões mais modernas do OpenGL, com shaders e buffer objects. O motivo foi simples: não consegui fazer nada funcionar em Haskell e não tive certeza se a culpa era minha ou das bibliotecas que utilizava.

Pois bem, fazer uma câmera se movimentar em um mundo 3D em C também não foi nada fácil. Mas com a abundância de material, consegui deixar funcionando de uma forma que me deixou bem satisfeito.

Decidi então voltar para Haskell e aplicar este conhecimento que acabei de conquistar.

Que trabalheira! Fazer tudo se encaixar da maneira certa e com os tipos corretos me fez suar algumas camisas. Se não fosse tão teimoso, não teria conseguido. Tive que trocar o pacote OpenGL pelo OpenGLRaw pois o pacote OpenGL não tem binding para "glUniformMatrix*"; também troquei o GLFW pelo GLFW-b porque o primeiro dependia do pacote OpenGL.

Recentemente li um artigo no InfoQ questionando se a linguagem C ainda era útil. Me fez pensar em muita coisa, inclusive em abandonar definitivamente Haskell e voltar às origens: ponteiros, gerenciamento de memória manual, strings cabulosas, ...

Talvez seja porque sou muito novo neste mundo, mas me sinto meio improdutivo programando em Haskell. A impressão que tenho é que, a menos que seja algo muito bem consolidado e utilizado por muitas pessoas da comunidade, muito tempo será gasto atrás de bibliotecas que normalmente são apenas um binding para uma escrita em C. Quando não for isto, só para ter uma breve ideia do que a API de uma biblioteca faz, acabo lendo alguns papers relembrando o que são Functors e Monads (para entender Arrows acho que vou precisar comprar um livro!).

Entender ponteiros e gerenciamento de memória em C também foi difícil. Mas naquela época eu era um jovenzinho no mundo da programação, meu conhecimento era muito limitado, se baseava muito em bater no código até que ele fizesse o que eu queria. Agora não consigo mais aceitar fazer alguma coisa sem entender o que estou fazendo.

Eu lembro que tive bons motivos para trocar C por Java. Depois de passar um tempo utilizando Java, vejo também as partes negativas da linguagem. Meu trabalho de conclusão da graduação foi dedicado a evidenciar os motivos desta troca e do futuro promissor de linguagens como Haskell.

No final das contas, acredito que esta pseudo-decepção acontece com toda linguagem em que você dedica bastante tempo para aprendê-la. A propaganda e os primeiros passos são maravilhosos. Parece que você descobriu um novo mundo onde todos são ricos e podem desfrutar de todas as coisas boas. Com o tempo você percebe que não é bem assim: cada escolha que a linguagem fez significa pontos positivos e negativos para nós usuários. Foi assim com C, Python, Java e agora com Haskell.

Java escolheu uma abordagem orientada a objetos: mesmo que seja uma função estática ou uma variável global, será necessária a roupagem de uma classe para acomodar este código. Haskell escolheu o funcional puro: mesmo operações que envolvam I/O recebem a roupagem de um monad.

Não que isto seja ruim. A utilização de monads para modelar computação sequencial foi uma grande descoberta que proporcionou a criação de inúmeras soluções. Estas escolhas trazem pontos positivos e negativos. Só devemos ter cuidado com o purismo extremo para não criar aberrações (e.g. Singleton).

Enfim, estou agoniado pois não sei o que escolher:

  • C me parece flexível mas com as complexidades que não quero ter. C11 parece solucionar algumas coisas (e.g. <threads.h>), mas o GCC ainda não suporta;
  • Sou bem produtivo em Java mas o overhead obrigatório e a necessidade de ter uma JVM me irritam profundamente;
  • C++ ainda é uma incógnita para mim, se for para ir neste nível ainda prefiro utilizar C. Java já me fez ver os motivos para dizer não à O.O. Por outro lado, boa parte de quem utilizava C está indo para C++, inclusive o GCC está utilizando C++. As bibliotecas disponíveis para C++ também pesam bastante (e.g. GLM, Boost);
  • Haskell é minha linguagem da vez mas está começando a me incomodar um pouco, sentimento de improdutividade me deixa muito tenso. Talvez precise dedicar mais tempo para que isto passe. Não sei se este esforço irá valer a pena ou poderia ser melhor aproveitado aprimorando meus conhecimentos em outra linguagem.

A diferença de desempenho entre C e Haskell não me preocupa muito, pois não vou escovar bits para ter um bom desempenho tão cedo.

No final das contas, a opinião mais correta sempre é: depende do projeto, escolha a melhor linguagem para o seu projeto. Pois bem, não tenho projeto nenhum, mas quero me aprofundar no desenvolvimento de jogos.

E agora?

9 de janeiro de 2013

DuDuHoX com som: OpenAL

Trabalhar no DuDuHoX está cada vez mais difícil. Já pensei em desistir em alguns problemas que tive, seja com código ou com bibliotecas.

Colocar animação no jogo foi muito complicado. Porque o motor do jogo não tem estados intermediários em que o personagem está indo de uma casa para outra. O estado do jogo só permite que o personagem ocupe uma casa e não metade de uma e metade de outra.

Minha solução para isto foi colocar a informação de animação no código da interface gráfica (OpenGL). Após pressionar alguma tecla que movimente o personagem, o motor do jogo já estará no estado novo completo, mas a interface não aceitará mais nenhuma entrada enquanto não terminar de exibir a animação de movimentação.

Outro grande problema que tive foi quando decidi colocar sons no jogo. Meus objetivos são: música de fundo e sons posicionais. A biblioteca que achei para isto foi a OpenAL. Ela é feita em C mas existe o pacote Haskell que faz o binding.

Mas, nem tudo é tão bonito. Instalar a biblioteca OpenAL no Windows foi um tremendo caos. Foi uma tarde inteira tentando fazer isto. Quando finalmente consegui instalar, percebi que também iria precisar da biblioteca ALUT. Esta não foi tão difícil de instalar, porém, ocorriam erros de link durante a compilação. Felizmente encontrei um bug reportado para o GHC que tratava exatamente do meu problema: Ticket 1243. Depois de aplicar o patch, tudo funcionou.

Fiz uma música no OpenMPT, desenhei o personagem no GIMP e coloquei tudo dentro do jogo.

Apesar das dificuldades, estou muito feliz com resultado que estou obtendo em fazer o DuDuHoX em Haskell. Decidi gravar um gameplay com o CamStudio e compartilhar com vocês através do YouTube: