Go With the Flow

novembro 21st, 2009 § 0

A Google tem um poderoso canal de comunicação com os nerds de todo o planeta. Tudo que sai da cabeça desses engenheiros é motivo de burburinho em todo o lugar, até que desapareça tempos depois.

A mais recente invenção dos caras é a GO, uma linguagem de programação de sistemas, compilável, com coletor de lixo e primitivas para concorrência. Em poucos dias, causou vários comentários que, obviamente, se arrefeceram uma semana depois. Mas não vamos deixar essa ausência de comentários abalar este post onde, com apenas meus poucos dias de estudo, mostrarei meus pitacos com relações a aspectos da linguagem que mais se destacam dos demais. (Não mostrarei como montar o ambiente, nem como fazer compilação. Isso você encontra no Google.) » Read the rest of this entry «

A cauda longa das linguagens

agosto 29th, 2009 § 0

Andy Hunt já dizia que nós deveríamos aprender uma nova linguagem a cada ano. É claro que sempre tem uns merdas que citam Malcolm Gladwell (e sua teoria de que se leva 10 anos de prática pra que alguém desenvolva um grande talento (link, link)) para desqualificar a sugestão de Hunt, afirmando que um ano “é muito pouco”. Puro jogo de palavras! Pois não se espera de ninguém ser um fodão na linguagem em que se aventurou. É suficiente apenas um mínimo de entendimento nos princípios e na filosofia da nova linguagem, além da cultura dos principais evangelistas. Um ano é suficiente para ter, sei lá, um quinto de conhecimento que o guru-criador da linguagem tem.

Outros usam também a conhecida citação “programar é difícil” para demonstrar que aprender novas linguagens não vale a pena, já que é contra-senso encarar coisas difíceis todo ano. Discordo, uma coisa é aprender a programar, outra é aprender uma nova linguagem. Programar é um conceito abstrato: transformar uma idéia em solução computacional. Linguagem é concreto: a ferramenta utilizada para por a solução computacional em prática. Confundir programação com linguagem é típico de quem nunca aprendeu mais de uma linguagem.

Aprender uma nova linguagem é útil. Principalmente quando você sai de uma “visão de mundo”, que é apregoada pela comunidade da linguagem, e entra numa outra, completamente diferente. Isso é tão libertador quanto aqueles sortudos viajantes, que andam de país em país; onde, em cada uma, percebe como as pessoas são diferentes e que existe um mundo muito maior do que eles próprios supunham imaginar.

Tudo isso para sugerir duas linguagens da cauda longa: uma é Haskell, linguagem funcional que gera código nativo (com desempenho comparável a C), a outra é Erlang, linguagem também funcional com foco em concorrência e que roda em uma máquina virtual especial para sistemas que não podem cair.

Eu estou aprendendo Haskell e comecei pelo ótimo tutorial Learn You a Haskell for Great Good, escrito pelo esloveno Miran Lipovača. Já Erlang (que eu havia começado a aprender há dois anos atrás, mas parei no meio), pretendo comecar no ano que vem, e irei seguir um tutorial que ainda não li, mas é cria do anterior: Learn You Some Erlang for Great Good, escrito pelo franco-canadense Frederic Trottier-Hebert.

Se você já está de saco cheio da mediocriade dos usuários de Java, vale a tentativa.

A hora e indústria de TI

agosto 24th, 2009 § 0

Bom, já havia falado que havia lido o livro “The Mythical Man-Month”. Hoje vou falar sobre mais algumas coisas sobre o texto.

O autor defende que horas e pessoas não são intercambiáveis, ou seja, não dá para aumentar a equipe e esperar que o produto seja entregue mais rápido. Com mais pessoas, pode ser que seja mais rápido, pode ser que seja a mesma coisa, ou ainda pode ser mais lento que se mantivesse a equipe menor. E foi ainda mais enfático: adicionar pessoas num projeto atrasado, deixa-o mais atrasado.

