Compartilhar com
12 minutos para ler
Você provavelmente já ouviu falar em Kotlin, a nova linguagem oficial para desenvolvimento Android que promete ser moderna e interoperável com Java. Mas você sabia que Kotlin também é uma ótima linguagem para utilizar no desenvolvimento backend? Neste artigo O Wellington Felix, do time de Desenvolvimento da Sinch, mostrou alguns dos principais recursos que fazem Kotlin brilhar no desenvolvimento de aplicações backend. Confira!
Kotlin foi criado pela Jetbrains, a empresa por trás de produtos como a IntelliJ IDEA e o PyCharm, e teve sua primeira versão estável em 2016. A Jetbrains utilizava bastante Java na época para desenvolver seus produtos e queria uma linguagem mais expressiva e menos verbosa. Por isso, Kotlin teve como principais objetivos dar mais produtividade ao desenvolvedor e garantir fácil interoperabilidade com Java. Em 2017, o Google anunciou Kotlin como uma linguagem oficial de desenvolvimento Android. Foi também em 2017 que a Pivotal anunciou suporte oficial a Kotlin para o Spring Framework 5.0, o que acabou popularizando bastante a linguagem para desenvolvimento backend. Em 2018, no survey anual do Stackoverflow Kotlin ficou em 2° lugar como a linguagem mais amada por desenvolvedores e em 4° como a mais popular entre quem pretende aprender uma nova linguagem. Também em 2018, uma outra pesquisa, desta vez conduzida pela Jetbrains, mostrou que dos mais de mil desenvolvedores Kotlin participantes, 41% utilizava a linguagem para desenvolvimento web backend. Isso mostra que existe um crescente interesse da comunidade no que Kotlin pode oferecer para desenvolvedores backend. A seguir, vou detalhar algumas das razões que acredito que fazem Kotlin uma ótima linguagem para desenvolvimento server-side.
Kotlin é uma linguagem null-safe. Isso significa que o sistema de tipos também dá informações ao compilador sobre a possibilidade de um valor referenciado ser nulo. Isso é um problema já conhecido em diversas linguagens em que uma tentativa de acesso a uma referência nula gera um erro de Runtime. No caso de Java, a conhecida NullPointerException. Tony Hoare, o criador da referência nula, chegou a dizer em uma conferência em 2009 que esse era o seu “erro de um bilhão de dólares” devido à “inúmera quantidade de erros, vulnerabilidades, e falhas de sistemas […] nos últimos quarenta anos”. Kotlin, resolve este problema fazendo uma distinção clara do que pode ser e do que não pode ser nulo: uma variável contendo um texto que tem o tipo String? sinaliza ao compilador que a variável pode conter null e força um tratamento especial onde necessário.
1 | val message: Message? = extractMessage(messageWrapper) val userName = message?.user?.name |
Exemplo de como Kotlin lida com valores nulos No exemplo acima precisamos utilizar o operador ?. para acessar os campos que podem ser nulos, e caso algum deles seja, a expressão toda será resolvida para null. Isso acaba com praticamente todos os casos de NullPointerException tornando seu código menos propenso a esse tipo de erro.
Para quem já possui projetos escritos em Java, é possível aproveitar uma codebase existente e fazer o código Kotlin viver lado a lado com o código Java! Isso é ótimo pois SDKs, bibliotecas e serviços internos podem ser aproveitados sem muita dificuldade. Além disso, Kotlin reaproveita o ótimo ecossistema de bibliotecas e framework já disponíveis para Java tornando ainda mais fácil a adoção da linguagem.
Em Kotlin, diversas construções podem ser escritas em poucas linhas de código, dando ao desenvolvedor mais expressividade e produtividade. Um exemplo disso são as data classes:
1 2 3 4 5 6 7 8 9 | data class Message(val text: String,</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val phone: String,</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p> val createdAt: Long = Instant.now().toEpochMilli()) |
Exemplo de uma data class em Kotlin com argumentos default Em Java, para criar uma classe modelo, também conhecida como POJO ou Bean, seria necessário escrever ou gerar código para definir getters, setters, toString, equals, copy… Ou utilizar uma biblioteca como Lombok. Com data classes o compilador de Kotlin gera tudo isso e ainda nos permite economizar tempo e linhas de código. Perceba também que nessa data class estamos utilizando outro recurso de Kotlin que nos dá bastante produtividade que são os argumentos default. Ao invés de criar diversos overloads de métodos ou construtores de classes, é possível definir um valor padrão para determinados argumentos reduzindo significativamente a quantidade de código necessário. Outro recurso da linguagem bastante interessante são as extension functions que permitem estender a funcionalidade de classes existentes sem a necessidade de herança de uma forma bem simples, eliminando a necessidade de classes utilitárias:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | fun BigDecimal.formatToBRL(): String {</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val brazilianFormat = DecimalFormat</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getCurrencyInstance(Locale( "pt" , "br" ))</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return brazilianFormat.format( this )</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>}</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>fun main(args: Array&lt;String&gt;) {</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;val amount = BigDecimal( 144.42 )</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;println(amount.formatToBRL()) // R$ 144,42</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>} |
Com a extension function acima, todo BigDecimal também terá o método formatToBRL() Roman Elizarov, líder do time de desenvolvimento das bibliotecas de Kotlin, escreveu ótimos artigos no Medium e também sobre Extension-oriented design e como extensionfunctions vão além de uma conveniência que a linguagem nos dá – podem ser usadas para tornar mais claro o comportamento de interfaces, por exemplo. Vale a pena dar uma olhada!
Com coroutines é possível escrever código assíncrono e não-bloqueante de forma simples e imperativa. Coroutines funcionam como Threads em Java, mas são muito mais leves. Como consequência, é possível disparar milhares de coroutines ao mesmo tempo sem se preocupar com o esgotamento de recursos. Isso é ótimo porque é muito comum lidar com concorrência e execuções assíncronas no backend, e a boa notícia é que frameworks como Spring estão começando a dar suporte a coroutines!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | coRouter {</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GET( "/customers/{id}" ) { req -&gt;</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val body = repository.findById(req.pathVariable( "id" ))</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?: throw IllegalArgumentException( "Customer not found" )</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerResponse.ok().bodyAndAwait(body)</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p> } |
coRouter é uma coroutine definida pelo Spring Framework O Spring Framework na sua próxima versão 5.2 dará suporte a coroutines. Um exemplo é o coRouter, que dispara uma coroutine para cada requisição recebida em um endpoint da aplicação.
Algumas desvantagens podem surgir na hora escolher Kotlin como linguagem para backend. Uma delas pode ser a escolha de framework que pode ser um pouco limitada. Como já mencionado, o Spring está começando a dar suporte oficial a Kotlin e é um ótimo framework e já bastante utilizado, entretanto ainda não tira tanto proveito dos recursos oferecidos pela linguagem, mas isso deve mudar nas próximas releases do Spring Framework. Uma outra opção é utilizar o Ktor, um framework open-source para desenvolver aplicações backend criado pela Jetbrains, e que tira bom proveito de construções mais idiomáticas de Kotlin como DSLs. Por isso, as opções ainda podem ser um pouco limitadas, e frameworks mais novos podem não ser tão completos quanto se espera.
Kotlin está amadurecendo e crescendo muito rapidamente, como se pode perceber pela receptividade que a comunidade está dando a linguagem e também pelo engajamento no suporte a Kotlin em grandes projetos como o Spring, que só mostra que Kotlin realmente traz algo para os desenvolvedores. Por isso, se você ou seu time já trabalham com Java, Kotlin pode ser uma ótima linguagem para resolver alguns dos problemas encontrados no dia-a-dia quando se programa em Java, e ainda se integra facilmente ao seu ecossistema Java. Mesmo para quem não utiliza Java, Kotlin pode ainda ser uma ótima opção já que o Spring Framework é bastante maduro e popular.
Wellington Felix Estudante de Ciência da Computação pela UFPE, tem interesse nas áreas de Engenharia de Software e Programação Funcional. Faz estágio no time de Messaging da Sinch desenvolvendo com Kotlin e Java.