10 pontos por GN⁺ 2024-12-16 | 5 comentários | Compartilhar no WhatsApp
  • Um texto que explica as limitações e problemas da linguagem Go percebidos pelo autor após anos de uso e sua migração para Java
  • Apresenta a perspectiva de que a característica de Go ser uma linguagem simples e "entediante" (boring) pode ser uma desvantagem, não uma vantagem
  • Filosofia do Go: a equipe de design do Go no Google enfatizou simplicidade e restrições, mas isso acaba gerando trabalho repetitivo que o usuário precisa resolver por conta própria

1. O fato de Go ser "não divertido" pode ser uma desvantagem

  • Argumento de Russ Cox:
    • Destaca que o fato de Go ser "entediante" (boring) é uma vantagem
    • Só existe for para loops, e recursos como filter, map e reduce não são oferecidos por padrão
    • A ausência de vários recursos avançados presentes na maioria das outras linguagens é vista como parte da simplicidade
  • Opinião de usuários no Reddit:
    • A fronteira entre "não ser divertido" e "ser poderoso" é vaga
    • Argumentam que a falta de recursos básicos do Go provavelmente acabará sendo corrigida com adições à linguagem
  • Dependência de pacotes de terceiros:
    • Pacote samber/lo, muito usado para suprir recursos ausentes:
      • Inclui funções essenciais como filter, map e busca
      • Tem 18.1k estrelas no GitHub e é usado em mais de 12.6k projetos
    • Algumas funções foram adicionadas ao pacote slices, mas ainda são insuficientes em termos funcionais
  • Reclamações do autor:
    • Obrigação de escrever loops repetitivos
    • Dificuldade de lidar de forma concisa com tarefas como filter e map
    • É possível extrair isso para métodos com receiver separados, mas isso prejudica a limpeza do código
  • A simplicidade do Go é uma vantagem em muitos casos, mas a falta de recursos básicos de conveniência também pode reduzir a produtividade e a legibilidade do código

2. Atrapalha os princípios de Clean Code

  • Problema no tratamento de erros:
    • Na maioria dos casos, funções incluem error como valor de retorno:
      • É preciso repetir o padrão if err != nil o tempo todo
      • Ao tentar organizar o código, ele acaba ficando ainda mais complexo
    • Mesmo em projetos simples, o código de handlers HTTP cresce para mais de 20 linhas
      • Quando a meta original era manter algo em torno de 4 linhas
    • A frustração com a abordagem de tratamento de erros chega ao ponto de considerar panic() com middleware de recuperação
  • Recomendação de nomes curtos:
    • Recomenda-se usar nomes curtos para variáveis, métodos e funções:
      • Nomes como c e a não deixam claro o que significam
      • Ex.: c pode ser Command, Controller, Argument ou Amendment?
      • Nomes mais longos poderiam deixar isso mais claro, mas a filosofia do Go prefere nomes curtos
    • Isso acaba gerando discussões intermináveis em code reviews da equipe, inclusive sobre nomes de métodos de teste
  • A filosofia do Go enfatiza concisão e simplicidade, mas o resultado pode ser complexidade e ineficiência contrárias aos princípios de código limpo

3. A filosofia de linguagem intencionalmente pequena e a cultura DIY

  • Falta de funcionalidades básicas:
    • Implementar um handler HTTP simples é fácil, mas se você precisar de middleware básico (ex.: exponential backoff, configurações cross-site etc.), terá de procurar vários pacotes
    • É difícil ter certeza de que esses pacotes (1) ainda são mantidos e (2) funcionam como esperado
  • Aumento de trabalho repetitivo:
    • A filosofia de design do Go de manter a simplicidade acaba exigindo do desenvolvedor "reinventar a roda"
    • Ex.: até um recurso simples de filter pode precisar ser implementado manualmente
  • Ecossistema de pacotes imaturo:
    • Muitos projetos no GitHub estão abandonados ou tiveram poucas versões lançadas
    • Por ser uma linguagem relativamente jovem, pode ser injusto compará-la a .NET/Java, mas na prática faltam estabilidade e maturidade ao ecossistema de pacotes do Go
  • Limitações dos ORMs:
    • O principal pacote ORM do Go (Gorm) fica atrás de Hibernate e Entity Framework em recursos
    • Há comportamentos estranhos e falta de documentação
    • Reação da comunidade Go: "Em Go você não precisa de ORM, faça você mesmo!"
  • A simplicidade do Go pode ser uma vantagem dependendo do projeto e da equipe, mas a falta de recursos nativos pode afetar negativamente a produtividade e a experiência de desenvolvimento

4. No Go, não existe só uma forma de fazer as coisas

  • O equívoco sobre consistência e uniformidade:
    • Table tests
      • Uso de suítes de teste como stretchr/testify (utilizado em 557k projetos)
      • Escrita de subtests customizados dentro de table tests
    • Isso mostra uma distância entre a filosofia do Go de haver uma "forma unificada" e a realidade
  • Gera conflitos dentro da equipe:
    • Aumentam as discussões entre equipes sobre estilo de testes e formas de implementação
    • A própria filosofia do Go e sua equipe de design carecem de consistência:
      • Ex.: divergências sobre nomenclatura de métodos getter
  • Recusa de recursos e dependência de pacotes:
    • A equipe do Go se recusa a adicionar recursos de assertion e é criticada por tratar a limitação como falha do programador
    • Como resultado, é preciso instalar outro pacote (go get) para usar funcionalidades necessárias
  • Embora Go busque simplicidade e uniformidade, na prática existem várias formas de implementar as coisas e debates decorrentes disso, e a ambiguidade da filosofia de design da linguagem agrava o problema

