{"id":671827,"date":"2025-12-31T17:59:09","date_gmt":"2025-12-31T16:59:09","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=671827"},"modified":"2025-12-31T17:59:14","modified_gmt":"2025-12-31T16:59:14","slug":"como-aumentar-a-adocao-do-kotlin-na-sua-empresa","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/pt-br\/kotlin\/2025\/12\/como-aumentar-a-adocao-do-kotlin-na-sua-empresa\/","title":{"rendered":"Como aumentar a ado\u00e7\u00e3o do Kotlin na sua empresa"},"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 terceira 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><strong>Todas as partes da s\u00e9rie:<\/strong><\/p>\n<ol>\n<li><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><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/10\/evaluating-kotlin-in-real-projects\/\" target=\"_blank\" rel=\"noreferrer noopener\" data-type=\"link\" data-id=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/10\/evaluating-kotlin-in-real-projects\/\">Avalia\u00e7\u00e3o do Kotlin em projetos reais<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/11\/growing-kotlin-adoption-in-your-company\/\" target=\"_blank\" rel=\"noreferrer noopener\">Como aumentar a ado\u00e7\u00e3o do Kotlin na sua empresa<\/a><\/li>\n<\/ol>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<h2 class=\"wp-block-heading\"><strong>Pregando a palavra: ganhe os cora\u00e7\u00f5es e mentes dos seus colegas desenvolvedores<\/strong><\/h2>\n<p>A esta altura, voc\u00ea j\u00e1 deve ter o n\u00facleo de uma equipe que est\u00e1 convencida dos benef\u00edcios do Kotlin. Agora vem a fase cr\u00edtica: como expandir a ado\u00e7\u00e3o?\u00a0<\/p>\n<p>Nesta fase, o essencial \u00e9 ganhar os cora\u00e7\u00f5es e mentes dos desenvolvedores Java c\u00e9ticos. Tanto fatores objetivos quanto subjetivos podem fazer diferen\u00e7a aqui:<\/p>\n<p>Fator objetivo: o c\u00f3digo<\/p>\n<ul>\n<li>Deixe o c\u00f3digo falar por si s\u00f3<\/li>\n<\/ul>\n<p>Fatores subjetivos: apoie e conecte os desenvolvedores<\/p>\n<ul>\n<li>Facilite a assimila\u00e7\u00e3o<\/li>\n<li>Ofere\u00e7a material de autoestudo<\/li>\n<li>Estabele\u00e7a uma comunidade interna de Kotlin<\/li>\n<li>Tenha paci\u00eancia\u2026<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\"><strong>Deixe o c\u00f3digo falar por si s\u00f3<\/strong><\/h3>\n<p>Dobre a aposta na experi\u00eancia que voc\u00ea ganhou ao (re)escrever um aplicativo em Kotlin e mostre os benef\u00edcios de forma tang\u00edvel e acess\u00edvel:<\/p>\n<ul>\n<li><strong>N\u00e3o fale, mostre<\/strong>: apresente os ganhos de concis\u00e3o do Kotlin, comparando trechos de c\u00f3digo em Java e em Kotlin.\u00a0<\/li>\n<li><strong>Afaste a perspectiva para os paradigmas gerais<\/strong>: o Kotlin n\u00e3o \u00e9 s\u00f3 <em>diferente<\/em> do Java; ele foi criado sobre uma base de seguran\u00e7a, concis\u00e3o visando m\u00e1xima legibilidade e facilidade de manuten\u00e7\u00e3o, extensibilidade e fun\u00e7\u00f5es tratadas como tendo a mais alta import\u00e2ncia. Juntos, esses paradigmas resolvem limita\u00e7\u00f5es fundamentais do Java, mas ainda mant\u00eam total interoperabilidade com o ecossistema do Java.<\/li>\n<\/ul>\n<p>Veja alguns exemplos tang\u00edveis:<\/p>\n<p><strong>1. Seguran\u00e7a contra valores nulos: o fim dos erros de bilh\u00f5es de d\u00f3lares\u00a0<\/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=\"\">\/\/This is why we have the billion-dollar mistake (not only in Java\u2026)\nBooking booking = null; \/\/\ud83e\udd28 This is allowed but causes:\nbooking.destination; \/\/Runtime error \ud83d\ude31\n\nOptional booking = null; \/\/Optionals aren\u2019t safe from null either: \ud83e\udd28\nbooking.map(Destination::destination); \/\/Runtime error \ud83d\ude31<\/pre>\n<p>Com o tempo, o Java adicionou alguns recursos de seguran\u00e7a contra valores nulos, como &#8220;Optional&#8221; e &#8220;Annotations&#8221; (<code>@NotNull<\/code>, etc.), mas falhou em resolver este problema fundamental. Al\u00e9m disso, o projeto <a href=\"https:\/\/openjdk.org\/projects\/valhalla\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valhalla<\/a> (tipos &#8220;Null-Restricted&#8221; e &#8220;Nullable&#8221;) n\u00e3o trar\u00e1 seguran\u00e7a contra valores nulos para o Java; apenas dar\u00e1 mais op\u00e7\u00f5es de escolha.\u00a0<\/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=\"\">\/\/Important to realize that null is very restricted in Kotlin:\nval booking:Booking? = null \/\/\u2026null can only be assigned to Nullable types \u2705\u00a0\nval booking:Booking = null \/\/null assigned to a Non-nullable types yields a Compilation error \ud83d\ude03\u00a0\n\nbooking.destination \/\/unsafely accessing a nullable type directly causes a Compilation error \ud83d\ude03\nbooking?.destination \/\/only safe access is possible\u00a0 \u2705<\/pre>\n<p>A grande coisa a respeito da prote\u00e7\u00e3o do Kotlin contra valores nulos \u00e9 que ela n\u00e3o traz apenas seguran\u00e7a, mas tamb\u00e9m excelente usabilidade. Veja um exemplo cl\u00e1ssico de poder ter tudo ao mesmo tempo:<\/p>\n<p>Vamos supor que temos este dom\u00ednio:<\/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=\"\">data class Booking(val destination:Destination? = null)\ndata class Destination(val hotel:Hotel? = null)\ndata class Hotel(val name:String, val stars:Int? = null)<\/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=\"\">public record Booking(Optional destination) {\n\n\u00a0\u00a0\u00a0public Booking() { this(Optional.empty()); }\n\n\u00a0\u00a0\u00a0public Booking(Destination destination) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(Optional.ofNullable(destination));\n\u00a0\u00a0\u00a0}\n}\n\npublic record Destination(Optional hotel) {\n\n\u00a0\u00a0\u00a0public Destination() { this(Optional.empty()); }\n\n\u00a0\u00a0\u00a0public Destination(Hotel hotel) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(Optional.ofNullable(hotel));\n\u00a0\u00a0\u00a0}\n}\n\npublic record Hotel(String name, Optional stars) {\n\n\u00a0\u00a0\u00a0public Hotel(String name) {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(name, Optional.empty());\n\n\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0public Hotel(String name, Integer stars) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(name, Optional.ofNullable(stars));\n\u00a0\u00a0\u00a0}\n}<\/pre>\n<p><strong>Constru\u00e7\u00e3o de objetos<\/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=\"\">\/\/Because Optional is a wrapper, the number of nested objects grows, which doesn\u2019t help readability\nfinal Optional booking = Optional.of(new Booking(\n      Optional.of(new Destination(Optional.of(\n            new Hotel(\"Sunset Paradise\", 5))))));<\/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=\"\">\/\/Since nullability is part of the type system, no wrapper is needed: The required type or null can be used.\u00a0\nval booking:Booking? = Booking(Destination(Hotel(\"Sunset Paradise\", 5)))<\/pre>\n<p><strong>Travessia de objetos aninhados<\/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=\"\">\/\/traversing a graph of Optionals requires extensive unwrapping\nfinal var stars = \"*\".repeat(booking\n\u00a0\u00a0                        .flatMap(Booking::getDestination)\n                          .flatMap(Destination::getHotel)\n                          .map(Hotel::getStars).orElse(0)); \/\/-&gt; \"*****\"<\/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=\"\">\/\/Easily traverse a graph of nullable types with: \u2018?\u2019, use\u00a0 ?: for the \u2018else\u2019 case.\nval stars = \"*\".repeat(booking?.destination?.hotel?.stars ?: 0) \/\/-&gt; \"*****\"<\/pre>\n<p><strong>Desempacotamento de objeto aninhado<\/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=\"\">\/\/extensive unwrapping is also needed for printing a leaf\u00a0\nbooking.getDestination()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.flatMap(Destination::getHotel)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(Hotel::getName)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(String::toUpperCase)\n\u00a0\u00a0\u00a0      .ifPresent(System.out::println);<\/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=\"\">\/\/In Kotlin we have two elegant options:\n\/\/1. we can again traverse the graph with \u2018?\u2019\nbooking?.destination?.hotel.?name?.uppercase()?.also(::println)\n\n\/\/2. We can make use of Kotlin\u2019s smart-cast feature\nif(booking?.destination?.hotel != null) {\n\u00a0\u00a0\u00a0\/\/The compiler has checked that all the elements in the object graph are not null, so we can access the elements as if they were non-nullable types\n\u00a0\u00a0\u00a0println(booking.destination.hotel.uppercase())\n}<\/pre>\n<p>A falta de prote\u00e7\u00e3o contra valores nulos no Java \u00e9 um dos pontos mais problem\u00e1ticos para os desenvolvedores e leva a programa\u00e7\u00e3o defensiva e mais prolixa e a construtos diferentes (ou nenhum) para a possibilidade de valores nulos. Al\u00e9m disso, as &#8220;NullPointerExceptions&#8221; respondem por cerca de um ter\u00e7o das falhas de aplicativos (<a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2020\/11\/productive-server-side-development-with-kotlin-stories\/\" target=\"_blank\" rel=\"noreferrer noopener\">blog da JetBrains<\/a>). No Kotlin, a verifica\u00e7\u00e3o de valores nulos em tempo de compila\u00e7\u00e3o evita completamente essas falhas em tempo de execu\u00e7\u00e3o. \u00c9 por isso que at\u00e9 hoje, <strong>a seguran\u00e7a contra valores nulos \u00e9 o principal est\u00edmulo para a migra\u00e7\u00e3o para o Kotlin<\/strong>.<\/p>\n<p><strong>2. Cole\u00e7\u00f5es s\u00e3o suas amigas, n\u00e3o suas inimigas<\/strong><\/p>\n<p>O criador do Spring, Rod Johnson, disse em uma entrevista recente que n\u00e3o foram os tipos &#8220;Nullable&#8221; que o fizeram experimentar o Kotlin e sim a API complicada demais das Java Streams: <a href=\"https:\/\/youtu.be\/Rx3XZoqbi78?t=1018\" target=\"_blank\" rel=\"noreferrer noopener\">Criador do Spring: Nenhuma vontade de programar em Java<\/a>.\u00a0<\/p>\n<p>O exemplo a seguir ilustra os v\u00e1rios motivos pelos quais a API das Java Streams \u00e9 t\u00e3o horrivelmente complicada e como o Kotlin resolve todos os problemas:<\/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 Product(String name, int... ratings){}\nList products = List.of(\n\u00a0\u00a0new Product(\"gadget\", 9, 8, 7),\u00a0\n\u00a0\u00a0new Product(\"goody\", 10, 9)\n);\n\nMap maxRatingsPerProduct =\n\n\u00a0\u00a0\u00a0\/\/\ud83e\udd28 1. Stream introduces indirection\n\u00a0\u00a0\u00a0products.stream()\n\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28 1. Always to and from Stream conversion\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.collect(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28 2. Lacks extension methods, so wrappers are required\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Collectors.groupingBy(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Product::name,\n\u00a0 \u00a0         \/\/\ud83e\udd28 2. Again\u2026\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Collectors.mapping( groupedProducts -&gt;\n\u00a0               \/\/\ud83e\udd28 3. (too) low-level types, arrays, and primitives cause extra complexity\n\u00a0               \/\/\ud83e\udd28 4. No API on Array, always wrap in stream\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Arrays.stream(groupedProducts.ratings())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .max()\n                      \/\/\ud83e\udd28 5. Extra verbosity due to Optional\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0         .orElse(0.0),\n\u00a0              \/\/\ud83e\udd28 6. No named arguments: what does this do?\n\u00a0               Collectors.reducing(0, Integer::max)\n              )\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ));<\/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=\"\">\/\/\ud83d\ude03 rich and uniform Collection API - even on Java collections - due to extension methods\nval maxRatingsPerProduct = products.\n      .groupBy { it.name }\n      .mapValues { (_, groupedProducts) -&gt; \/\/\ud83d\ude03 destructuring for semantic precision\n            \/\/\ud83d\ude03 built-in nullability support, and the same API for\u00a0\n            \/\/arrays like other Collections\n            groupedProducts.flatMap { it.ratings }\n                  .maxOrNull() ?: 0\u00a0\n            }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/pre>\n<p>Gra\u00e7as ao framework uniforme de cole\u00e7\u00f5es do Kotlin, \u00e9 muito simples e direto converter entre diferentes tipos de cole\u00e7\u00f5es:<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=\"\">int[] numbers = {1, 3, 3, 5, 2};\n\nSet unique = Arrays.stream(numbers).boxed().collect(Collectors.toSet());\n\nMap evenOrOdd = unique.stream()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.collect(Collectors.toMap(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0n -&gt; n,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0n -&gt; n % 2 == 0));<\/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 numbers = arrayOf(1, 3, 3, 5, 2)\n\nval unique: Set = numbers.toSet() \/\/\ud83d\ude03 simply call to to do the conversion\n\nval evenOrOdd: Map = unique.associateWith { it % 2 == 0 }<\/pre>\n<p><strong>Efeito final:<\/strong><\/p>\n<ul>\n<li><strong>API intuitiva e rica em recursos para cole\u00e7\u00f5es:<\/strong> os pipelines s\u00e3o lidos da esquerda para a direita, como no ingl\u00eas, e n\u00e3o dentro de chamadas coletoras aninhadas.<\/li>\n<li><strong>Menos c\u00f3digo repetitivo e menos complexidade:<\/strong> sem Collectors.groupingBy, nem Stream, nem Optional, nem Arrays.stream.<\/li>\n<li><strong>Um s\u00f3 modelo mental:<\/strong> quer voc\u00ea comece com <code>List<\/code>, <code>Set<\/code>, <code>Array<\/code> ou um array primitivo, voc\u00ea sempre procura os <em>mesmos<\/em> operadores de cole\u00e7\u00f5es.<\/li>\n<li><strong>Desempenho sem dor:<\/strong> o compilador insere boxing ou unboxing apenas onde for inevit\u00e1vel; voc\u00ea escreve c\u00f3digo normal.<\/li>\n<li><strong>Seguran\u00e7a integrada contra valores nulos:<\/strong> a API de cole\u00e7\u00f5es oferece suporte total a valores nulos, com v\u00e1rios helpers, comumente com o sufixo <code>orNull(...)<\/code>.<\/li>\n<li><strong>Interoperabilidade transparente com Java, atrav\u00e9s de wrappers idiom\u00e1ticos:<\/strong> gra\u00e7as aos m\u00e9todos de extens\u00e3o, voc\u00ea fica com &#8220;o melhor de dois mundos&#8221; \u2014 cole\u00e7\u00f5es ricas em recursos, al\u00e9m das cole\u00e7\u00f5es do Java.<\/li>\n<\/ul>\n<p>Em termos simples, o Kotlin eleva as tarefas rotineiras com cole\u00e7\u00f5es \u2014 filtragem, mapeamento, agrupamento, etc. \u2014 a fun\u00e7\u00f5es de primeira categoria que podem ser <em>compostas<\/em>, para que voc\u00ea expresse <em>o que<\/em> voc\u00ea quer, em vez da cerim\u00f4nia de <em>como<\/em> chegar l\u00e1.<\/p>\n<p><strong>3. O Kotlin n\u00e3o tem exce\u00e7\u00f5es verificadas, mas o c\u00f3digo \u00e9 mais seguro<\/strong><\/p>\n<p>O Java \u00e9 uma das \u00fanicas linguagens ainda com suporte a exce\u00e7\u00f5es verificadas. Embora essas exce\u00e7\u00f5es tenham sido implementadas inicialmente como um recurso de seguran\u00e7a, n\u00e3o corresponderam \u00e0s expectativas. Sua prolixidade, seus blocos de captura sem sentido, que ou n\u00e3o fazem nada, ou relan\u00e7am a exce\u00e7\u00e3o como uma <code>RuntimeException<\/code>, e sua falta de alinhamento com lambdas s\u00e3o algumas das raz\u00f5es pelas quais elas atrapalham, em vez de tornar o seu c\u00f3digo mais seguro.<\/p>\n<p>O Kotlin segue o paradigma comprovado que \u00e9 usado por quase todas as outras linguagens de programa\u00e7\u00e3o \u2014 C#, Python, Scala, Rust e Go, de usar exce\u00e7\u00f5es apenas em situa\u00e7\u00f5es sem recupera\u00e7\u00e3o.<\/p>\n<p>Os exemplos a seguir destacam os obst\u00e1culos que as exce\u00e7\u00f5es verificadas introduzem no seu c\u00f3digo, sem acrescentar nenhuma seguran\u00e7a:<\/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 String downloadAndGetLargestFile(List urls) {\n\u00a0\u00a0\u00a0List contents = urls.stream().map(urlStr -&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Optional optional;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0optional = Optional.of(new URI(urlStr).toURL());\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28 Within lambdas checked exceptions are not supported and must always be caught...\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (URISyntaxException | MalformedURLException e) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0optional = Optional.empty();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return optional;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}).filter(Optional::isPresent) \u00a0 \u00a0 \u00a0 \/\/Quite a mouthful to get rid of the Optional...\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(Optional::get)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(url -&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try (InputStream is = url.openStream()) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return new String(is.readAllBytes(), StandardCharsets.UTF_8);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (IOException e) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28\u2026 or re-thrown, which is annoying, I don\u2019t really care about IOE\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new IllegalArgumentException(e);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}).toList();\n\u00a0\u00a0\u00a0\/\/\ud83e\udd28 An empty List results in a NoSuchElementException, so why is it not checked? The chance that the List is empty is as high as the other two cases above...\n\u00a0\u00a0\u00a0return Collections.max(contents);\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=\"\">\/\/\ud83d\ude03 safe return type\nfun downloadAndGetLargestFile(urls: List): String? =\n\u00a0\u00a0\u00a0urls.mapNotNull { \u00a0\u00a0\u00a0\/\/\ud83d\ude03 convenient utility methods to rid of null\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83d\ude03 try catch is possible, yet runCatching is an elegant way to convert an exception to null\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0runCatching { URI(it).toURL() }.getOrNull()\n\u00a0\u00a0\u00a0}.maxOfOrNull{ \u00a0\/\/\ud83d\ude03 safe way to retrieve the max value\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0it.openStream().use{ it.reader().readText() } \u00a0\/\/\ud83d\ude03 convenient extension methods to make java.io streams fluent\n\u00a0\u00a0\u00a0}<\/pre>\n<p><strong>4. Fun\u00e7\u00f5es como cidad\u00e3s de primeira categoria<\/strong><\/p>\n<p>O Kotlin trata fun\u00e7\u00f5es como cidad\u00e3s de primeira categoria, o que pode provocar d\u00favidas para quem vem do Java: o que isso significa e por que isso importa?<\/p>\n<p>A principal diferen\u00e7a est\u00e1 na abordagem limitada do Java: seus recursos funcionais concentram-se, em sua maioria, no local da chamada, atrav\u00e9s de lambdas, enquanto o lado da declara\u00e7\u00e3o fica atado a interfaces funcionais prolixas e menos intuitivas. No Kotlin, \u00e9 poss\u00edvel definir, passar, retornar e compor fun\u00e7\u00f5es sem nenhum c\u00f3digo repetitivo, tornando a programa\u00e7\u00e3o funcional muito mais expressiva e natural.<\/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 void doWithImage(\n      URL url,\u00a0\n      \/\/\ud83e\udd28 Function interfaces introduce an indirection: because we don\u2019t see the signature of a Function we don\u2019t know what a\u00a0 BiConsumer does, unless we look it up\n      BiConsumer f) throws IOException {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0f.accept(url.getFile(), ImageIO.read(url));\n}\n\n\/\/\ud83e\udd28 Same here\npublic void debug(Supplier f) {\n\u00a0\u00a0\u00a0if(isDebugEnabled()) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logger.debug(\"Debug: \" + f.get());\n\u00a0\u00a0\u00a0}\n}\n\n\/\/\ud83e\udd28 calling no-argument lambdas is verbose\ndebug(() -&gt; \"expensive concat\".repeat(1000));<\/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=\"\">fun doWithImage(\n\u00a0\u00a0\u00a0url: URL,\n\u00a0 \/\/\ud83d\ude03 Kotlin has a syntax for declaring functions: from the signature, we see what goes in and what goes out\u00a0\n\u00a0\u00a0\u00a0f:(String, BufferedImage) -&gt; Unit) =\u00a0\n      f(url.file, ImageIO.read(url))\n\n\u00a0\u00a0\/\/\ud83d\ude03 same here: nothing goes in, a String goes out\nfun debug(msg: () -&gt; String) {\n\u00a0\u00a0\u00a0if(isDebugEnabled) {\n            logger.debug(msg())\n\u00a0\u00a0\u00a0}\n}\n\n\/\/\ud83d\ude03 convenient syntax to pass a lambda: {}\ndebug{\"expensive concat\".repeat(1000)}<\/pre>\n<p>O Kotlin fornece uma sintaxe clara e concisa para declarar fun\u00e7\u00f5es: s\u00f3 a partir da assinatura, \u00e9 poss\u00edvel ver imediatamente o que entra e o que sai, sem ter que navegar at\u00e9 uma interface funcional externa.\u00a0<\/p>\n<p>O Java &#8220;vaza&#8221; seus recursos de programa\u00e7\u00e3o funcional por uma grande quantidade de interfaces <code>java.util.function.*<\/code> com assinaturas prolixas e complexas. Isso costuma tornar a programa\u00e7\u00e3o funcional desajeitada de usar. J\u00e1 o Kotlin trata fun\u00e7\u00f5es como cidad\u00e3s de primeira categoria: essas interfaces ficam ocultas para o desenvolvedor, mas continuam totalmente interoper\u00e1veis com a abordagem do Java:<\/p>\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-655829\" style=\"aspect-ratio: 1.1355932203389831; width: 510px; height: auto;\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/unnamed-16.png\" alt=\"\" width=\"804\" height=\"708\" \/><\/figure>\n<p>Como resultado, \u00e9 muito mais simples, direto e intuitivo usar fun\u00e7\u00f5es no Kotlin. Isso reduz consideravelmente os requisitos para aproveitar esse poderoso conceito de programa\u00e7\u00e3o no seu pr\u00f3prio c\u00f3digo.\u00a0<\/p>\n<p><strong>5. Concorr\u00eancia sem dores de cabe\u00e7a, usando corrotinas<\/strong><\/p>\n<p>Se voc\u00ea precisar de um alto fluxo de dados, de processamento paralelo em uma s\u00f3 solicita\u00e7\u00e3o ou de streaming, a \u00fanica op\u00e7\u00e3o que voc\u00ea tem em Java \u00e9 usar uma biblioteca reativa, como a Reactor e a RxJava, dispon\u00edveis em frameworks como o Spring WebFlux, Vert.X, Quarkus, etc.<\/p>\n<p>O problema dessas bibliotecas \u00e9 que elas s\u00e3o notoriamente complicadas e for\u00e7am voc\u00ea a usar programa\u00e7\u00e3o funcional. Assim, elas t\u00eam uma curva \u00edngreme de aprendizado, mas \u00e9 muito f\u00e1cil cometer erros que podem ter consequ\u00eancias graves quando o aplicativo est\u00e1 sobrecarregado. Muito provavelmente, foi por isso que a programa\u00e7\u00e3o reativa nunca ficou muito popular.\u00a0<\/p>\n<div class=\"alert \">\n<p><strong>Observa\u00e7\u00e3o:<\/strong> VirtualThreads n\u00e3o substituem bibliotecas reativas, embora haja alguma sobreposi\u00e7\u00e3o. VirtualThreads oferecem entrada e sa\u00edda sem bloqueio, mas n\u00e3o oferecem recursos como processamento paralelo ou streams reativas. Concorr\u00eancia estruturada e valores com escopo tamb\u00e9m permitir\u00e3o processamento paralelo assim que os principais frameworks tiverem suporte a esse recurso. Para streams reativas, voc\u00ea sempre ter\u00e1 que usar uma biblioteca reativa.<\/p>\n<\/div>\n<p>Ent\u00e3o, vamos supor que voc\u00ea seja um desenvolvedor em Java que usa o Spring Boot e quer fazer uma chamada paralela em uma s\u00f3 solicita\u00e7\u00e3o. Voc\u00ea acabar\u00e1 tendo algo assim:\u00a0<\/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=\"\">@PostMapping(\"\/users\")\n@ResponseBody\n@Transactional\npublic Mono storeUser(@RequestBody User user) {\n\u00a0\u00a0\u00a0Mono avatarMono = avatarService.randomAvatar();\n\u00a0\u00a0\u00a0Mono validEmailMono = emailService.verifyEmail(user.getEmail());\n\u00a0\u00a0\u00a0\/\/\ud83e\udd28 what does \u2018zip\u2019 do?\n\u00a0\u00a0\u00a0return Mono.zip(avatarMono, validEmailMono).flatMap(tuple -&gt;\u00a0\n\u00a0      if(!tuple.getT2()) \/\/what is getT2()? It\u2019s the validEmail Boolean\u2026\n\u00a0\u00a0\u00a0     \/\/\ud83e\udd28 why can I not just throw an exception?\n\u00a0\u00a0\u00a0      Mono.error(new InvalidEmailException(\"Invalid Email\"));\n\u00a0      else personDao.save(UserBuilder.from(user)\n                                          .withAvatarUrl(tuple.getT1()));\n\u00a0\u00a0\u00a0\u00a0\u00a0);\u00a0\u00a0\n\u00a0\u00a0}<\/pre>\n<p>Embora do ponto de vista do tempo de execu\u00e7\u00e3o esse c\u00f3digo funcione perfeitamente, a complexidade acidental introduzida \u00e9 enorme:\u00a0<\/p>\n<ul>\n<li>O c\u00f3digo \u00e9 dominado por <code>Mono\/Flux<\/code> em toda a cadeia de chamadas, o que for\u00e7a voc\u00ea a empacotar todos os objetos do dom\u00ednio.<\/li>\n<li>Por toda parte, h\u00e1 muitos operadores complexos, como <code>zip<\/code>, <code>flatMap<\/code>, etc.<\/li>\n<li>Voc\u00ea n\u00e3o pode usar construtos-padr\u00e3o de programa\u00e7\u00e3o, como gerar exce\u00e7\u00f5es.\u00a0<\/li>\n<li>A inten\u00e7\u00e3o de neg\u00f3cios do seu c\u00f3digo \u00e9 significativamente prejudicada: o c\u00f3digo concentra-se em <code>Monos<\/code> e <code>flatMap<\/code>, e assim obscurece o que realmente est\u00e1 acontecendo do ponto de vista de neg\u00f3cios.<\/li>\n<\/ul>\n<p>A boa not\u00edcia \u00e9 que h\u00e1 uma poderosa solu\u00e7\u00e3o para isso, na forma das corrotinas do Kotlin. Elas podem ser consideradas uma implementa\u00e7\u00e3o reativa no n\u00edvel da linguagem. Assim, combinam o melhor de dois mundos:\u00a0<\/p>\n<ul>\n<li>Voc\u00ea escreve c\u00f3digo sequencial, como fazia antes.<\/li>\n<li>No momento da execu\u00e7\u00e3o, o c\u00f3digo \u00e9 executado de forma ass\u00edncrona ou em paralelo.<\/li>\n<\/ul>\n<p>\u00c9 assim que se parece o c\u00f3digo em Java acima, depois de convertido em corrotinas:<\/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=\"\">@GetMapping(\"\/users\")\n@ResponseBody\n@Transactional\nsuspend fun storeUser(@RequestBody user:User):User = coroutineScope {\n\u00a0\u00a0\u00a0val avatarUrl = async { avatarService.randomAvatar() }\n\u00a0  val validEmail = async { emailService.verifyEmail() }\n\u00a0\u00a0\u00a0if(!validEmail.await()) throw InvalidEmailException(\"Invalid email\")\n\u00a0\u00a0\u00a0personRepo.save(user.copy(avatar = avatarUrl.await()))\n}<\/pre>\n<p>A palavra-chave &#8220;suspend&#8221;, do Kotlin, permite execu\u00e7\u00e3o estruturada e sem bloqueios de forma clara e concisa. Juntamente com <code>async{}<\/code> e <code>await()<\/code>, ela possibilita o processamento paralelo sem precisar de callbacks profundamente aninhados, nem de construtos complexos, como <code>Mono<\/code> ou <code>CompletableFuture<\/code>.<\/p>\n<p>\u00c9 por isso que a complexidade diminui e a satisfa\u00e7\u00e3o dos desenvolvedores e a facilidade de manuten\u00e7\u00e3o aumentam, com exatamente as mesmas caracter\u00edsticas de desempenho.\u00a0<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-655845\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/unnamed-17.png\" alt=\"\" width=\"1566\" height=\"456\" \/><\/figure>\n<p><strong>Observa\u00e7\u00e3o<\/strong>: o suporte a corrotinas n\u00e3o \u00e9 igualmente bom em todos os principais frameworks de Web baseados em Java. O Spring \u00e9 excelente para isso, assim como o Micronaut, mas no momento, o Quarkus oferece apenas suporte limitado a corrotinas.<\/p>\n<p><strong>6. Mas ei, o Java tamb\u00e9m est\u00e1 evoluindo!<\/strong><\/p>\n<p>O Java continua evoluindo, com recursos como records, correspond\u00eancia de padr\u00f5es e projetos futuros como Amber, Valhalla e Loom. Essa evolu\u00e7\u00e3o firme fortalece a JVM e beneficia todo o ecossistema.<\/p>\n<p>Mas o problema \u00e9 que a maioria desses &#8220;novos&#8221; recursos do Java s\u00e3o coisas de que os desenvolvedores em Kotlin j\u00e1 v\u00eam desfrutando h\u00e1 anos. Seguran\u00e7a contra valores nulos, classes de valores, fun\u00e7\u00f5es de n\u00edvel superior, argumentos-padr\u00e3o, cole\u00e7\u00f5es concisas, fun\u00e7\u00f5es de primeira linha, tudo isso est\u00e1 incorporado ao projeto do Kotlin e est\u00e1 dispon\u00edvel de uma forma mais unificada e amig\u00e1vel para os desenvolvedores. \u00c9 por isso que c\u00f3digo em Kotlin costuma parecer mais limpo, mais seguro e muito mais produtivo.<\/p>\n<p>E n\u00e3o \u00e9 s\u00f3 isso: o Kotlin tamb\u00e9m se beneficia das inova\u00e7\u00f5es no Java. Avan\u00e7os em n\u00edvel da JVM, como threads virtuais, o Loom em geral ou os aumentos de desempenho do Valhalla, tamb\u00e9m se aplicam de forma transparente ao Kotlin.<\/p>\n<p>Em resumo: o Java evolui, mas o Kotlin foi projetado desde o primeiro dia para dar aos desenvolvedores as ferramentas modernas de que eles precisam, tornando-o uma escolha segura, moderna e progressista para construir o futuro.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-655858\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/kotlin-castle-1.png\" alt=\"\" width=\"1698\" height=\"1780\" \/><\/figure>\n<p><strong>7. A vantagem evolucion\u00e1ria do Kotlin<\/strong><\/p>\n<p>\u00c9 inevit\u00e1vel que as linguagens de programa\u00e7\u00e3o mais antigas carreguem uma bagagem herdada do seu tempo, em compara\u00e7\u00e3o com as alternativas modernas. Atualizar uma linguagem e ao mesmo tempo dar suporte a imensas bases de c\u00f3digo j\u00e1 existentes traz desafios \u00fanicos aos projetistas de linguagens. O Kotlin tem duas vantagens cruciais:<\/p>\n<p><strong>Refer\u00eancias s\u00f3lidas<\/strong>: em vez de reinventar a roda, a equipe do projeto inicial do Kotlin reuniu paradigmas comprovados de importantes linguagens de programa\u00e7\u00e3o e os unificou em um todo coeso. Essa abordagem aproveitou ao m\u00e1ximo o aprendizado evolucion\u00e1rio a partir da comunidade mais ampla de programa\u00e7\u00e3o.<\/p>\n<p><strong>Aprendizado com as limita\u00e7\u00f5es do Java<\/strong>: os projetistas do Kotlin puderam observar as armadilhas do Java e desenvolver solu\u00e7\u00f5es s\u00f3lidas do zero.<\/p>\n<p>Para ter insights mais profundos sobre a evolu\u00e7\u00e3o do Kotlin, veja a excelente palestra que Andrey Breslav, da equipe original de projeto do Kotlin, deu no KotlinDevDay Amsterdam: <a href=\"https:\/\/www.youtube.com\/watch?v=7z_K-hTTeqI&amp;ab_channel=Xebia\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Shoulders of Giants: Languages Kotlin Learned From<\/em><\/a> (&#8220;Sobre os ombros de gigantes: as linguagens das quais o Kotlin aprendeu&#8221;).<\/p>\n<p><strong>Fatores subjetivos: apoie e conecte os desenvolvedores em sua jornada de ado\u00e7\u00e3o do Kotlin<\/strong><\/p>\n<h3 class=\"wp-block-heading\"><strong>1. Facilite a assimila\u00e7\u00e3o<\/strong><\/h3>\n<p>O objetivo da compara\u00e7\u00e3o entre trechos expressivos de c\u00f3digo em Java e em Kotlin \u00e9 abrir o apetite pelo Kotlin. Por\u00e9m, s\u00f3 o c\u00f3digo n\u00e3o \u00e9 suficiente para ganhar os cora\u00e7\u00f5es e mentes dos desenvolvedores em Java. Para acelerar a ado\u00e7\u00e3o e garantir um in\u00edcio suave, forne\u00e7a:<\/p>\n<ul>\n<li><strong>Um projeto de amostra<\/strong>: um projeto pronto para ser executado, com c\u00f3digo tanto em Java quanto em Kotlin lado a lado, para dar \u00e0s equipes uma refer\u00eancia pr\u00e1tica durante a migra\u00e7\u00e3o.<\/li>\n<li><strong>Verifica\u00e7\u00f5es de qualidade incorporadas<\/strong>: pr\u00e9-configuradas com ferramentas como SonarQube, ktlint e detekt, para promover um c\u00f3digo limpo, consistente e f\u00e1cil de manter desde o primeiro dia. Isso permitir\u00e1 que voc\u00ea aplique regras de lint, frameworks de testes, bibliotecas e pipelines de CI com consist\u00eancia, para reduzir a fric\u00e7\u00e3o em todas as equipes.<\/li>\n<li><strong>Mentoria e suporte<\/strong>: engenheiros de Kotlin experientes e dispon\u00edveis para orientar novas equipes, responder perguntas e dar conselhos pr\u00e1ticos nos est\u00e1gios iniciais do desenvolvimento.\n<ul>\n<li>Este ponto \u00e9 especialmente importante: com apenas algumas horas de orienta\u00e7\u00e3o de um desenvolvedor experiente de outra equipe que j\u00e1 tenha passado por esses est\u00e1gios, pode-se evitar muitos danos e muita d\u00edvida t\u00e9cnica.\u00a0<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Um pouco de suporte e mentoria \u00e9 a maneira mais poderosa de incentivar um entusiasmo duradouro pelo Kotlin.<\/p>\n<h3 class=\"wp-block-heading\"><strong>2. Ofere\u00e7a material de (auto)estudo<\/strong><\/h3>\n<p>Especialmente para quem vem do Java, \u00e9 poss\u00edvel aprender o b\u00e1sico do Kotlin por conta pr\u00f3pria. Fornecer alguns recursos logo de in\u00edcio facilita o caminho e reduz os requisitos para se tornar produtivo com o Kotlin.\u00a0<\/p>\n<ul>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/getting-started.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>O &#8220;Tour do Kotlin&#8221; da JetBrains (guia de introdu\u00e7\u00e3o)<\/strong><br \/><\/a>Um tutorial curto, baseado em navegador, no site oficial do Kotlin.<\/li>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/koans.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Kotlin Koans<br \/><\/strong><\/a>Um conjunto de pequenos desafios de programa\u00e7\u00e3o, mantido pela JetBrains.<\/li>\n<li><a href=\"https:\/\/www.udacity.com\/course\/kotlin-bootcamp-for-programmers--ud9011\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Udacity \u201cKotlin Bootcamp for Programmers\u201d<\/strong><br \/><\/a>Um curso completo, baseado em v\u00eddeo e criado em parceria com o Google.<\/li>\n<\/ul>\n<div class=\"alert \">\n<p><strong>Observa\u00e7\u00e3o:<\/strong> Embora o autoestudo seja valioso para aprender o b\u00e1sico, ele tamb\u00e9m tem algumas desvantagens. Uma delas \u00e9 sua natureza opcional: ao ficar atarefado na loucura di\u00e1ria, \u00e9 tentador pular o autoestudo. Al\u00e9m disso, o aprendiz n\u00e3o ter\u00e1 o feedback de um profissional que conhe\u00e7a as nuances sutis do Kotlin idiom\u00e1tico e corretamente aplicado. H\u00e1 uma grande chance de que, ap\u00f3s algum autoestudo, essa pessoa escreva em Kotlin ao estilo do Java, o que trar\u00e1 alguns benef\u00edcios, mas n\u00e3o aproveitar\u00e1 todo o potencial da linguagem.\u00a0<\/p>\n<\/div>\n<p>A menos que uma boa mentoria n\u00e3o seja poss\u00edvel, um curso cl\u00e1ssico pode ser muito ben\u00e9fico. H\u00e1 uma obriga\u00e7\u00e3o de comparecer; os alunos podem trocar ideias com colegas do mesmo n\u00edvel e ter suas perguntas respondidas por um profissional experiente, que desenvolver\u00e1 suas habilidades com muito mais rapidez e com menos Kotlin n\u00e3o idiom\u00e1tico, durante a transi\u00e7\u00e3o.\u00a0<\/p>\n<h3 class=\"wp-block-heading\"><strong>3. Estabele\u00e7a uma comunidade interna de Kotlin<\/strong><\/h3>\n<p>Uma das maneiras mais r\u00e1pidas de aumentar o n\u00edvel de conhecimento sobre Kotlin em toda a sua empresa \u00e9 criar e principalmente incentivar uma comunidade interna.<\/p>\n<ul>\n<li><strong>Crie uma comunidade interna de Kotlin<\/strong>\n<ul>\n<li>Primeiro, procure uma equipe inicial de pelo menos 3\u20136 desenvolvedores que estejam dispostos a investir em uma comunidade de Kotlin. Tamb\u00e9m se certifique de que eles tenham tempo e cr\u00e9dito de seus gerentes para essa tarefa.<\/li>\n<li>Depois que a equipe estiver formada, organize um evento de lan\u00e7amento para toda a empresa, com palestrantes bem conhecidos na comunidade de Kotlin. Isso acender\u00e1 a chama do Kotlin e lhe dar\u00e1 impulso.<\/li>\n<li>Agende encontros regulares (mensais ou quinzenais), para o impulso nunca arrefecer.<\/li>\n<li>Crie um canal de chat ou wiki compartilhada, que possa conter perguntas, trechos de c\u00f3digo e notas de eventos.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Convide palestrantes (externos)<\/strong>\n<ul>\n<li>Traga engenheiros que j\u00e1 tenham entregado aplicativos em Kotlin em produ\u00e7\u00e3o para contar suas hist\u00f3rias de batalha com franqueza.<\/li>\n<li>Alterne entre conversas profundamente t\u00e9cnicas (corrotinas, KMP, programa\u00e7\u00e3o funcional) e estudos de casos de n\u00edvel mais gen\u00e9rico (estrat\u00e9gias de migra\u00e7\u00e3o, dicas sobre ferramentas).<\/li>\n<\/ul>\n<\/li>\n<li><strong>Apresente as li\u00e7\u00f5es aprendidas de outros projetos da empresa<\/strong>\n<ul>\n<li>Pe\u00e7a a l\u00edderes de projetos que apresentem o que aprenderam sobre o Kotlin: o que funcionou ou n\u00e3o e quais foram os desfechos mensur\u00e1veis.<\/li>\n<li>Esses insights podem ser capturados em &#8220;regras do jogo com o Kotlin&#8221;, que novas equipes podem aproveitar.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Ponha os seus pr\u00f3prios desenvolvedores no palco<\/strong>\n<ul>\n<li>Fa\u00e7a sess\u00f5es-rel\u00e2mpago de conversas, de 5\u201310 minutos, nas quais qualquer pessoa possa demonstrar um truque interessante, uma biblioteca ou uma falha que ela resolveu.<\/li>\n<li>Celebre os colaboradores publicamente \u2014 men\u00e7\u00f5es em reuni\u00f5es gerais ou boletins internos aumentam o engajamento e o compartilhamento de conhecimentos.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Tenha pulso firme com os loops de feedback<\/strong>\n<ul>\n<li>Ap\u00f3s cada sess\u00e3o, fa\u00e7a enquetes r\u00e1pidas sobre a clareza e a utilidade. Depois, ajuste as agendas futuras conforme os resultados.<\/li>\n<li>Fa\u00e7a um rod\u00edzio dos encargos na organiza\u00e7\u00e3o, para que a comunidade n\u00e3o dependa de um s\u00f3 defensor e seja resiliente no longo prazo.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Observa\u00e7\u00e3o<\/strong>: Muitas das sugest\u00f5es acima parecem simples e diretas. Por\u00e9m, n\u00e3o se deve subestimar o esfor\u00e7o necess\u00e1rio para manter uma comunidade vibrante e viva.\u00a0<\/p>\n<h3 class=\"wp-block-heading\"><strong>4. Tenha paci\u00eancia\u2026<\/strong><\/h3>\n<p>Mudan\u00e7as de cultura s\u00e3o demoradas. O perigo de ficar t\u00e3o entusiasmado com uma ferramenta que faz diferen\u00e7a para voc\u00ea \u00e9 for\u00e7ar as coisas, o que pode ser contraproducente. Uma abordagem eficaz \u00e9 incentivar o processo de ado\u00e7\u00e3o com todas as atividades discutidas acima, usando <em>&#8220;mostre, n\u00e3o fale&#8221;<\/em> como princ\u00edpio fundamental.<\/p>\n<h3 class=\"wp-block-heading\">Em seguida nesta s\u00e9rie<\/h3>\n<p>Mudaremos o foco de convencer desenvolvedores para persuadir tomadores de decis\u00f5es. A pr\u00f3xima postagem mostrar\u00e1 como criar um caso convincente de neg\u00f3cios a favor da ado\u00e7\u00e3o do Kotlin, baseado em dados reais e desfechos mensur\u00e1veis. Voc\u00ea aprender\u00e1 como traduzir ganhos para os desenvolvedores em argumentos para a administra\u00e7\u00e3o, como associar ganhos de produtividade com economia de custos e como demonstrar por que o Kotlin \u00e9 mais que uma atualiza\u00e7\u00e3o t\u00e9cnica\u00a0<strong>\u2014<\/strong>\u00a0\u00e9 uma jogada estrat\u00e9gica tanto para as equipes quanto para as empresas.<\/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<p>\u00a0<\/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":671831,"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\/671827"}],"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=671827"}],"version-history":[{"count":3,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/671827\/revisions"}],"predecessor-version":[{"id":671853,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/671827\/revisions\/671853"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media\/671831"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media?parent=671827"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/categories?post=671827"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/tags?post=671827"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/cross-post-tag?post=671827"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}