A razão para esse fenômeno, para muitos ainda contraintuituvo, é que determinadas tarefas são difíceis de serem feitas em paralelo, e quanto mais pessoas, maior o tempo gasto em comunicação entre os membros, em detrimento do trabalho “útil”.

Uma outra coisa que o livro fala é que a diferença de produtividade entre um excelente programador e um mau programador é de 10 para 1. O que significa que nem sempre compensa contratar os piores programadores porque não compensa pelo custo-benefício.

Mas chega a desanimar se comparar o livro com a realidade brasileira. Não se fala na área man-month, man-day, homens-mês ou homens-dia; fala-se simplesmente hora (do tipo: “essa alteração leva tantas horas”), como se a pessoa encarregada em construir o programa simplemente ficasse fora da equação, e o projeto ficasse pronto pela simples passagem do tempo.

Pra piorar: o valor percebido de um software está em quanto satisfez as expectativas do cliente, não em quantas horas foram gastas na construção. Entre uma feature que traz grande satisfação, mas poucas horas, e outra que traz pouca satisfação, mas muitas horas; a última seria economicamente vantajosa pra quem vende horas. (Percebe porque está cheio de consultoria pereba?)

E a razão 10:1 para a produtividade entre o melhor e o pior pode até indicar pra uma empresa de software que vale a pena contratar o melhor. Mas como são raras as empresas sensíveis a esse ponto, essa razão significa simplesmente uma coisa: quem faz muito ganha relativamente pouco e quem faz pouco ganha relativamente muito. Implica que não é vantagem para nenhum programador melhorar seu próprio nível educacional, pois uma eventual reciclarem teria pouco reconhecimento.

E isso é verdade! Acredito que tenha muitos profissionais que não sabem como é um bom projeto de software, seja porque nunca trabalhou num, seja porque nunca se qualificou para tal.

Dá até tristeza ler “The Mythical Man-Month”.

Rails e a bala de prata

agosto 21st, 2009 § 0

Estou quase acabando de ler o livro “The Mythical Man-Month”, aquele que todo líder deveria ler antes de meter os pés pelas mão em projetos de software. O que achei mais interessante não é tanto o fato dele derrubar o “senso-comum” de que um projeto pode terminar mais cedo simplesmente adicionando mais pessoas (isso vai pro próximo post), mas o fato dele enfatizar que não existem balas de prata, ou seja, não existirá nada que faça a construção de software ganhar um incremento gigantesco de produtividade. Inclua aí as IDEs, a orientação a objetos ou o desenvolvimento visual.

Incrivelmente, os caras da nossa área sentem-se como alquimistas, na busca pela tranformação do ferro em ouro. Rails, por exemplo, é ainda visto pelos noobs como um framework que iria trazer incríveis ganhos de produtividade em relação ao Java. Mas quando o cara começa a “pegar mais” nos estudos, percebe uma coisa incômoda: o framework não traz tanto ganho assim! Só-que não traz mesmo! Software é complexo de se fazer, porque você ainda terá de lidar com espectativas de usuários, com facilidade de uso e com facilidade de manutenção, independentemente de qual linguagem utilizada. (Se bobear, talvez seja esse o motivo da adoção de Rails ser fraca: não é produtivo o bastante.)

Mas ignorar Rails por não ser bala de prata é imbecil demais! É a opção, esquisita, das pessoas que só irão sair da zona de conforto quando a verdadeira bala de prata for apresentada diante de seus olhos. Porém, a solução mágica não existe, né? Meu, Rails é mais produtivo, um pouquinho só, e não é em todas as determinadas situações. Ainda assim, vale a pena aprender, pois a proporção entre legais/idiotas é alto entre os “railers”, ao contŕario dos javeiros. E sua cultura de testes é de invejar qualquer um.

Se ainda não conhece, vai atrás e aprenda. Não deixe o conforto pela espera da solução mágica tomar conta de você.

MVC: Supostas perguntas frequentes

junho 29th, 2009 § 4

