No final de novembro de 2011 teve início uma grande agitação no mundo Scala, causada pelo vazamento de um email da Yammer que gerou muitos questionamentos, pois indicava que a infraestrutura básica do Scala voltaria a ser o Java. Em seguida a Typesafe publicou uma resposta, agradecendo os comentários e aproveitou para abordar os planos para o futuro do Scala.
No topo das novidades temos o Scala IDE para Eclipse, cujo desenvolvimento vinha sendo feito desde o início por Miles Sabin [consultor de Scala da Chuusai], mas que agora é mantido pela Typesafe. A IDE mais recente pode ser usada com o JDK 5 ou JDK 6 e está na versão 2.0.0 (oficialmente liberado para a versão Eclipse 3.6 Helios, podendo também ser instalado no Eclipse 3.7 Indigo com algumas restrições de funcionalidade). Assim como outras bibliotecas pré-compiladas do Scala, o IDE possui diferentes pacotes para download, que são baseados na versão do Scala a ser usada. Há releases com suporte às versões 2.9.x ou 2.8.x.
Outras IDEs comerciais também fornecem suporte ao Scala. As recentes versões do JetBrains e IntelliJ IDE 11 já suportam o Scala na instalação padrão para ambas as edições: comercial e comunitária.
Em seu post "voltando ao trabalho", a Typesafe responde críticas específicas como as exigências na curva de aprendizado, tempo de compilação e desempenho. A empresa comenta que o Scala ainda é considerado um trabalho em andamento, e que embora o desempenho seja importante, existe o cuidado de se evitar otimizações prematuras enquanto a linguagem amadurece. Para a construção (build), recomenda-se o uso da Simple Build Tool (SBT), uma ferramenta que é executada em segundo plano e reduz o tempo de inicialização entre compilações. Por fim, em função do crescimento da comunidade em torno do Scala, o repositório de fontes da linguagem foi movido para o GitHub.
Entretanto, os comentários relacionados à compatibilidade binária geraram insatisfação. Embora a Typesafe possua um plano de assinatura, que garante suporte e manutenção comercial para o conjunto Scala e Typesafe Stack, não foram consideradas as necessidades da comunidade como um todo e de outros frameworks, ao contrário do feito em outras plataformas como Java, Python e Perl. Como alternativa, é oferecida uma aplicação proprietária chamada Migration Manager, que é capaz de determinar estaticamente se haveria variações em tempo de compilação entre diferentes builds. A ferramenta foi utilizada pela própria Typesafe para garantir que o Scala 2.9.1 manteve a compatibilidade retroativa com a versão 2.9.0. A empresa alega também que continua a fornecer todos os frameworks necessários para o desenvolvedor, tal como bibliotecas comuns de teste, IO e gerenciamento transacional em memória.
David Pollak, criador do conhecido framework web Lift, não acredita que este seja o foco correto, no entanto. Em seu post "A fragilidade de versão do Scala torna a adoção por empresas quase impossível", argumenta que as constantes mudanças no bytecode estariam prejudicando diretamente o crescimento do ecossistema do Scala fora do produto da Typesafe.
Uma característica do Scala é que seu compilador gera um bytecode frágil. Isto significa que todos os códigos em executáveis (JAR ou WAR) precisam ser compilados usando as mesmas versões de bibliotecas e compilador. Quando se está usando o Scala 2.9.1 em um projeto, é necessário fazer a compilação usando uma versão do Lift, além de todas as suas dependências que também foram compiladas nesta mesma versão. Por isso o Lift tem poucas dependências de bibliotecas.
A fragilidade de versão do Scala cria dois grandes custos para os complexos sistemas corporativos:
- Todas as dependências precisam ser compiladas com a mesma versão do Scala e usando as mesmas versões das bibliotecas Scala, o que torna incrivelmente complexo e demorado gerar compilações quando há várias equipes;
- Bibliotecas externas (como Lift) não podem ter múltiplas camadas de dependências, porque é necessário combinar exatamente a mesma versão da biblioteca e do Scala por todas as dependências.
David Pollak é um dos poucos que pode se embasar em cinco anos de envolvimento com a linguagem Scala e com a comunidade como um todo. A manutenção do projeto do framework Lift, através destes princípios orientadores, é uma excelente referência de como uma comunidade deve funcionar.
A fragilidade citada não é tão problemática com equipes de desenvolvimento pequenas ou quando uma única equipe na empresa está usando Scala. Durante uma migração de Java para Scala para um projeto iniciado do zero, o tempo/custo de trocar a versão é menor do que um dia de trabalho. Mas os problemas surgem rapidamente conforme o aumento do número de equipes:
Por exemplo, em uma organização com duas ou três equipes de desenvolvimento criando código Scala, pode-se definir conjuntamente a versão do Scala e das várias bibliotecas a serem usadas. Quando uma nova versão do Scala ou das bibliotecas estiver disponível, basta juntar algumas pessoas de cada equipe e decidir atualizá-la (ou não). Mas uma vez que se tem mais do que três equipes, o esforço de coordenação passa a ser significativo. Tentar juntar dez diferentes equipes para definir a versão do Scala, Lift, ScalaZ, Rogue, Dispatch e outras bibliotecas, começa a ter um custo bem expressivo.
Como um criador de biblioteca, a questão da fragilidade de versão significa que a nossa biblioteca não é tão boa quanto poderia ser e que não conseguimos servir a nossa comunidade da maneira que desejamos.
No artigo barreiras para a adoção do Scala, David Pollak já manifesta estas preocupações. Ele acredita que este problema não está recebendo a atenção devida e que um verificador proprietário de bytecode é mais um remendo do que uma solução.
O que fiz em relação a este problema? Ao longo dos anos, levantei este assunto privadamente e ele não foi solucionado. Tentei organizar um projeto para encaminhar parte deste assunto, mas não consegui massa crítica para levá-lo adiante.
Há mais de um ano, durante o ciclo de desenvolvimento da versão 2.8, foi formado o projeto "Fresh Scala". A ideia básica era ter a integração contínua, envolvendo a maior parte das bibliotecas Scala e liberar atualizações semanais, para que a comunidade e o ecossistema pudessem nos dar melhores retornos sobre as novas versões do Scala. Devido a falta de tempo dos voluntários, o sistema não foi implantado e aqui estamos, após um ano e meio, com o mesmo problema de fragilidade de versão no Scala.
A iniciativa do Fresh Scala não progrediu muito em um ano e meio, mas Josh Suereth, da Typesafe, assumiu a responsabilidade em seu post Scala Fresh 2.0. Nele é anunciado o Scala Fresh 2.0, uma recriação do projeto hospedado no GitHub:
O que aconteceu com o Scala Fresh? As pessoas podem não ter percebido, mas o Scala Fresh falhou, porque <b>eu</b> falhei com o Scala Fresh. Tive muito pouco tempo disponível, entre um emprego em tempo integral no Google, atuação como escritor e as crianças. Isto não deverá ser um problema no futuro, porém, graças à Typesafe estar levando a sério a compatibilidade binária.
Iniciei os trabalhos no que pode ser chamado de "Scala Fresh 2.0", um lugar onde as bibliotecas comunitárias serão construídas e publicadas sobre a última versão do Scala. Issoo será útil para dois propósitos:
- Assegurar que futuras versões do Scala não quebrem a compatibilidade com as bibliotecas da comunidade;
- Assegurar que as principais bibliotecas Scala estejam disponíveis para todas as versões maiores do Scala.
Josh Suereth também argumenta que a responsabilidade sobre a compatibilidade binária é do desenvolvedor da biblioteca, ao invés da plataforma:
Compatibilidade binária é um esforço da comunidade. Sei que a Typesafe está fazendo o possível com os seus recursos, e estou pessoalmente atuando como posso.
É possível escrever código em Java que não mantém a compatibilidade retroativa. Remover métodos públicos e alterar assinaturas de métodos são exemplos de causas de quebra de compatibilidade em qualquer linguagem. Por outro lado, o design de bibliotecas compatíveis retroativamente é algo que muitos desenvolvedores Java já fazem automaticamente, e ainda contam com ferramentas como o Verificador de Uso de APIs do PDE.
Se a evolução das bibliotecas Java é algo previsível (em virtude da implementação das classes estarem em um único arquivo), Josh Suereth destaca que é possível introduzir mudanças incompatíveis através dos Traits do Scala, já que são (na prática) uma junção de interface e implementação:
trait Foo { def foo = "foo" } trait Foo { // mantém a compatibilidade retroativa com o código acima def foo = "foo" def bar = "bar" } --- trait Bar { def foo = { " foo" } } trait Bar { // não mantém a compatibilidade. def foo = { bar + " foo" } def bar = "bar" }
É possível ter mudanças de código compatíveis em nível de fonte (uma classe que tem o trait Bar, irá compilar em ambos os casos), mas clientes compilados usando a versão anterior do Bar não terão o método bar(), de modo que os clientes mais novos poderão tentar chamar um método que não possui implementação.
As principais bibliotecas do Scala sofrem constantemente com este problema. Por exemplo, a biblioteca de coleções é alterada a cada nova versão do Scala, e como a maioria das APIs usa esta biblioteca, há uma amarração com a versão do Scala usada para compilar o bytecode (e também com a versão das principais bibliotecas). Alguns já começaram a questionar se seria uma boa ideia ignorar o Scala como uma linguagem compilada, tratá-la como veículo para o desenvolvimento da versão 2.10 e deixar de lado, por enquanto, a compatibilidade entre versões. Se o desenvolvedor escolher seguir adiante com a nova versão, será necessário recompilar tudo para garantir o funcionamento correto.