{"id":671775,"date":"2025-12-31T04:11:19","date_gmt":"2025-12-31T03:11:19","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=671775"},"modified":"2025-12-31T04:11:24","modified_gmt":"2025-12-31T03:11:24","slug":"avaliacao-do-kotlin-em-projetos-reais","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/pt-br\/kotlin\/2025\/12\/avaliacao-do-kotlin-em-projetos-reais\/","title":{"rendered":"Avalia\u00e7\u00e3o do Kotlin em projetos reais"},"content":{"rendered":"<p><em>Postagem convidada de <a href=\"https:\/\/www.linkedin.com\/in\/urs-peter-70a2882\/\" target=\"_blank\" rel=\"noreferrer noopener\" data-type=\"link\" data-id=\"https:\/\/bit.ly\/urs-peter-linked-in\">Urs Peter<\/a>, Engenheiro de Software S\u00eanior e Instrutor de Kotlin certificado pela JetBrains. Para leitores que preferirem uma maneira mais estruturada de adquirir conhecimentos sobre Kotlin, Urs tamb\u00e9m dirige o\u00a0<\/em><a href=\"https:\/\/academy.xebia.com\/upskilling\/kotlin-academy\/\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Programa de Qualifica\u00e7\u00e3o em Kotlin<\/em><\/a><em> da Xebia Academy.<\/em><\/p>\n<p><em>Esta \u00e9 a segunda postagem da s\u00e9rie <strong>O guia definitivo para a ado\u00e7\u00e3o bem-sucedida do Kotlin em um ambiente dominado pelo Java<\/strong>, que acompanha o processo de ado\u00e7\u00e3o do Kotlin por equipes reais, desde a curiosidade de um s\u00f3 desenvolvedor at\u00e9 uma transforma\u00e7\u00e3o geral da empresa.<\/em><\/p>\n<p>Leia a primeira parte: <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/10\/getting-started-with-kotlin-for-java-developers\/\" target=\"_blank\" rel=\"noreferrer noopener\">Como iniciar a ado\u00e7\u00e3o do Kotlin por desenvolvedores em Java<\/a><\/p>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<h2 class=\"wp-block-heading\"><strong>O est\u00e1gio de avalia\u00e7\u00e3o: o Kotlin como mais que uma brincadeira<\/strong><\/h2>\n<p>Depois que voc\u00ea sentir seguran\u00e7a sobre o Kotlin em testes, ser\u00e1 a hora de uma avalia\u00e7\u00e3o mais substancial. H\u00e1 duas abordagens principais:<\/p>\n<ol>\n<li><a href=\"#1.-build-a-new-microservice\/application-in-kotlin\" data-type=\"link\" data-id=\"https:\/\/blog.jetbrains.com\/#1.-build-a-new-microservice\/application-in-kotlin\">Desenvolver um novo microsservi\u00e7o ou aplicativo em Kotlin<\/a><\/li>\n<li><a href=\"#2.-extend\/convert-an-existing-java-application\" data-type=\"link\" data-id=\"https:\/\/blog.jetbrains.com\/#2.-extend\/convert-an-existing-java-application\">Ampliar ou converter um aplicativo em Java j\u00e1 existente<\/a><\/li>\n<\/ol>\n<h3 id=\"1.-build-a-new-microservice\/application-in-kotlin\" class=\"wp-block-heading\"><strong>1. Desenvolver um novo microsservi\u00e7o ou aplicativo em Kotlin<\/strong><\/h3>\n<p>Come\u00e7ar do zero com um novo aplicativo ou microsservi\u00e7o oferece a experi\u00eancia completa do Kotlin, sem as limita\u00e7\u00f5es de um c\u00f3digo antigo. Esta abordagem costuma fornecer a melhor experi\u00eancia de aprendizado e demonstra mais claramente os pontos fortes do Kotlin.<\/p>\n<div class=\"wp-block-columns is-layout-flex wp-container-3 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis: 66.66%;\">\n<p><strong>Dica de profissional<\/strong>: Obtenha a ajuda de um especialista durante este est\u00e1gio. Embora desenvolvedores tenham uma confian\u00e7a natural em suas habilidades, evitar erros iniciais, na forma de Kotlin ao estilo do Java e de uma falta de bibliotecas para Kotlin, pode evitar meses de d\u00edvida t\u00e9cnica.<\/p>\n<\/div>\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis: 33.33%;\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-646384\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/10\/unnamed-5.png\" alt=\"\" width=\"600\" height=\"400\" \/><\/figure>\n<\/div>\n<\/div>\n<p>\u00c9 assim que voc\u00ea pode evitar armadilhas comuns ao usar Kotlin a partir de um ambiente de Java:<\/p>\n<p><em>Armadilha: escolher um framework diferente do que voc\u00ea usa em Java.<\/em><\/p>\n<p>Dica: <strong>Continue com o seu framework atual<\/strong>.\u00a0<\/p>\n<p>O mais prov\u00e1vel \u00e9 que voc\u00ea estivesse usando o Spring Boot com Java; ent\u00e3o, use-o com o Kotlin, tamb\u00e9m. O Spring Boot tem suporte de primeira ao Kotlin, de modo que n\u00e3o h\u00e1 nenhum benef\u00edcio adicional em usar algo diferente. Al\u00e9m disso, voc\u00ea seria for\u00e7ado a aprender n\u00e3o apenas uma nova linguagem, mas tamb\u00e9m um novo framework, o que s\u00f3 traria mais complexidade, sem oferecer nenhuma vantagem.<\/p>\n<p><strong>Importante<\/strong>: o Spring interfere com o princ\u00edpio de &#8220;heran\u00e7a proposital&#8221; do Kotlin, o que exige que voc\u00ea marque explicitamente as classes como abertas para poder estend\u00ea-las.<\/p>\n<p>Para evitar ter que adicionar a palavra-chave &#8220;open&#8221; a todas as classes relacionadas ao Spring (como <code>@Configuration<\/code> e outras), use o seguinte plug-in de build: <a href=\"https:\/\/kotlinlang.org\/docs\/all-open-plugin.html#spring-support\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/kotlinlang.org\/docs\/all-open-plugin.html#spring-support<\/a>. Se voc\u00ea criar um projeto do Spring com a conhecida <a href=\"https:\/\/start.spring.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">ferramenta on-line &#8220;initializr&#8221;, do Spring<\/a>, esse plug-in de build j\u00e1 estar\u00e1 configurado para voc\u00ea.<\/p>\n<p><em>Armadilha: escrever em Kotlin ao estilo do Java e usando APIs comuns do Java, em vez da biblioteca-padr\u00e3o do Kotlin:<\/em><em>\u00a0<\/em><\/p>\n<p>Esta lista pode ser muito longa; ent\u00e3o, vamos nos concentrar nas armadilhas mais comuns:<\/p>\n<h4 class=\"wp-block-heading\"><em>Armadilha 1: usar o Java Stream, em vez das Kotlin Collections<\/em><\/h4>\n<p>Dica: <strong>Sempre use as Kotlin Collections.<\/strong><\/p>\n<p>As Kotlin Collections t\u00eam total interoperabilidade com as Java Collections, mas v\u00eam equipadas com fun\u00e7\u00f5es de alta ordem, simples, diretas e ricas em recursos, que tornam o Java Stream obsoleto.\u00a0<\/p>\n<p>Veja abaixo um exemplo que visa selecionar os 3 produtos mais vendidos por faturamento (pre\u00e7o \u00d7 n\u00famero vendido), agrupados por categoria:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">record Product(String name, String category, double price, int sold){}\n\nList products = List.of(\n           new Product(\"Lollipop\", \"sweets\", 1.2, 321),\n           new Product(\"Broccoli\", \"vegetable\", 1.8, 5);\n\nMap&lt;String, List&gt; top3RevenueByCategory =\n       products.stream()\n          .collect(Collectors.groupingBy(\n                Product::category,\n                Collectors.collectingAndThen(\n                    Collectors.toList(),\n                    list -&gt; list.stream()\n                              .sorted(Comparator.comparingDouble(\n                                  (Product p) -&gt; p.price() * p.sold())\n                                   .reversed())\n                                   .limit(3)\n                                   .toList()\n                       \t\t)\n          )\n);<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val top3RevenueByCategory: Map&lt;String, List&gt; =\n   products.groupBy { it.category }\n       .mapValues { (_, list) -&gt;\n           list.sortedByDescending { it.price * it.sold }.take(3)\n       }<\/pre>\n<p>A interoperabilidade do Kotlin com o Java permite que voc\u00ea trabalhe com classes e records do Java como se fossem nativos do Kotlin, embora voc\u00ea tamb\u00e9m possa usar uma classe (de dados) do Kotlin como alternativa.<\/p>\n<h4 class=\"wp-block-heading\"><em>Armadilha 2: continuar usando tipos &#8220;Optional&#8221; no Java.<\/em><\/h4>\n<p>Dica: <strong>Adote os tipos &#8220;Nullable&#8221;<\/strong>.\u00a0<\/p>\n<p>Uma das principais raz\u00f5es pelas quais desenvolvedores em Java mudam para o Kotlin \u00e9 o suporte incorporado a valores nulos, que d\u00e1 adeus \u00e0s NullPointerExceptions. Assim, tente usar apenas tipos &#8220;Nullable&#8221;. N\u00e3o use mais tipos &#8220;Optional&#8221;. Voc\u00ea ainda tem tipos &#8220;Optional&#8221; nas suas interfaces? \u00c9 assim que voc\u00ea se livra deles facilmente, convertendo-os em tipos &#8220;Nullable&#8221;:<\/p>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/Let\u2019s assume this repository is hard to change, because it\u2019s a library you depend on\nclass OrderRepository {\n      \/\/it returns Optional, but we want nullable types\n      fun getOrderBy(id: Long): Optional = \u2026\n}\n\n\/\/Simply add an extension method and apply the orElse(null) trick\nfun OrderRepository.getOrderByOrNull(id: Long): Order? = \n                                    getOrderBy(id).orElse(null)\n\n\/\/Now enjoy the safety and ease of use of nullable types:\n\n\/\/Past:\n val g = repository.getOrderBy(12).flatMap { product -&gt;\n     product.goody.map { it.name }\n}.orElse(\"No goody found\")\n\n\/\/Future:\n val g = repository.getOrderByOrNull(12)?.goody?.name ?: \"No goody found\"<\/pre>\n<h4 class=\"wp-block-heading\"><em>Armadilha 3: continuar usando wrappers est\u00e1ticos.<\/em><\/h4>\n<p>Dica: <strong>Adote m\u00e9todos de extens\u00e3o<\/strong>.\u00a0<\/p>\n<p>Os m\u00e9todos de extens\u00e3o oferecem muitas vantagens:<\/p>\n<ul>\n<li>Eles tornam o seu c\u00f3digo muito mais fluente e leg\u00edvel que os wrappers.<\/li>\n<li>A complementa\u00e7\u00e3o de c\u00f3digo \u00e9 capaz de encontr\u00e1-los, o que n\u00e3o acontece com os wrappers.<\/li>\n<li>Como os m\u00e9todos de extens\u00e3o precisam ser importados, eles permitem que voc\u00ea use os recursos adicionados de forma seletiva, em um trecho espec\u00edfico do seu aplicativo.<\/li>\n<\/ul>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/Very common approach in Java to add additional helper methods\npublic class DateUtils {\n      public static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = \n           DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\");\n\n      public String formatted(LocalDateTime dateTime, \n\t\t              DateTimeFormatter formatter) {\n         return dateTime.format(formatter);\n      }\n\n      public String formatted(LocalDateTime dateTime) {\n         return formatted(dateTime, DEFAULT_DATE_TIME_FORMATTER);\n      }\n}\n\n\/\/Usage\n formatted(LocalDateTime.now());\n<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val DEFAULT_DATE_TIME_FORMATTER: DateTimeFormatter = \nDateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\")\n\n\/\/Use an extension method, including a default argument, which omits the need for an overloaded method.\u00a0\nfun LocalDateTime.asString(\n\u00a0\u00a0\u00a0formatter: DateTimeFormatter = DEFAULT_DATE_TIME_FORMATTER): String =\u00a0\n      this.format(formatter)\n\n\/\/Usage\nLocalDateTime.now().formatted()<\/pre>\n<p>Tenha em mente que Kotlin oferece m\u00e9todos e vari\u00e1veis de n\u00edvel superior. Isso implica que \u00e9 poss\u00edvel simplesmente declarar, por exemplo, <em><code>DEFAULT_DATE_TIME_FORMATTER<\/code><\/em> como sendo de n\u00edvel superior, sem precisar associ\u00e1-lo a um objeto, como acontece no Java.<\/p>\n<h4 class=\"wp-block-heading\"><em>Armadilha 4: usar as APIs do Java (de forma desajeitada)<\/em><\/h4>\n<p>Dica: <strong>Use o elegante equivalente do Kotlin.\u00a0<\/strong><\/p>\n<p>A biblioteca-padr\u00e3o do Kotlin usa m\u00e9todos de extens\u00e3o, que tornam as bibliotecas do Java muito mais amig\u00e1veis, apesar de a implementa\u00e7\u00e3o subjacente ainda ser em Java. Quase todas as principais bibliotecas e frameworks de terceiros, como o Spring, fizeram o mesmo.<\/p>\n<p><strong>Exemplo de biblioteca-padr\u00e3o:<\/strong><\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">String text;\ntry (\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var reader = new BufferedReader(\n                  new InputStreamReader(new FileInputStream(\"out.txt\"), \n            StandardCharsets.UTF_8))) {\n\u00a0\u00a0\u00a0text = reader\n            .lines()\n            .collect(Collectors.joining(System.lineSeparator()));\n}\nSystem.out.println(\"Downloaded text: \" +\u00a0 text + \"n\");<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/Kotlin has enhanced the Java standard library with many powerful extension methods, like on java.io.*, which makes input stream processing a snap due to its fluent nature, fully supported by code completion\n\nval text = FileInputStream(\"path\").use {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0     it.bufferedReader().readText()\n           }\nprintln(\"Downloaded text: $textn\");<\/pre>\n<p><strong>Exemplo no Spring:<\/strong><br \/><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">final var books =\u00a0 RestClient.create()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.get()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.uri(\"http:\/\/...\/api\/books\")\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.retrieve()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.body( new ParameterizedTypeReference&lt;List&gt;(){}); \/\/ \u21e6 inconvenient ParameterizedTypeReference<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import org.springframework.web.client.body\nval books = RestClient.create()\n\u00a0\u00a0\u00a0.get()\n\u00a0\u00a0\u00a0.uri(\"http:\/\/...\/api\/books\")\n\u00a0\u00a0\u00a0.retrieve()\n\u00a0\u00a0\u00a0.body&lt;List&gt;() \/\/\u21e6 Kotlin offers an extension that only requires the type without the need for a ParameterizedTypeReference<\/pre>\n<h4 class=\"wp-block-heading\"><em>Armadilha 5: usar um arquivo separado para cada classe p\u00fablica<\/em><\/h4>\n<p>Dica: <strong>Combine classes p\u00fablicas relacionadas em um s\u00f3 arquivo.\u00a0<\/strong><\/p>\n<p>Isso permite ter uma boa compreens\u00e3o de como um (sub)dom\u00ednio est\u00e1 estruturado, sem ter que navegar por d\u00fazias de arquivos.<\/p>\n<p><strong>Java<\/strong><\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-647331\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/10\/unnamed-15.png\" alt=\"\" width=\"1114\" height=\"934\" \/><\/figure>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/For domain classes consider data classes - see why below\ndata class User(val email: String,\n            \/\/Use nullable types for safety and expressiveness\n\u00a0 \u00a0        val avatarUrl: URL? = null,\u00a0\n           var isEmailVerified: Boolean)\n\ndata class Account(val user:User,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val address: Address,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val mfaEnabled:Boolean,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val createdAt: Instant)\n\ndata class Address(val street: String,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val city: String,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 val postalCode: String)<\/pre>\n<h4 class=\"wp-block-heading\"><em>Armadilha 6: adotar o paradigma mut\u00e1vel de programa\u00e7\u00e3o<\/em><\/h4>\n<p>DIca: <strong>adote a imutabilidade \u2014 o padr\u00e3o no Kotlin<\/strong><\/p>\n<p>A tend\u00eancia \u00e9 clara em muitas linguagens de programa\u00e7\u00e3o, incluindo o Java: a imutabilidade est\u00e1 ganhando da mutabilidade.\u00a0<\/p>\n<p>O motivo \u00e9 simples: a imutabilidade evita efeitos colaterais indesejados, tornando o c\u00f3digo mais seguro, previs\u00edvel e f\u00e1cil de raciocinar. Ela tamb\u00e9m simplifica a concorr\u00eancia, pois dados imut\u00e1veis podem ser compartilhados livremente entre threads, sem risco de condi\u00e7\u00f5es de corrida.<\/p>\n<p>\u00c9 por isso que a maioria das linguagens modernas, incluindo o Kotlin, ou enfatizam a imutabilidade como padr\u00e3o, ou a encorajam fortemente. No Kotlin, a imutabilidade \u00e9 o padr\u00e3o, embora a mutabilidade continue sendo uma op\u00e7\u00e3o, quando realmente necess\u00e1ria.<\/p>\n<p>Aqui est\u00e1 um guia r\u00e1pido do <strong>power pack de imutabilidade<\/strong> do Kotlin:<\/p>\n<p>1. Use <code>val<\/code>, em vez de <code>var<\/code><\/p>\n<p>Prefira usar <code>val<\/code>, em vez de <code>var<\/code>. Se voc\u00ea usar <code>var<\/code> quando <code>val<\/code> poderia ter sido usado, o IntelliJ IDEA lhe enviar\u00e1 uma notifica\u00e7\u00e3o.\u00a0<\/p>\n<p>2. Use classes de dados (imut\u00e1veis) com <code>copy(...)<\/code><\/p>\n<p>Em classes relacionadas a dom\u00ednios, use classes <code>data<\/code> com <code>val<\/code>. As classes <code>data<\/code> do Kotlin costumam ser comparadas aos <code>records<\/code> do Java. Embora haja alguma sobreposi\u00e7\u00e3o, as classes <code>data<\/code> oferecem um recurso matador: <code>copy(...)<\/code>, cuja aus\u00eancia torna muito trabalhoso transformar <code>record<\/code>, o que muitas vezes \u00e9 necess\u00e1rio na l\u00f3gica de neg\u00f3cios:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/only immutable state\npublic record Person(String name, int age) {\n\u00a0\u00a0\u00a0\/\/Lack of default parameters requires overloaded constructor\n\u00a0\u00a0\u00a0public Person(String name) {\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(name, 0);\n\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\/\/+ due to lack of String interpolation\n\u00a0 public String sayHi() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return \"Hello, my name is \" + name + \" and I am \" + age + \" years old.\";\n\u00a0\u00a0\u00a0}\n}\n\n\/\/Usage\nfinal var jack = new Person(\"Jack\", 42);\njack: Person[name=Jack, age=5]\n\n\/\/The issue is here: transforming a record requires manually copying the identical state to the new instance \u2639\ufe0f\nfinal var fred = new Person(\"Fred\", jack.name);<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/also supports mutable state (var)\ndata class Person(val name: String,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val age: Int = 0) {\n\u00a0 \/\/string interpolation\n\u00a0 fun sayHi() = \"Hi, my name is $name and I am $age years old.\"\n}\nval jack = Person(\"Jack\", 42)\njack: Person(name=Jack, age=42)\n\n\/\/Kotlin offers the copy method, which, due to the \u2018named argument\u2019 feature, allows you to only adjust the state you want to change \ud83d\ude03\nval fred = jack.copy(name = \"Fred\")\nfred: Person(name=Fred, age=42)<\/pre>\n<p>Ent\u00e3o, use classes &#8220;data&#8221; quando relacionadas a dom\u00ednios, sempre que poss\u00edvel. Sua natureza imut\u00e1vel garante uma experi\u00eancia segura, concisa e tranquila ao trabalhar com o n\u00facleo do seu aplicativo.\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<p>Dica: <strong>prefira cole\u00e7\u00f5es imut\u00e1veis, em vez de mut\u00e1veis<\/strong><\/p>\n<p>Cole\u00e7\u00f5es imut\u00e1veis t\u00eam vantagens claras quanto \u00e0 seguran\u00e7a das threads, podem ser passadas adiante com seguran\u00e7a e s\u00e3o mais f\u00e1ceis de raciocinar. Embora Java ofere\u00e7a alguns recursos de imutabilidade para cole\u00e7\u00f5es, \u00e9 perigoso usar esses recursos, porque podem facilmente causar exce\u00e7\u00f5es em tempo de execu\u00e7\u00e3o:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">List.of(1,2,3).add(4); \u274cunsafe \ud83d\ude2c! .add(...) compiles, but throws UnsupportedOperationException<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/The default collections in Kotlin are immutable (read-only)\nlistOf(1,2,3).add(4); \u00a0\/\/\u2705safe: does not compile\n\nval l0 = listOf(1,2,3)\u00a0\nval l1 = l0 + 4 \/\/\u2705safe: it will return a new list containing the added element\nl1 shouldBe listOf(1,2,3,4) \/\/\u2705<\/pre>\n<p>O mesmo se aplica ao uso de <code>Collections.<em>unmodifiableList(...)<\/em><\/code>, que n\u00e3o s\u00f3 \u00e9 inseguro, mas tamb\u00e9m requer aloca\u00e7\u00e3o adicional:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class PersonRepo {\n\u00a0\u00a0\u00a0private final List cache = new ArrayList();\n\u00a0\u00a0\u00a0\/\/ Java \u2013 must clone or wrap every call\n\u00a0\u00a0\u00a0public List getItems() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Collections.unmodifiableList(cache); \u00a0 \/\/\u26a0\ufe0fextra alloc\n\u00a0\u00a0\u00a0}\n}\n\n\/\/Usage\npersonRepo.getItems().add(joe) \u274cunsafe \ud83d\ude2c! .add(...) can be called but throws UnsupportedOperationException<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class PersonRepo {\n\n\/\/The need to type \u2018mutable\u2019 for mutable collections is intentional: Kotlin wants you to use immutable ones by default. But sometimes you need them:\n\n\u00a0\u00a0\u00a0private val cache: MutableList = mutableListOf()\n\n\u00a0\u00a0\u00a0fun items(): List = cache \/\/\u2705safe: though the underlying collection is mutable, by returning it as its superclass List, it only exposes the read-only interface\n\n}\n\n\/\/Usage\npersonRepo.items().add(joe) \/\/\u2705safe:\ud83d\ude2c! Does not compile<\/pre>\n<p>Quando se trata de concorr\u00eancia, deve-se preferir usar estruturas de dados imut\u00e1veis, incluindo cole\u00e7\u00f5es. No Java, \u00e9 preciso um esfor\u00e7o adicional com cole\u00e7\u00f5es especiais, que oferecem uma API diferente ou limitada, como <code>CopyOnWriteArrayList<\/code>. Por outro lado, no Kotlin, <code>List<\/code>, que \u00e9 somente para leitura, funciona para quase todos os casos de uso.\u00a0<\/p>\n<p>Se voc\u00ea precisar de cole\u00e7\u00f5es mut\u00e1veis e seguras para threads, o Kotlin oferece cole\u00e7\u00f5es persistentes (<code>persistentListOf(...)<\/code>, <code>persistentMapOf(...)<\/code>), que compartilham todas a mesma interface poderosa.<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ConcurrentHashMap persons = new ConcurrentHashMap();\npersons.put(\"Alice\", 23);\npersons.put(\"Bob\", \u00a0 21);\n\n\/\/not fluent and data copying going on\nMap incPersons = new HashMap(persons.size());\npersons.forEach((k, v) -&gt; incPersons.put(k, v + 1));\n\n\/\/wordy and data copying going on\npersons\n\u00a0\u00a0\u00a0.entrySet()\n\u00a0\u00a0\u00a0.stream()\n\u00a0\u00a0\u00a0.forEach(entry -&gt;\u00a0\n      entry.setValue(entry.getValue() + 1));<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">persistentMapOf(\"Alice\" to 23, \"Bob\" to 21)\n\u00a0\u00a0\u00a0      .mapValues { (key, value) -&gt; value + 1 } \/\/\u2705same rich API like any other Kotlin Map type and not data copying going on<\/pre>\n<h4 class=\"wp-block-heading\"><em>Armadilha 7: continuar usando builders (ou pior ainda, tentar usar o Lombok)\u00a0<\/em><\/h4>\n<p>Dica: <strong>Use argumentos nomeados.<\/strong><\/p>\n<p>Builders s\u00e3o muito comuns no Java. Embora sejam convenientes, adicionam mais c\u00f3digo, s\u00e3o inseguros e aumentam a complexidade. Eles n\u00e3o t\u00eam utilidade no Kotlin, pois um \u00fanico recurso da linguagem os torna obsoletos: os argumentos nomeados.\u00a0<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public record Person(String name, int age) {\n\n\u00a0\u00a0\u00a0\/\/ Builder for Person\n\u00a0\u00a0\u00a0public static class Builder {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private String name;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private int age;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Builder() {}\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Builder name(String name) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.name = name;\n\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Builder age(int age) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.age = age;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Person build() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return new Person(name, age);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0}\n}\n\n\/\/Usage\nnew JPerson.Builder().name(\"Jack\").age(36).build(); \/\/compiles and succeeds at runtime\n\nnew JPerson.Builder().age(36).build(); \/\/\u274cunsafe \ud83d\ude2c: compiles but fails at runtime.<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">data class Person(val name: String, val age: Int = 0)\n\n\/\/Usage - no builder, only named arguments.\nPerson(name = \"Jack\") \/\/\u2705safe: if it compiles, it always succeeds at runtime\nPerson(name = \"Jack\", age = 36) \/\/\u2705<\/pre>\n<h3 id=\"2.-extend\/convert-an-existing-java-application\" class=\"wp-block-heading\"><strong>2. Ampliar ou converter um aplicativo em Java j\u00e1 existente<\/strong><\/h3>\n<p>Se voc\u00ea n\u00e3o tiver a op\u00e7\u00e3o de desenvolver do zero uma aplica\u00e7\u00e3o para experimentar o Kotlin, a solu\u00e7\u00e3o \u00e9 <a href=\"https:\/\/www.jetbrains.com\/help\/idea\/get-started-with-kotlin.html#add-kotlin-dependency\" target=\"_blank\" rel=\"noreferrer noopener\">adicionar novos recursos ou m\u00f3dulos inteiros em Kotlin a uma base de c\u00f3digo j\u00e1 existente em Java<\/a>. Gra\u00e7as \u00e0 interoperabilidade transparente entre o Kotlin e o Java, voc\u00ea pode escrever c\u00f3digo Kotlin que parece ser Java para ser chamado a partir de c\u00f3digo Java. Esta abordagem permite:<\/p>\n<ul>\n<li>Uma migra\u00e7\u00e3o gradual, sem uma reprograma\u00e7\u00e3o dram\u00e1tica<\/li>\n<li>Testes do Kotlin no mundo real, no seu contexto espec\u00edfico<\/li>\n<li>Aumentar a confian\u00e7a da equipe atrav\u00e9s de c\u00f3digo de produ\u00e7\u00e3o em Kotlin<\/li>\n<\/ul>\n<p>Em vez de come\u00e7ar <em>com alguma coisa qualquer<\/em>, considere estas abordagens diferentes:<\/p>\n<p><strong>De fora para dentro:<\/strong><\/p>\n<p>Comece pela parte das &#8220;folhas&#8221; do seu aplicativo \u2014 por exemplo, controlador, tarefa em lote, etc. \u2014 e depois v\u00e1 avan\u00e7ando para o dom\u00ednio central. Isso lhe dar\u00e1 estas vantagens:\u00a0<\/p>\n<ul>\n<li><strong>Isolamento em tempo de compila\u00e7\u00e3o<\/strong>: as classes das &#8220;folhas&#8221; raramente t\u00eam outras coisas dependendo <em>delas<\/em>; ent\u00e3o, voc\u00ea pode mud\u00e1-las para Kotlin e ainda fazer build com o resto do sistema inalterado.<\/li>\n<li><strong>Menos edi\u00e7\u00f5es em cascata.<\/strong> Uma interface de usu\u00e1rio ou um controlador convertido pode chamar c\u00f3digo existente no dom\u00ednio do Java quase sem altera\u00e7\u00f5es, gra\u00e7as \u00e0 interoperabilidade transparente.<\/li>\n<li><strong>Solicita\u00e7\u00f5es de pull menores, revis\u00f5es mais f\u00e1ceis.<\/strong> Voc\u00ea pode migrar arquivo a arquivo ou recurso a recurso.<\/li>\n<\/ul>\n<p><strong>De dentro para fora:<\/strong><\/p>\n<p>Come\u00e7ar pelo n\u00facleo e depois prosseguir para as camadas externas costuma ser uma abordagem mais arriscada, pois isso elimina as vantagens da abordagem de fora para dentro, mencionadas acima. Por\u00e9m, \u00e9 uma abordagem vi\u00e1vel nos seguintes casos:<\/p>\n<ul>\n<li><strong>N\u00facleo muito pequeno ou autocontido.<\/strong> Se a sua camada de dom\u00ednio consistir em apenas algumas classes simples de Java (POJOs) e servi\u00e7os, pode ser barato convert\u00ea-la logo no in\u00edcio e isso pode liberar imediatamente construtos idiom\u00e1ticos (classes de dados e de valores, hierarquias seladas).<\/li>\n<li><strong>A arquitetura j\u00e1 est\u00e1 para ser redesenhada, mesmo.<\/strong> Se voc\u00ea estiver planejando refatorar invariantes ou introduzir padr\u00f5es de projeto orientado por dom\u00ednios (DDD), tais como objetos de valor ou agregados, durante a migra\u00e7\u00e3o, \u00e0s vezes pode ser mais limpo reprojetar primeiro o dom\u00ednio em Kotlin.<\/li>\n<li><strong>Contratos de seguran\u00e7a estrita contra valores nulos.<\/strong> Colocar o Kotlin no n\u00facleo transforma o dom\u00ednio em uma &#8220;fortaleza segura contra valores nulos&#8221;. As camadas externas em Java ainda podem enviar valores nulos, mas os limites se tornam expl\u00edcitos e mais f\u00e1ceis de vigiar.<\/li>\n<\/ul>\n<p><strong>M\u00f3dulo a m\u00f3dulo<\/strong><\/p>\n<ul>\n<li>Se a sua arquitetura estiver organizada por recursos, em vez de em camadas, e os m\u00f3dulos tiverem um tamanho administr\u00e1vel, ent\u00e3o \u00e9 uma boa estrat\u00e9gia converter os m\u00f3dulos um a um.<\/li>\n<\/ul>\n<p><strong>Recursos de linguagem para converter Java em Kotlin<\/strong><\/p>\n<p>O Kotlin oferece uma variedade de recursos \u2014 principalmente anota\u00e7\u00f5es \u2014 que permitem que o seu c\u00f3digo em Kotlin se comporte como Java nativo. Isso \u00e9 especialmente valioso em ambientes h\u00edbridos, nos quais Kotlin e Java coexistam na mesma base de c\u00f3digo.<br \/><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Person @JvmOverloads constructor(val name: String,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 var age: Int = 0) {\n\u00a0 companion object {\n\n\u00a0 @JvmStatic\n\u00a0 @Throws(InvalidNameException::class)\n\u00a0 fun newBorn(name: String): Person = if (name.isEmpty())\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw InvalidNameException(\"name not set\")\n\u00a0\u00a0\u00a0\u00a0\u00a0else Person(name, 0)\n\n\u00a0\u00a0\u00a0@JvmField\n\u00a0\u00a0\u00a0val LOG = LoggerFactory.getLogger(KPerson.javaClass)\n\u00a0\u00a0}\n}<\/pre>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/thanks to @JvmOverloads an additional constructor is created, propagating Kotlin\u2019s default arguments to Java\nvar john =\u00a0 new Person(\"John\");\n\n\/\/Kotlin automatically generates getters (val) and setters (var) for Java\njohn.setAge(23);\nvar name = ken.getName();\n\n\/\/@JvmStatic and @JvmField all accessing (companion) object fields and methods as statics in Java\n\n\/\/Without @JvmStatic it would be: Person.Companion.newBorn(...)\nvar ken =\u00a0 Person.newBorn(\"Ken\");\u00a0\n\n\/\/Without @JvmField it would be: Person.Companion.LOG\nPerson.LOG.info(\"Hello World, Ken ;-)\");\n\n\/\/@Throws(...) will put the checked Exception in the method signature \ntry {\n\u00a0 Person ken =\u00a0 Person.newBorn(\"Ken\");\n} catch (InvalidNameException e) {\n\u00a0 \/\/\u2026\n}<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@file:JvmName(\"Persons\")\npackage org.abc\n\n@JvmName(\"prettyPrint\")\n\nfun Person.pretty() =\n\u00a0 \u00a0 \u00a0 Person.LOG.info(\"$name is $age old\")<\/pre>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/@JvmName for files and methods makes accessing static fields look like Java: without it would be: PersonKt.pretty(...)\nPersons.prettyPrint(ken)<\/pre>\n<p><strong>O conversor de Java para Kotlin do IntelliJ IDEA<\/strong><\/p>\n<p>O IntelliJ IDEA oferece um conversor de Java para Kotlin; ent\u00e3o, teoricamente, essa ferramenta pode fazer isso para voc\u00ea. Por\u00e9m, o c\u00f3digo resultante est\u00e1 longe de ser perfeito; assim, use-o apenas como ponto de partida. A partir da\u00ed, converta-o em uma representa\u00e7\u00e3o mais apropriada para o Kotlin. Discutiremos mais este assunto na postagem final desta s\u00e9rie do blog: <em>Fatores de sucesso para a ado\u00e7\u00e3o do Kotlin em larga escala<\/em>.<\/p>\n<p>Muito provavelmente, usar o Java como ponto de partida far\u00e1 voc\u00ea escrever em Kotlin com o estilo do Java, o que lhe trar\u00e1 alguns benef\u00edcios, mas n\u00e3o liberar\u00e1 o poderoso potencial do Kotlin. Por isso, escrever um novo aplicativo \u00e9 a abordagem que prefiro.\u00a0<\/p>\n<h3 class=\"wp-block-heading\">Em seguida nesta s\u00e9rie<\/h3>\n<p>Esta parte da nossa s\u00e9rie de postagens no blog, <em>O guia definitivo para a ado\u00e7\u00e3o bem-sucedida do Kotlin em um ambiente dominado pelo Java<\/em>, demonstrou como experimentos com o Kotlin podem evoluir para c\u00f3digo de produ\u00e7\u00e3o. Nossa pr\u00f3xima postagem se concentrar\u00e1 no lado humano da ado\u00e7\u00e3o: convencer os seus colegas. Ela explicar\u00e1 como apresentar argumentos claros e orientados pelo c\u00f3digo, como guiar novos desenvolvedores e criar uma comunidade de Kotlin pequena, mas duradoura dentro da sua equipe.<\/p>\n<p><em>Artigo original em ingl\u00eas por:<\/em><\/p>\n<div class=\"about-author \">\n<div class=\"about-author__box\">\n<div class=\"row\">\n<div class=\"about-author__box-img\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/10\/a3f7-400o400o1-QYUavRYyARnAVJLCpM1m8M.webp\" alt=\"\" \/><\/div>\n<div class=\"about-author__box-text\">\n<h4>Urs Peter<\/h4>\n<p>Urs \u00e9 um calejado engenheiro de software, arquiteto de solu\u00e7\u00f5es, palestrante e instrutor, com mais de 20 anos de experi\u00eancia no desenvolvimento de sistemas resilientes, escal\u00e1veis e cr\u00edticos, a maioria envolvendo Kotlin e Scala.<\/p>\n<p>Al\u00e9m de seu trabalho como consultor, ele tamb\u00e9m \u00e9 um instrutor apaixonado e autor de uma grande variedade de treinamentos, desde cursos das linguagens Kotlin e Scala at\u00e9 treinamentos em arquiteturas como microsservi\u00e7os e arquiteturas dirigidas por eventos.<\/p>\n<p>Sendo uma pessoa por natureza voltada para outras pessoas, ele adora compartilhar conhecimentos, inspirar e ser inspirado por colegas em encontros e congressos. Urs \u00e9 um instrutor de Kotlin certificado pela JetBrains.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n    <div class=\"about-author \">\n        <div class=\"about-author__box\">\n            <div class=\"row\">\n                <div class=\"about-author__box-img\">\n                    <img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/08\/photo_2021-08-03_15-27-43-200x200.jpg\" width=\"200\" height=\"200\" alt=\"Alyona Chernyaeva\" loading=\"lazy\"  class=\"avatar avatar-200 wp-user-avatar wp-user-avatar-200 photo avatar-default\">\n                <\/div>\n                <div class=\"about-author__box-text\">\n                                            <h4>Alyona Chernyaeva<\/h4>\n                                                        <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n","protected":false},"author":1086,"featured_media":671777,"comment_status":"closed","ping_status":"closed","template":"","categories":[],"tags":[],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/671775"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/users\/1086"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/comments?post=671775"}],"version-history":[{"count":3,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/671775\/revisions"}],"predecessor-version":[{"id":671801,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/671775\/revisions\/671801"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media\/671777"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media?parent=671775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/categories?post=671775"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/tags?post=671775"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/cross-post-tag?post=671775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}