5. Debugar em Go não é divertido

  • Não é possível avaliar expressões durante o debug:
    • Em uma sessão de depuração, não dá para avaliar expressões nem verificar representações de string customizadas de objetos
    • Isso dificulta entender claramente o estado dos objetos em tempo de execução
  • Stack traces e logs pouco intuitivos:
    • Quando testes em grande escala falham (ex.: milhares de testes rodando em CI), os stack traces e logs gerados são confusos
    • Como resultado, o debug fica mais difícil e a produtividade cai
  • Experiência de debug no estilo C:
    • A cadeia de ferramentas de debug do Go funciona com base em C:
      • Oferece uma experiência de depuração primitiva, parecida com a de C
      • Pouco amigável para desenvolvedores
  • Comparação com Rust:
    • Rust melhora limitações do Go:
      • Fornece informações de erro claras e úteis
      • Inclui sugestões exatas de correção nas mensagens de erro
  • A experiência de debug em Go se baseia numa filosofia de design voltada a entregar binários otimizados, mas isso sacrifica a experiência do desenvolvedor. Em ambientes onde eficiência de depuração é importante, pode ser melhor considerar outras linguagens

Resumo: adequação e limitações do Go

  • Vantagens das ferramentas nativas do Go:
    • Fornece uma toolchain básica para gerenciamento de pacotes, testes e monitoramento de desempenho
    • Pode ser usada sem configuração adicional, simplificando a preparação inicial do ambiente de desenvolvimento
  • Limitações:
    • "Código entediante" e trabalho repetitivo:
      • A toolchain do Go é funcional, mas força trabalho repetitivo (plumbing code) ao escrever código
      • Ex.: sintaxe monótona e recursos limitados reduzem o interesse no trabalho
    • "import cycle not allowed":
      • Não permite dependências circulares (import cycle) em testes
      • Em trabalhos com Domain-Driven Design (DDD), isso aumenta a complexidade por causa de restrições estruturais
    • Dependência da técnica de embedding de struct:
      • O mecanismo de embedding de struct é estranho e limitado, causando dificuldade prática de uso
  • Áreas de uso adequadas:
    • Adequado para desenvolvimento de infraestrutura:
      • Ferramentas em nível de sistema como Docker, Drone e Hugo são escritas em Go
    • Útil para desenvolver servidores leves e aplicações CLI
  • Áreas de uso inadequadas:
    • Desenvolvimento de aplicações corporativas complexas (ex.: sistemas ERP):
      • A filosofia limitada da linguagem e suas ferramentas tornam ineficiente gerenciar lógica de negócio em larga escala
  • Go oferece excelente eficiência em certos tipos de trabalho, especialmente os ligados à infraestrutura, mas não é uma ferramenta adequada para aplicações com domínios de negócio complexos. Mesmo quando o CTO é inclinado à stack do Google, é preciso cautela na escolha tecnológica

5 comentários

 
secret3056 2024-12-17

Se ao menos tivesse o ? do Rust, já não seria muito melhor do que é agora...

 
bbulbum 2024-12-17

A sensação que tive ao usar Go foi perceber o quanto, até então, eu fazia tratamento de erros de forma implícita.
Claro, tratar erros em um único ponto pode parecer estruturalmente mais limpo, mas tenho a impressão de que, ao deixar explícito que se trata de uma operação que pode retornar erro, acabamos escrevendo código de forma mais segura.

 
tsboard 2024-12-16

if err != nil {} isso sinceramente é meio incômodo. Também concordo com as desvantagens apontadas. Mesmo assim, se entendermos claramente o que essa linguagem se propõe a ser e pensarmos em que pontos aproveitá-la melhor, acho que dá para usá-la ainda melhor apesar dessas críticas. É parecida com C, mas tem GC, suporta genéricos, ainda que de forma limitada, e além disso faz cross-compilation! Vendo por esse lado, não dá para dizer que é uma linguagem bem generosa?

 
riki3 2024-12-16

Quando migrei de Java para Go, acho que no começo tive uma sensação parecida.
Hoje gosto tanto de Go que chego a pensar que foi um desperdício o tempo que usei Java. Dizer que não é adequado para aplicações de negócio complexas me faz pensar que não houve reflexão suficiente sobre como simplificar o sistema nessa aplicação.

 
GN⁺ 2024-12-16
Opinião do Hacker News
  • Problemas surgem quando desenvolvedores Java tentam impor um estilo Java ao Go

    • A filosofia do Go parece menos útil no curto prazo, mas faz uma grande diferença no longo prazo
    • Pessoas muito imersas no ecossistema JVM tendem a ter dificuldade para aproveitar o Go
  • Muitos desenvolvedores tentam abstrair cedo demais

    • Criam abstrações desnecessárias quando uma repetição simples já basta
  • A biblioteca padrão do Go é grande, mas não tão grande a ponto de fazer tudo

    • Há uma tendência de reinventar a roda em cada projeto
    • Go é ideal para aplicações de servidor e CLI
  • Existem desafios maiores do que a escolha da linguagem de programação

    • É importante se adaptar aos mecanismos e à filosofia do Go
  • É difícil entender por que gostam de Go

    • A preferência parece estar mais no toolchain e na facilidade de deploy do que na linguagem em si
  • É frustrante ver a equipe principal do Go voltar atrás em decisões erradas

    • Existem um bom sistema de pacotes e boas ferramentas
    • Para sistemas ERP complexos, Java pode ser uma escolha melhor
  • Go tem problemas parecidos com os do UNIX

    • Há uma tendência de empurrar a complexidade para o usuário
    • O runtime do Java está evoluindo rapidamente em comparação com o Go