P. Por que um tópico sobre “supostas perguntas frequentes”?
R. Dois motivos: 1. É incrível a quantidade de gente perguntando as mesmas coisas em fóruns por aí. 2. É incrível gente com anos trabalhando que simplesmente erra feio nesse negócio de MVC. E eu tava pensando em fazer um post épico, como havia feito anteriormente, mas como ainda tá “assando”, resolvi fazer um outro post épico sobre isso daqui.

P. O que é MVC?
R. Háááá! Ainda bem que perguntou, acredita que tem gente que faz cara de conteúdo ao ouvir essas três letras? Enfim, deixa pra lá. MVC é um pattern usado, geralmente, para apresentações visuais de uma aplicação. Por ser pattern, implica que MVC também é uma descrição de uma solução para um problema recorrente; e que também não é uma receita de bolo para ser seguido de olhos vendados. O nome segue a sigla das três “coisas” que a aplicação vai ser dividida:

Model: é como o seu programa seria se o usuário fosse um “über-geek” e pudesse manipular o sistema fazendo simples classes com main() invocando as funções desejadas. Ou seja, é o domínio do seu sistema.
View: é o que o Homer Simpson do seu usuário vê: uma representação visual do domínio realizado pelo model.
Controller: é o que fica entre o model e a view. Entre várias coisas, ele faz o que o model não deve fazer: manipular a view.

Implicação: o Controller conhece a View e o Model, a View conhece o Model, e o Model não conhece ninguém.

P. Model, View e Controller são camadas, certo?
R. Não, na realidade, nunca vi ninguém por nome nesses “troços”. Sério! Às vezes, ouvi dizer que eram componentes, outros que eram camadas. Não acho nenhum dos dois nomes apropriados. Componentes remetem ao modismo do início da década de 00 de se usar “componentes reusáveis” por “operários” em “fábricas de softwares” (eca!). Ou então a um outro modismo de componentes distribuídos como COM+ ou EJB (daqueles antigão). Nenhuma das duas coisas deram certo, e o MVC não tem nada a ver com isso. E camadas refere-se a um estilo de design para dividir um domínio grande, que pode ser feito num software com ou sem interface visual.

A real é que, na dúvida, o pessoal dá um jeito não dizer em que Model, View e Controller são classificados.

P. Mas perái! M, V e C são camadas sim! Model é a de persistência, View, a de apresentação e Controller, de negócio!
R. Nããããão, tá loco! Ponha uma coisa na sua cabeça: os objetivos tanto da divisão em camadas, quanto do MVC são distintas: a primeira tem o objetivo de controlar dependências, a segunda, de representar um domínio visualmente. Não são a mesma coisa, e nem dá para unificá-las em um modelo único. Algumas classes suas serão uma coisa do ponto de vista do MVC e serão outra coisa do ponto de vista das camadas.

P. O Controller serve para controlar o sistema?
R. Não, o nome controller é que é confuso, e remete a alguns programadores o “objeto deus” (God Object) ou o “objeto bolha-assassina” (Blob Object). Porém, objetos deuses são anti-patterns, ou seja, soluções aparentemente ideiais para problemas recorrentes que causam mais problemas ainda. Quando vier à sua cabeça “Controller”, pense-o como “Input Controller” (controlador de entrada), e este “coiso” deve fazer, estritamente, as seguintes atividades:
- ouve eventos;
- obtém os parâmetros de entrada desejados da View;
- obtém do Model um domínio (invariavelmente, este está num meio persistente);
- chama um método do domínio;
- escolhe a view a ser renderizada, fazendo “bind” de algum domínio do Model.

Não raro, programadores pouco experientes colocam, no “Controller”, lógicas de negócio ou tranformações de objeto para a view. Não é isso, remova esses códigos e ponham nos seus devidos lugares.

