Java não é tão ruim assim…

Java é uma linguagem grande, famosa, e muito usada. Mas não é, digamos, “charmosa”. Não só eu, mas muita gente reclama que ela é inflexível, sem-graça, e demora a adotar recursos que as concorrentes têm faz tempo (em termos de recursos da linguagem, o C# da Microsoft evoluiu muito mais rápido).

Dependendo do gosto do programador, uma linguagem charmosa seria Python (eu gosto, é quase um pseudocódigo executável), alguma variante de Lisp (os fãs são dedicados, mas eu nunca consegui me adaptar), Ruby (superficialmente lembra Python, é muito flexível, mas sintaticamente é mais complexa), Lua (minimalista e elegante, quase um pseudocódigo executável, como Python), ou até C (reina tranqüilo no seu nicho de infraestrutura, bom para quem gosta do “baixo nível”), C++ (ótimo poder de abstração sem perder as capacidades do C).

Mas aí eu parei para pensar mais friamente: exceto por alguma inveja aqui e ali do C#, Java tem suas qualidades.

Comparando com C e C++:

A tipagem estática e sintaxe simples permite navegação e refatoração fáceis com ferramentas de desenvolvimento. Compare com C++, onde ferramentas de “autocompletar” facilmente falh(av)am porque não entendem as milhares de macros e templates a serem processados nos headers.

O ambiente gerenciado permite reflexão, serialização e stack-traces bem úteis. Já em C e C++, bah… Nessas linguagens, se tiver um core dump para descobrir por que o programa morreu, o programador já acha excelente! Java tem strings Unicode também; em C/C++ tem que correr atrás de alguma lib pra isso.

Em Java até precisa escrever o nome da classe 2 vezes ao instanciá-la, mas diferente de C, C++, e Objective-C, não é necessário ter 2 cópias da assinatura de cada função (nome e parâmetros) uma no cabeçalho e outra na implementação (e a instanciação em Obj-C é pior, pelo que li: Classe* obj = [[Classe alloc] init];). Depois de um tempo longe do C e C++, tinha até esquecido essa incomodação da replicação entre .h e .c.

Em Java dá para deixar outras pessoas mexerem no seu código sem (muito) medo de estragarem seu cuidadoso gerenciamento de memória e ponteiros, depurado com muito suor (entretanto, talvez esqueçam de fechar a conexão com o banco…).

Comparando com as linguagens dinâmicas (Python, Ruby, etc.):

Java é pesado e consome uma enorme quantidade de memória, mas apesar disso, tem o potencial de ser mais rápido que qualquer linguagem dinâmica.

Java é estável, a linguagem não muda radicalmente a cada ano (nem a cada dois anos, talvez mude algo depois de três anos). Dá para começar e terminar seu projeto tranqüilo sem chegar no fim com aquela sensação de estar usando uma versão obsoleta da linguagem.

A questão de reflexão e bibliotecas deixa de ser uma vantagem do Java (como era em relação ao C++), mas em compensação, em Java é muito mais fácil criar interfaces razoáveis e autodocumentadas (por causa das declarações de tipos) entre módulos diferentes da aplicação. Em Python, é um vale tudo: se algum espertinho ou distraído resolver adicionar um atributo de objeto chamado tmp35 no if mais escondido do arquivo A e acessá-lo num tratador de exceção que quase nunca é executado no arquivo B, a linguagem vai aceitar; o atributo vai existir ou não dependendo do if, e o tratador de exceção pode ter um comportamento diferente dependendo disso.

Você queria ter uma boa mensagem de erro mas o próprio tratador de exceção pode jogar uma exceção por causa de uma variável não encontrada, enquanto que em Java um problema desses não passaria do estágio de compilação. Em Java, muito mais problemas são detectados logo na compilação, ou pelo próprio editor que já compila o programa em segundo plano. Geralmente dizem que basta usar testes unitários com as linguagens dinâmicas, mas não sei… Precisaria de muito mais testes (escrever os testes é complicado!), e não daria para esquecer de testar os casos mais excepcionais, já que vários tipos de erro de digitação só são detectados quando o programa executa tal linha. Ao fazer uma grande refatoração numa linguagem com tipos mais estritos, pelo menos temos uma garantia que não deixamos nenhum pedaço do código horrivelmente inconsistente, né?

Comparando com outras linguagens:

Apesar de verbosa, a linguagem Java vem do C++, com práticos atalhos como i++; i += 2; a = b = c = 0; declaração de variáveis em qualquer local da função; operador ternário ?:; e ganhou um for-each bem antes do C++. Imaginem se Java viesse do Pascal, com variáveis declaradas só no começo das funções, i := i + 1; e os horríveis begin e end, que embora teoricamente sejam necessários “apenas para instruções compostas”, acabam sendo necessários quase sempre, porque a linguagem não permite fazer muita coisa por linha (nada de v[i++] = w[j++] = x[k++]).

Anúncios

6 pensamentos sobre “Java não é tão ruim assim…

  1. Alô, Marcus!
    Adoro comparações de linguagens, ahah! :D
    Bem, acho que toda linguagem é uma barganha. Acho que com Java, às vezes fica difícil sacar o que é afinal que você está barganhando.

    Você falou um pouco de sintaxe… Mas cara, estamos em 2013 e Java ainda não ganhou açúcar sintático pra mapas e listas. :-/
    O meu problema com isso não é que seja difícil chamar new HashMap/ArrayList e umas chamadas a put/add, meu problema é que as pessoas ficam encorajadas a criar classes demais, e desencorajadas a usar Map pra passar um parâmetro complexo, por exemplo.
    Em Java, todo mundo acha feio isso (extrapolação do megazorde), no entanto em outras linguagens, se faz isso o tempo o todo.

    Por fim, sobre o runtime, não entendi, você estava dizendo que Java era mais lento que Python e Ruby? Não seria o contrário?

    Tendo dito isso, acho que a parte mais atraente de Java é a que você falou no começo: o ferramental disponível (tooling). Existem muitas ferramentas excelentes para Java, e isso é usualmente o fator que **mais pesa** na escolha duma linguagem pelos desenvolvedores comuns.

    É importante ter boas ferramentas, especialmente quando trabalhando em equipe, mas pessoalmente, acho meio besta as pessoas deixarem de usar uma linguagem melhor, simplesmente porque a IDE favorita não tem autocomplete pra ela. As pessoas ficam mimadas pela ferramenta…

    Acho que uma linguagem melhor dá uma produtividade muito maior do que uma ferramenta melhor, mas as pessoas têm uma certa ilusão de que custa mais caro. Todavia, a realidade é outra: assim como trocar para uma IDE melhor, você perde um bocado de produtividade no início, mas depois que a coisa engrena, o investimento se paga rapidão — e no caso da linguagem, de várias formas diferentes.

    Desculpe o texto comprido, não tive tempo de deixar mais curto! :D

    Falou, cara!
    Abraço!

    • Verdade, a sintaxe de um recurso facilmente define se ele será usado com freqüência ou não. Uma linguagem com maps e tuplas embutidas com sintaxe especial encoraja a criar pequenas estruturas de dados conforme a necessidade. Como Java não tem isso, encoraja a criar classes apenas para conter um par de dados. Poucos usariam um Object[] para isso, embora aconteça às vezes (o JPA retorna List<Object[]> para representar uma lista de linhas quando não se usa uma entidade mapeada).

      Em algum momento do planejamento do Java 8 estava a idéia de criar açúcar sintático para mapas e listas, mas parece que concentraram todos os esforços no projeto lambda (e mesmo assim o negócio está atrasado).

      Quanto ao “peso” do Java, ele realmente é muito mais rápido que Python e Ruby, mas é estranho, sempre tem uma coisinha ou outra que dá a impressão do Java ser pesado. Talvez sejam os antivírus do Windows (já que no Linux essa impressão de lerdeza é bem menor), talvez seja o tempo de inicialização (que eu mesmo testei e vi que um processo pode consumir 20 vezes mais tempo se ele abrir pequenos programinhas em Java se comparado com um programa Java que faça tudo), ou talvez seja o fato que as ferramentas em Java são escritas em Java mesmo, enquanto que as ferramentas que eu uso para outras linguagens são escritas em C. Sei lá.

      • Hmm… Eu apostaria da impressão de peso do Java ser o tempo de inicialização: é realmente uma buesta.

        Chutômetro: acho que é muita IO. Unzipar uma caraiada de jar, com uma caraiada de .class dentro (tem praticamente um .class pra cada classe — inclusive as internas)..!

        • Acho que a quantidade de I/O e o JIT colaboram para a inicialização lenta. Mas se em vez do jar fossem as classes separadas, poderia ser pior: já tentou copiar para um pendrive milhares de arquivinhos e comparar o tempo de copiar um arquivão só zipado? O arquivão vai muito mais rápido!

    • Saiu recentemente no news.ycombinator.com:

      Ele diz que alguns dos motivos para lentidão de linguagens dinâmicas quando comparadas com C são: a impossibilidade de evitar cópias de memória, de pré-alocar um tamanho mínimo quando já se sabe o que vai precisar, e o uso freqüente de hashmaps.

  2. Ahh, só pra constar!
    Uma das coisas que eu acho muito excelente em Java, acho que uma das melhores decisões dos criadores foi: suporte a Unicode obrigatório!
    Isso aí é simplesmente flor de especial! :)

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s