Trocando Ruby por Kotlin — Parte 3

Fabrício Rissetto
Creditas Tech
Published in
6 min readAug 8, 2019

Esse é o último de uma série de 3 posts que foram escritos de forma colaborativa por Fabrício Rissetto, Matheus Caceres e Murilo Capanema. Caso ainda não tenha lido, aqui estão as partes 1 e 2.

O primeiro serviço Kotlin em produção

Após algumas POCs com a linguagem, feitas primeiramente num fim de semana e com a presença de um pouco de cerveja, confirmamos que aquela era uma linguagem fascinante e que merecia um teste mais sério.

Foi então que decidimos extrair um contexto pequeno e bem definido do nosso monolito para um microsserviço em Kotlin. Esse contexto, que lidava com políticas automáticas de crédito, estava bem desacoplado do restante do monolito, e havia sido escrito em Ruby e utilizando o Hanami. Tomamos um cuidado ao extraí-lo: tirar esse contexto do monolito não era o único objetivo, queríamos também avaliar Kotlin e seus frameworks. Para isso, decidimos migrar o código da forma mais fiel possível à implementação em Ruby, mantendo as mesmas classes, nomes de métodos e atributos. Claro, tivemos que incluir algumas coisas a mais, como interfaces, devido à mudança de uma linguagem dinamicamente tipada para uma estaticamente tipada, por outro lado muita coisa diminuiu também.

Comparação entre Ruby e Kotlin

No final da reescrita desse contexto para Kotlin fizemos uma apresentação do resultado para toda a empresa. Demos um overview sobre a linguagem e depois mostramos os exemplos de código em Ruby e Kotlin, junto com algumas outras métricas. Além da expressividade e legibilidade extremamente alta (justamente uma das bandeiras defendidas por Ruby), Kotlin apresentou uma diminuição altíssima na quantidade de código gerado. O contexto escrito em Ruby tinha exatas 1174 linhas enquanto o Kotlin, que fazia exatamente a mesma coisa, tinha 650. Observamos que em alto nível as linguagens são parecidas e nenhuma delas tem características notórias como, por exemplo, não utilizar chaves na especificação de classes e métodos, que poderia artificialmente favorecer essa discrepância. Por mais que a métrica de número de linhas não seja a melhor pra esse tipo de comparação, o resultado refletia perfeitamente a nossa percepção de simplicidade. Notamos a diminuição (ou ausência) de boilerplate para: criação de propriedades públicas nas classes, construtor, imutabilidade, tratamento de presença ou não de objetos (null safety), etc. Lembrando novamente que, com menos boilerplate e contando com a ajuda do compilador, temos também menos testes de unidade.

Repository Pattern