P. Ouvi falar de um tal de Model 2, ele é diferente do MVC?
R. Model 2 é uma adaptação do MVC, usando tecnologias padrão do J2EE como era conhecido no início da década de 00 (ou seja: Struts ou Servlet e JSP). O nome é puramente mercadológico, servia para diferenciar do “Model 1″, que era a utilização exclusiva de JSP para construção da aplicação web (assim como era o ASPão e o PHP). Por ser intimamente relacionado com tecnologias ultrapassadas, toda a burocracia da época está no Model 2, como Form Beans e XMLs, manipulação direta de mapas de escopos; sem falar de domínios fracos, normalmente misturados no meio da view ou das queries do banco. Minha recomendação: esqueça Model 2, porque você pode aprender MVC por outros meios.

P. O MVC da Web é diferente do MVC do Desktop?
R. Sim, existem duas diferenças: 1) um Controller de Desktop recebe eventos de clique do mouse, de teclado, de botões e outros componentes; um Controller de Web recebe exclusivamente eventos de submissão. Consequência: aplicações Desktop são orientadas a eventos, enquanto aplicações Web, orientadas a fluxos. Tudo que uma aplicação web entende é uma “stringona” com os dados de um suposto formulário (não dá pra saber se o cliente é humano ou que viu a interface gráfica) e que precisa devolver uma nova “stringona” para o cliente que, supostamente, renderiza para algum desenho gráfico. A aplicação Desktop sabe exatamente os eventos recebidos e pode agir diferentemente para cada um deles. 2) A View de Desktop mantém sincronia constante do Model (através do pattern Observer), qualquer alteração que o usuário fizer no model através de um painel, será refletida imediatamente em outros painéis que, porventura, estejam visualizando o mesmo Model. Na Web, não existe nada disso, a partir do momento em que o usuário está diante de uma tela, essa representação do Model estará desconectada do Model real e o usuário não saberá quanto (e se) o Model mudou. O único momento de mudança é quando o usuário aperta F5, mas isso implica num evento consciente do usuário, não numa coisa automática, como as aplicações Desktop de qualidade fazem.

P. Estava pensando em fazer um MVC distribuído, penso que o Model ficaria no Server e a View, no Client; só não sei onde ficaria o Controller, tem alguma sugestão?
R. Antes de mais nada, não existe MVC distribuído. O erro da sua pergunta baseia-se numa premissa equivocada, a de que é possível esconder a distribuição na aplicação. Não pode, e pra piorar, muitas “vendors” no passado (e ainda no presente) vendem soluções onde você poderia chamar um objeto remoto como se fosse local. Mas na real, chamadas locais e remotas somente são iguais quando ocorre sucesso, não quando ocorrem falhas, como queda na rede, versões incompatíveis ou falhas de autenticação/autorização.

