De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank.

Olá, pessoal!

Há 8 meses, embarquei na jornada de ser um Lead Software Engineer no Nubank. Vindo de um mundo onde Kotlin e Go eram minhas principais ferramentas, mergulhar em Clojure foi uma mudança de paradigma. Hoje, quero compartilhar um pouco dess…


This content originally appeared on DEV Community and was authored by Fernando Rosa

Olá, pessoal!

Há 8 meses, embarquei na jornada de ser um Lead Software Engineer no Nubank. Vindo de um mundo onde Kotlin e Go eram minhas principais ferramentas, mergulhar em Clojure foi uma mudança de paradigma. Hoje, quero compartilhar um pouco dessa experiência, mostrando com código as diferenças e o que torna Clojure uma linguagem tão fascinante de se trabalhar.

Vamos explorar três problemas simples, resolvidos em cada uma das três linguagens.

Problema 1: O Clássico "Olá, Mundo!"

Tudo começa aqui. Ver a sintaxe mais básica já nos dá uma pista da filosofia de cada linguagem.

Go:
Focado em simplicidade e um ferramental robusto. Tudo é explícito.

package main

import "fmt"

func main() {
    fmt.Println("Olá, Mundo!")
}

Kotlin:
Moderno, conciso e interoperável com Java. A sintaxe é familiar para quem vem do mundo OO.

fun main() {
    println("Olá, Mundo!")
}

Clojure:
Aqui a primeira "estranheza" que vira um encanto. A sintaxe LISP, com parênteses e prefixos (função argumento), trata código como dados. É simples e incrivelmente poderosa.

(println "Olá, Mundo!")

Análise Rápida: De cara, a concisão de Clojure se destaca. A ausência de cerimônias como declaração de package ou main para um script simples já mostra o foco em ir direto ao ponto.

Problema 2: Transformação de Dados – Agrupar e Somar Vendas

Este é um cenário do dia a dia: temos uma lista de vendas e queremos calcular o total por produto. É aqui que a abordagem funcional de Clojure realmente brilha.

Digamos que temos estes dados:
[{"produto": "A", "valor": 10}, {"produto": "B", "valor": 20}, {"produto": "A", "valor": 5}]

Go:
Em Go, faríamos isso de forma imperativa, inicializando um mapa e iterando sobre a lista para acumular os valores. É eficiente, mas verboso.

package main

import "fmt"

type Venda struct {
    Produto string
    Valor   int
}

func main() {
    vendas := []Venda{
        {"A", 10},
        {"B", 20},
        {"A", 5},
    }

    totalPorProduto := make(map[string]int)
    for _, v := range vendas {
        totalPorProduto[v.Produto] += v.Valor
    }

    fmt.Println(totalPorProduto)
    // Output: map[A:15 B:20]
}

Kotlin:
Kotlin oferece uma API de coleções rica e funcional, tornando o código mais expressivo e menos propenso a erros.

data class Venda(val produto: String, val valor: Int)

fun main() {
    val vendas = listOf(
        Venda("A", 10),
        Venda("B", 20),
        Venda("A", 5)
    )

    val totalPorProduto = vendas
        .groupBy { it.produto }
        .mapValues { entry ->
            entry.value.sumOf { it.valor }
        }

    println(totalPorProduto)
    // Output: {A=15, B=20}
}

Clojure:
Em Clojure, a transformação de dados é o coração da linguagem. O código é uma composição de funções, resultando em uma "pipeline" de dados clara e elegante.

(def vendas
  [{:produto "A" :valor 10}
   {:produto "B" :valor 20}
   {:produto "A" :valor 5}])

(def total-por-produto
  (->> vendas
       (group-by :produto)
       (map (fn [[produto lista-vendas]]
              [produto (reduce + (map :valor lista-vendas))]))
       (into {})))

(println total-por-produto)
; Output: {"A" 15, "B" 20}

Análise Rápida: Enquanto Go é explícito e manual, Kotlin e Clojure mostram o poder das abstrações funcionais. A solução em Clojure, com o macro ->> (thread-last), descreve perfeitamente o fluxo: pegue as vendas, agrupe por :produto, depois mapeie cada grupo para calcular a soma e, por fim, transforme tudo em um mapa. É como ler uma receita.

Problema 3: Concorrência – Incrementando um Contador com Segurança