Com relação a implementação do repository pattern, utilizamos o Spring Data. Achamos muito fácil utilizá-lo e configurá-lo. Há pouco boilerplate code, além de possuir uma ampla documentação e material. Entretanto, uma característica que não gostamos foi a necessidade do uso de annotations nas classes de domínio. Uma opção para evitar as annotations é utilizar configuração via XML, mas achamos ainda pior. Uma alternativa interessante oferecida no mundo Kotlin é o Exposed, no qual chegamos a avaliar mas rapidamente encontramos limitações (por ser ainda muito recente) e por isso abortamos. No final, aceitamos ficar com o Spring Data e o pequeno ruído provocado pelas suas annotations, algo infelizmente ainda muito comum ao se utilizar libs Java :’(.

Libs Java ou Kotlin?

Temos dado preferência em utilizar bibliotecas Java quando elas atendem aos requisitos razoavelmente bem (o que acontece com muita frequência), pela questão de maturidade das bibliotecas e documentações (além do ponto citado logo abaixo que é a facilidade de contratação de devs Java). Quando encontramos bibliotecas específicas de Kotlin e que são muito superiores as já oferecidas em Java, as utilizamos sem medo. Um ótimo exemplo é o Arrow, biblioteca inspirada no ScalaCats, que implementa uma série de abstrações para se lidar com o paradigma funcional, algo que temos explorado cada vez mais em Kotlin (em breve faremos posts falando sobre isso).

Curva de aprendizado

No processo de migração tivemos que aprender MUITA coisa nova e, acredite, a linguagem foi a mais fácil delas. A própria filosofia e estratégia da JetBrains ao criar a linguagem favorece isso: Kotlin não traz nada de revolucionário, apenas se apoia nas boas funcionalidades das linguagens mais recentes e traz tudo de bom das linguagens com ampla adoção e espaço no mercado enterprise, como Java e C#. Então sua sintaxe acaba sendo muito intuitiva para a maioria dos desenvolvedores.

Entretanto, nem tudo são flores. Para os desenvolvedores que nunca haviam trabalhado com nada da stack JVM, a curva de aprendizado não compreendia apenas a linguagem, mas também todo o ecossistema. “Será que vamos usar o maven ou gradle para gerenciar as dependências? Que framework web vamos usar, o Spring ou o Ktor? Qual framework de testes é melhor? Qual ORM?”. Todas essas perguntas e algumas outras constituíram 80% da curva de aprendizado. A linguagem foi 20%.

Impactos e resultados

Além dos impactos positivos com expressividade, sucintez e ampla oferta de frameworks maduros, o que se converte em maior velocidade de desenvolvimento e dedicação do nosso tempo para focar no que realmente queríamos, o negócio, também tivemos uma diminuição na taxa de erros que a linguagem favorece a evitar, como o null reference exception. A taxa de erros com esse bug específico até hoje (e já temos muitos outros serviços em Kotlin) é de exatamente 0. Isso mesmo, zero erros de null reference (em Kotlin, apesar de ser tecnicamente possível, para esse tipo de erro acontecer é preciso se esforçar muito).

Além do aspecto técnico, também tivemos outros benefícios que, apesar de não ser a motivação principal, sempre estiveram nas listagens de pontos “prós e contras” das linguagens analisadas. Um desses pontos é o fator “facilidade de contratação”. Ao contrário de Ruby, cuja popularidade tem diminuído aos poucos, Kotlin está em uma curva de crescimento e tem grandes empresas a apoiando. De fato ainda não dá pra saber até onde esse rápido crescimento irá se sustentar, mas estamos muito convictos de que a linguagem vai ganhar cada vez mais espaço no mercado e que tomará MUITO o espaço de Java nos próximos anos. E são exatamente esses desenvolvedores que nós estamos buscando. Encontrar desenvolvedores em Java é mais fácil e muitos deles têm altíssimo interesse em trabalhar com Kotlin. Contratar bons desenvolvedores Java e trazê-los para nos ajudar a trabalhar num ecossistema que eles já conhecem, e ainda por cima com Kotlin, não tem sido uma tarefa tão difícil.

Um último ponto é quanto ao benefício da diversidade. A Creditas é uma empresa que abraça a diversidade em todos os aspectos, desde sociais a tecnológicos. Ter trazido pessoas de diferentes stacks de desenvolvimento nos fez refletir e questionar nossas premissas mais antigas e promoveu a discussão e o conflito de ideias, o que foi e tem sido muito produtivo.

Contribuições open source

Nesse período fértil e de constantes aprendizados, além de termos feito diversas contribuições para frameworks como, Arrow, Kluent, Fuel, também criamos alguns projetos de exemplo que estão disponíveis nos seguintes repositórios: DDD Rails Sample e Kotlin DDD Sample. Provável que no futuro abriremos alguns outros projetos que hoje são internos. Aguarde :)

“Disclaimer” de encerramento…

O objetivo dessa série de posts é compartilhar nossa história, caminhos trilhados e frutos colhidos. Não pretendemos sugerir que Ruby deve ser abandonado, tampouco que as linguagens que não foram escolhidas são inferiores a Kotlin, ou que as linguagens que não foram consideradas na nossa lista não são dignas de mérito, nem que estudamos absolutamente tudo que deveríamos nas POCs e linguagens citadas. Faz parte da vida tomar decisões corajosas com base em informações incompletas e na presença de incertezas. Foi o que fizemos. E estamos muitos orgulhosos em colher os frutos da escolha a cada dia que passa.

Tem interesse em trabalhar conosco? Nós estamos sempre procurando por pessoas apaixonadas por tecnologia para fazer parte da nossa tripulação! Você pode conferir nossas vagas aqui.

--

--