Se você realmente precisar de uma aplicação distribuída (ex.: uma aplicação Desktop em C# conversando remotamente com um servidor Tomcat) você terá um MVC para o Client (o Model são Active Records que se comunicam com o Server, a View é o módulo onde se instancia componentes e o Controller, os métodos que entende os eventos) e um outro MVC para o Server (o Model são entidades, com seus services e mapeamento objeto-relacional, a View é XML, JSON, um formato binário ou outro qualquer e o Controller é o que entende requisições remotas).

P. Tenho uma aplicação Web, gostaria de reaproveitar o Controller se precisasse mudar minha aplicação para Desktop, como fazer isso?
R. Não faz. O controller é intimamente ligado à view, ou seja, nova view, novo controller. A origem do seu problema pode ser Controllers agindo como God Objects (ver aqui), e a solução seria um refactoring, não um Controller multi-uso.

P. O que o framework MVC faz? Age como Controller?
R. Quase. Lembra da lista citada acima sobre o que um Controller faz? Veremos o que um framework faz sozinho e outros que depende da ajuda manual do programador:
- ouve eventos (framework);
- obtém os parâmetros de entrada desejados da View (framework, obtidos via DI);
- obtém do Model um domínio (manualmente);
- chama um método do domínio (manualmente);
- escolhe a view a ser renderizada, fazendo “bind” de algum domínio do Model (parcialmente pelo framework, a escolha da view pode ser sobreescrita manualmente).

Há tentativas de algumas comunidades para criarem um framework onde o Controller deixa de existir, mas acredito que não funciona em todos os casos e dependem de models fixados a um padrão imposto ao framework.

Frameworks vão além, é claro, pois proveem funcionalidades adicionais como helpers para views e outras coisas.


São essas as perguntas que eu consegui imaginar. E você? Tem alguma dúvida sobre MVC além dessas daqui?

Já usou Memcached?

maio 2nd, 2009 § 1

Cache não é algo que os programadores desconhem. Quem esteve numa universidade, e teve uma aula séria de Arquitetura de Computadores, sabe que a memória é disposta numa hierarquia de caches. E quem já programou em Java, já ouviu falar de inicialização tardia, muito usado em singletons (apesar de não ser só para isso): » Read the rest of this entry «

Aprenda Java EE 6, agora! (3)

março 22nd, 2009 § 1

Seguindo o post anterior, continuaremos a aplicação de AgendaMedica. Lembra do que faltava? Precisávamos de um conceito de Consulta, que não havia no nosso modelo. E precisávamos que a consulta tivesse uma característica melhor do mundo real, como, por exemplo, não permitir duas consultas no mesmo horário e não permitir consultas fora do horário do médico.
» Read the rest of this entry «

Aprenda Java EE 6, agora! (2)

fevereiro 24th, 2009 § 2

Dessa vez, estarei utilizando a versão b37 do Glassfish v3. Por causa disso, você vai ter que fazer alterações à mão no plugin do Eclipse para o servidor Glassfish. Na versão b36 havia as pastas web e ejb dentro de module. Agora, todos os jars estão dentro de module, sem distinção de pastas.

Primeiro, feche o Eclipse. Iremos copiar o plugin do Glassfish e descompactá-lo, para alterar o seu arquivo de configurações. No Linux eu fiz assim, supondo que ECLIPSE_HOME seja uma variável onde aponta para a pasta do Eclipse: » Read the rest of this entry «

Aprenda Java EE 6, agora!

fevereiro 15th, 2009 § 4

Quando fiquei craque no Java, a versão do “Enterprise Edition” era ainda 1.4. Eu aprendi a versão 5, logo depois do lançamento do Glassfish. Mas agora estou fazendo algo diferente, não vou esperar a versão Java EE 6 sair, vou aprender as coisas tão logo as novidades apareçam.

E você também pode fazer isso. Pegue uma versão promoted do Glassfish no site deles, que, assim como o Lost, tem sempre uma versão nova nas quartas à noite, que você baixa na quinta. A última versão, que estou usando nesta semana, é a b36.

Baixe a última versão disponível e descompacte num lugar que você achar apropriado. No Eclipse, na hora de instalar o servidor, basta escolher a opção “Glassfish v3 Prelude” (se você não usava Glassfish, na tela de novo servidor há uma opção de baixar os adaptadores para outros servidores). Pronto!

Eu vou fazer uma aplicação de exemplo, que é uma agenda de consultório médico. É babaca, mas tem uma regras óbvias que não dá pra ser tratado com o velho CRUD.

Vamos lá. Crie um “Dynamic Web Project” cujo Runtime seja o “Glassfish v3 Prelude”, vou chamá-lo de AgendaMedica. Não sei como vocês lidam com testes no Eclipse, mas costumo criar um novo projeto Java que referencia o projeto que estou interessado em testar. No caso, criarei também o projeto Java AgendaMedicaTeste. Após criado, dê <Alt> + <Enter> sobre o projeto, clique em “Java Build Path”, vá na aba “Projects” e adicione o projeto AgendaMedica.

No projeto AgendaMedicaTeste, eu já criei um método de testes pra realizar a consulta:

package br.com.objectzilla.agendamedica;
 
import java.util.Calendar;
 
import org.junit.Assert;
import org.junit.Test;
 
public class AgendamentoTeste {
 
	@Test
	public void pacienteMarcaHoraComMedico() {
		// um paciente...
		Paciente paciente = new Paciente();
		paciente.setNome("Maria");
 
		// um médico...
		Medico medico = new Medico();
		medico.setNome("Dr. Gregory House");
 
		// ambos agendam um horário
		Agendamento agendamento = new AgendamentoImpl();
		Calendar horario = Calendar.getInstance();
		horario.set(2009, Calendar.MARCH, 5, 17, 00, 00);
 
		agendamento.marcaConsulta(medico, paciente, horario);
 
		// agora, médico tem consulta com paciente marcada às 5
		Paciente pacienteMarcado = medico.consulta(horario);
		Assert.assertEquals(paciente.getNome(), pacienteMarcado.getNome());
	}
}

Beleza, mas o código não compila, né? Ora, não seja por isso. Vá criando as classes clicando nos erros com o botão direito do mouse, só não se esqueça de colocar as classes no projeto AgendaMedica. No caso, Agendamento é uma interface e o restante são classes.

Bom, tente rodar o script de teste (clique com botão direito sobre a classe e dê Run As… > JUnit Test). Vai dar erro, óbvio! Por isso, convido a você a escrever código nas classes até o script rodar com sucesso. Não se preocupe, se você não conseguir ou não tiver paciência, no final do post eu mostro o link onde você pode baixar o código.

Agora, vamos transformar a interface Agendamento em um Stateless Session Bean. Não precisa nem mover pra um projeto próprio, pois agora os EJBs podem ser “deployados” em aplicações WAR. Basta adicionar @Local na interface (a v3 ainda não possui suporte a @Remote), assim:

@Local
public interface Agendamento {
	// ...
}

E adicionar @Stateless na classe que implementa:

@Stateless
public class AgendamentoImpl implements Agendamento {
	// ...
}

Pronto, faça o deploy do projeto web no servidor Glassfish v3 e veja o seguinte log aparecer:

INFO: Bound Java:Global name [business view] : java:global/AgendaMedica/AgendamentoImpl#br.com.objectzilla.agendamedica.Agendamento
INFO: Bound Java:Global name [single business view] : java:global/AgendaMedica/AgendamentoImpl

Repare em como é realizado o binding com o JNDI. A partir da versão 6, não será mais uma implementação específica de contêiner. Todos os servidores de aplicações, se quiserem ser homologados para Java EE 6, deverão dispor seus EJBs, em contextos JNDI, de acordo com o seguinte padrão:

java:global[/<application-name>]/<module-name>/<bean-name>#<interface-name>

Onde:

<application-name> é opcional, refere-se ao nome do pacote EAR (não tem no nosso caso).

<module-name> é o módulo onde está o EJB (AgendaMedica).

<bean-name> é o nome do bean (AgendamentoImpl).

<bean-name> é o nome do bean (AgendamentoImpl).

<interface-name> é o nome completo da interface que implementa o bean (br.com.objectzilla.agendamedica.Agendamento).

O leitor atento deve ter reparado: está sendo feito dois bindings para o EJB! Isso também faz parte do padrão. Se o bean implementar apenas uma interface, um alias será criado onde o nome da interface não aparece.

Já que criamos o Session Bean, seria interessante se usássemos, não é não? Vamos fazer um Servlet, mas não precisa tomar o susto de configurar o wer.xml, pois basta criar um classe que herde de HttpServlet e adicionar uma anotação de acordo com o seguinte código:

@WebServlet(value="/agendamento")
public class AgendamentoServlet extends HttpServlet {
 
	@Override
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
			IOException {
 
	}
}

Após o deploy, basta digitar http://localhost:8080/AgendaMedica/agendamento e você vai ver… uma tela em branco. Normal, a gente não fez nada mesmo. Agora, vamos preencher o doGet() com uma chamada ao método de marcarConsulta() de agendamento. Eu também injetei uma instância de EJB.

@WebServlet(value="/agendamento")
public class AgendamentoServlet extends HttpServlet {
 
	@EJB
	private Agendamento agendamento;
 
	@Override
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
			IOException {
 
		String nomeMedico = req.getParameter("medico");
		String nomePaciente = req.getParameter("paciente");
		int hora = Integer.parseInt(req.getParameter("hora"));
 
		// criando médico
		Medico medico = new Medico();
		medico.setNome(nomeMedico);
 
		// criando paciente
		Paciente paciente = new Paciente();
		paciente.setNome(nomePaciente);
 
		// criando horário
		Calendar horario = Calendar.getInstance();
		horario.set(Calendar.HOUR, hora);
		horario.set(Calendar.MINUTE, 0);
		horario.set(Calendar.SECOND, 0);
 
		// chamando método de agendamento
		agendamento.marcaConsulta(medico, paciente, horario);
 
		PrintWriter pw = resp.getWriter();
		pw.format("Eu juro que marquei consulta para o paciente %s, com o médico %s, na hora %d.",
				medico.getNome(), paciente.getNome(), horario.get(Calendar.HOUR));
 
 
	}
}

Se você rodar http://localhost:8080/AgendaMedica/agendamento?medico=Jose&paciente=Adolfo&hora=14, vai ver que a aplicação mostra uma mensagem na tela que não diz se foi, ou não foi, feito algo. Precisaria de uma tela de consulta, mas só dá pra fazer isso se nossa aplicação persistisse os objetos entre as requisições, o que atualmente não ocorre.

Vou fazer isso no próximo post, onde apresentarei mais novos recursos e novas funcionalidades na aplicação pra que ela finalmente funcione de verdade.

Quem quiser, pode ir alterando a aplicação por conta própria, deixei no repositório GitHub em http://github.com/leonardoverissimo/javaee-6-application/tree/master.

Filho de feio inteligente com gostosa burra

fevereiro 10th, 2009 § 0

Seguinte, na segunda-feira (09/fev), eu vi um PDF sobre uma experimentação de tipagem estática em Python. Não que eu esteja duvidando da capacidade dos caras que fizeram a apresentação, até porque, mexer com linguagens não é para qualquer um, mas sei lá, o fato de muita gente ter dado um “up” no Reddit implica que muita gente sonha com uma linguagem cuja tipagem é tanto estática quanto dinâmica.

Isso me preocupa, sabia? A impressão que dá é que as pessoas sonham com uma espécie de uma linguagem meio-termo, que acabasse com as guerras nerdísticas e que fosse a única que reinaria soberana sobre todos as outras. E uma que fosse estática e dinâmica, ao mesmo tempo, seria a candidata ideal. Infelizmente, tenho que te contar a triste realidade: tipagem estática e dinâmica são antagônicas, tipo água e vinho.

Você já programou em C++? Então, quem conhece o troço sabe que existem vários paradigmas conflitantes entre si. Um paradigma é a programação procedural com conteineres STL, outro é a programação orientada a objetos e outro é programação por templates. Todos bem diferentes, e cuja mistureba só pode ser feita com bastante cuidado por gente que não tem amor à própria vida. Sim, é realmente complicado programar em templates e depois tentar usar OO, é complicado usar o paradigma C quando boa parte do código já está com a sintaxe do C++. E eu desconfio que a mesma coisa pode ocorrer com essas linguagens que misturam tipagem estática e tipagem dinâmica. Vamos fazem uma experimentação com Groovy? Primeiro: o que acontece quando compilamos (com groovyc) o seguinte trecho?

// recebe um objeto de tipo indefinido
def imprima(valor) {
    println valor
}
 
// objeto de tipo "String" numa referência de tipo "String"
String msg = "Olá"
 
// objeto de tipo "String" passado para parâmetro sem tipo
imprima msg

Sucesso, é perfeitamente possível passar um objeto qualquer numa referência sem tipo.

Mas, e se invertermos, assim?

// recebe um objeto de tipo "String"
def imprima(String valor) {
    println valor
}
 
// objeto de tipo "String" numa referência sem tipo
msg = "Olá"
 
// objeto de tipo "String" passado para parâmetro de tipo "String"
imprima msg

Sucesso também, o compilador não reclama quando uma referência String recebe um objeto de uma referência sem tipo. E se chutarmos o balde, definindo a função imprime() recebendo um int?

// recebe um objeto de tipo "int"
def imprima(int valor) {
    println valor
}
 
// objeto de tipo "String" numa referência de tipo "String"
String msg = "Olá"
 
// objeto de tipo "int" passado para parâmetro de tipo "String"
imprima msg

Acha que dá erro de compilação? Dá nada! Compila com sucesso também! Não existem casos específicos para isso. Em Groovy, os tipos não são decididos em tempos de compilação. Erros de tipos só são descobertos quando você executa o código com tipagem divergente.

Não tenho nada contra linguagens de tipagens estáticas, nem de dinâmicas. Só acho que cada um deve estar no seu quadrado. Muito se fala que, com linguagens “mistas”, como Groovy, se obtém os benefícios da tipagem estática com os benefícios da tipagem dinâmica. Será mesmo? Vamos pensar: Em minha opinião, a vantagem da tipagem estática é a possibilidade de reduzir erros causados por atribuições errôneas, impossibilitanto até mesmo e existência do código executável; a desvantagem é que os tipos estáticos causam um engessamento da aplicação (a famosa dúvida: “como trocar a classe, uma vez que as referências são da classe antiga?”), e cuja solução (criação de classes abstratas e de interfaces) precisa ser feita no começo do desenvolvimento.

A vantagem da tipagem dinâmica (de novo, em minha opinião) é possibilitar um código mais flexível pois, como as referências não se comprometem com tipos, uma nova classe com os mesmos contratos de uma antiga sempre será substituível por esta. A desvantagem é que, principalmente com APIs públicas ou com equipes dispersas, torna-se mais difícil definir um contrato dos métodos e classes.

Veja, Groovy não tem aquela vantagem de uma linguagem estática. Se você retornar, em uma função, um valor de tipo diferente, é possível quebrar o código em algum outro lugar e você nem perceber. Significa que precisará de uma grande suíte (e de uma forte cultura) de testes unitários, como qualquer linguagem dinâmica.

E também não tem aquela vantagem de uma linguagem dinâmica. Tipos não são garantias de que métodos obedeçam estritamente um contrato. Em linguagens “puramente” dinâmicas, como não há tipos nas referências, é permitido uma certa flexibilidade do que se pode ou não pode aceitar. Exemplo, em Ruby, poderia ter métodos que recebem valores válidos, não importando seu tipo.

# classe hipotética Triângulo
# válido
t = Triangulo.new :tipo=>:retangulo
 
# válido também, por que não?
t = Triangulo.new "tipo"=>"retangulo"
 
# válido
t.hipotenusa 10
 
# válido, por que não?
t.hipotenusa "10"
 
# opa! erro! O método lança exceção!
t.cateto_oposto -4

Tá vendo, os métodos podem tanto receber String quanto números, o importante é o valor resultante ser um número natural. O pensamento da tipagem limita essas espertezas, pois fica-se o tempo todo imaginando: “Não! Esse método tem que receber uma ‘classe X’!” (Pior que o indivíduo se esquece até da diferença entre objeto e classe.). Como Groovy não vai incentivar ninguém a abandonar os tipos em tudo quanto é canto, também não se receberá os benefícios das linguagens dinâmicas.

Então, pra amarrar com o título acima. Sou da opinião de que Groovy é ruim… não, corrigindo… de que Groovy é a pior linguagem do mundo porque, ao unir o feio inteligente (a tipagem estática) com a gostosa burra (a tipagem dinâmica), não se deu origem a um filho bonito e inteligente, como era de se esperar.

Foi pior, o filho é feio e burro.

Where Am I?

You are currently browsing the Sem categoria category at Objectzilla.