Como lidar com estado compartilhado é um desafio central em sistemas concorrentes. Cada linguagem tem sua abordagem. Vamos simular 1.000 "processos" incrementando um contador.

Go:
Goroutines e Channels são os cidadãos de primeira classe para concorrência em Go. Para estado mutável compartilhado, usamos mutex para garantir a segurança.

package main

import (
    "fmt"
    "sync"
)

func main() {
    var contador int
    var wg sync.WaitGroup
    var mu sync.Mutex

    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mu.Lock()
            contador++
            mu.Unlock()
        }()
    }

    wg.Wait()
    fmt.Println("Contador final:", contador)
    // Output: Contador final: 1000
}

Kotlin:
Coroutines são a resposta de Kotlin para concorrência leve. Para estado compartilhado, podemos usar tipos atômicos do Java ou um Mutex específico para coroutines.

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

val mutex = Mutex()
var contador = 0

fun main() = runBlocking {
    val jobs = List(1000) {
        launch(Dispatchers.Default) {
            mutex.withLock {
                contador++
            }
        }
    }
    jobs.forEach { it.join() }
    println("Contador final: $contador")
    // Output: Contador final: 1000
}

Clojure:
Clojure abraça a imutabilidade e fornece construções simples e poderosas para gerenciar estado quando ele é inevitável. O atom é perfeito para estado compartilhado e não coordenado. A função swap! garante atualizações atômicas.

(def contador (atom 0))

(defn incrementar []
  (swap! contador inc))

(let [processos (repeatedly 1000 #(future (incrementar)))]
  (doseq [p processos] (deref p))) ; Espera todos terminarem

(println "Contador final:" @contador)
; Output: Contador final: 1000

Análise Rápida: As três linguagens resolvem o problema com segurança, mas a abordagem de Clojure é notavelmente mais limpa. Não há locks manuais visíveis no nosso código de negócio. A complexidade da concorrência é abstraída pelo atom e pela função swap!, tornando o código mais simples de ler e escrever.

Conclusão

Trabalhar com Go e Kotlin me deu uma base sólida em sistemas eficientes e bem tipados. Mas a imersão em Clojure no Nubank me ensinou a amar a simplicidade, a imutabilidade e o poder da programação funcional.

A capacidade de moldar o código como uma sequência de transformações de dados e de lidar com concorrência de forma tão elegante não só torna o desenvolvimento mais rápido, mas também mais prazeroso. É uma linguagem que nos convida a pensar no problema de forma diferente e, na minha opinião, de um jeito muito mais direto e poderoso.

E você, já teve uma experiência parecida ao aprender uma nova linguagem que mudou sua forma de pensar? Adoraria saber!


This content originally appeared on DEV Community and was authored by Fernando Rosa


Print Share Comment Cite Upload Translate Updates
APA

Fernando Rosa | Sciencx (2025-08-12T00:29:48+00:00) De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank.. Retrieved from https://www.scien.cx/2025/08/12/de-kotlin-e-go-para-clojure-uma-jornada-de-8-meses-no-nubank/

MLA
" » De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank.." Fernando Rosa | Sciencx - Tuesday August 12, 2025, https://www.scien.cx/2025/08/12/de-kotlin-e-go-para-clojure-uma-jornada-de-8-meses-no-nubank/
HARVARD
Fernando Rosa | Sciencx Tuesday August 12, 2025 » De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank.., viewed ,<https://www.scien.cx/2025/08/12/de-kotlin-e-go-para-clojure-uma-jornada-de-8-meses-no-nubank/>
VANCOUVER
Fernando Rosa | Sciencx - » De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank.. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/08/12/de-kotlin-e-go-para-clojure-uma-jornada-de-8-meses-no-nubank/
CHICAGO
" » De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank.." Fernando Rosa | Sciencx - Accessed . https://www.scien.cx/2025/08/12/de-kotlin-e-go-para-clojure-uma-jornada-de-8-meses-no-nubank/
IEEE
" » De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank.." Fernando Rosa | Sciencx [Online]. Available: https://www.scien.cx/2025/08/12/de-kotlin-e-go-para-clojure-uma-jornada-de-8-meses-no-nubank/. [Accessed: ]
rf:citation
» De Kotlin e Go para Clojure: uma jornada de 8 meses no Nubank. | Fernando Rosa | Sciencx | https://www.scien.cx/2025/08/12/de-kotlin-e-go-para-clojure-uma-jornada-de-8-meses-no-nubank/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.