1 pontos por GN⁺ 8 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • A Haskell foi adotada no processo de modernização da cadeia de suprimentos de mais de 435 lojas e centros de distribuição e, 8 anos depois, cerca de 1 milhão de linhas de código mantidas por várias equipes estão em operação em sistemas críticos de produção
  • Haskell reduz tipos de erros em tempo de execução e oferece suporte a refatorações baseadas no GHC e à integração com sistemas legados, mas é preciso aceitar a manutenção interna por falta de SDKs e a complexidade dos recursos avançados de tipos
  • O sucesso dependeu muito mais da capacidade e da cultura das equipes do que da linguagem; em duas iniciativas, a adoção não se consolidou devido a vazamentos de espaço em uma equipe sem especialistas em Haskell e à saída de desenvolvedores-chave
  • O runtime do GHC nunca foi causa de uma falha de produção na H-E-B e, com a evolução do ecossistema em HLS, OpenTelemetry, profiling e outros, Haskell em produção se tornou uma opção competitiva
  • Recursos avançados devem ser restringidos por trás de pequenas bibliotecas e interfaces claras, junto com testes, observabilidade e compartilhamento de conhecimento; na era dos agentes de codificação, a validação de tipos do GHC e o feedback rápido se tornam ainda mais importantes

O desafio da modernização do mainframe

  • Os clientes da H-E-B, varejista que é a maior empresa privada do Texas, se importam mais com as prateleiras das lojas abastecidas do que com os sistemas internos
  • Durante décadas, um mainframe COBOL operou de forma estável, mas nos últimos 10 anos surgiram recursos centrados em tecnologia, como retirada na calçada, entrega em domicílio, estoque em tempo real e busca dentro da loja
  • Ao expandir as operações da cadeia de suprimentos para mais de 435 lojas e os centros de distribuição que as apoiam, os sistemas centrais existentes passaram a receber demandas além do escopo para o qual foram originalmente projetados
  • A principal dificuldade da modernização do mainframe não é mover código para a nuvem, mas preservar o conhecimento específico da organização acumulado ao longo de décadas na lógica de negócios legada
  • Dividir um monólito com centenas de tabelas em microsserviços pertencentes a equipes de engenharia autônomas é uma tarefa técnica e politicamente enorme, além de cara

Adoção de Haskell e escala operacional

  • Consultores propuseram Haskell como linguagem comum para um novo projeto que substituiria a maior aplicação de mainframe da empresa
  • O trabalho que começou como experimento cresceu e se tornou vários sistemas centrais de produção da cadeia de suprimentos
  • Oito anos após a adoção, várias equipes de diferentes domínios mantêm cerca de 1 milhão de linhas de código Haskell
  • A operação em produção por longo prazo revelou não apenas resultados reais, mas também dificuldades técnicas e organizacionais

Vantagens obtidas pelo negócio

  • O que as empresas querem não é avaliação preguiçosa, funções puras ou dados imutáveis em si, mas um sistema como o COBOL de próxima geração, capaz de operar por 40 anos sem null pointer exception e com baixo custo de manutenção
  • Aplicações Haskell eliminam por padrão tipos de erros em tempo de execução comuns em programas imperativos e de tipagem dinâmica
    • Bugs não desaparecem completamente, mas os problemas restantes se concentram mais em erros de lógica de negócios do que em null pointer exception ou confusão de tipos
  • Em migrações legadas de vários anos pelo padrão strangler fig, o GHC apoia refatorações seguras
    • É possível fazer alterações repetidas enquanto os requisitos se formam, permitindo uma migração ágil em vez de waterfall
    • A empresa pode medir resultados de forma incremental em vez de investir antecipadamente em um resultado cristalizado de forma equivocada
  • Parsers em Haskell permitem usar formatos legados de milhares de linhas, como IBM copybooks de largura fixa, diretamente como contratos
  • Uma poderosa interface de função estrangeira (FFI) permite integração também com serviços existentes que oferecem apenas bibliotecas C
    • A H-E-B escreveu bibliotecas Haskell que encapsulam simdjson C++, Oracle ODPI-C e IBM MQ

Falta de SDKs e propriedade dos contratos

  • Quando faltam SDKs para Haskell, é preciso criar os clientes e o código de integração necessários e continuar mantendo-os
  • Em troca, a equipe passa a ser dona direta dos contratos, evita dependência de fornecedores e não precisa esperar que o mantenedor upstream distribua correções
  • A H-E-B avaliou que, para dependências centrais, essa troca valia o suficiente
  • Agentes de codificação lidam bem com o trabalho mecânico de portar bibliotecas Go para Haskell, reduzindo a diferença de velocidade de desenvolvimento entre linguagens
    • Porém, uma tradução simples pode não aproveitar plenamente os benefícios do sistema de tipos de Haskell sem prompts sofisticados

Integração multilíngue por meio de DSLs embutidas

  • Haskell é forte como linguagem hospedeira para DSLs embutidas (eDSLs)
    • Uma equipe central pode definir uma vez o modelo de domínio ou a lógica de negócios e depois gerar código com tipos seguros nas linguagens usadas por outras equipes
    • Outras equipes conseguem se integrar ao sistema sem escrever Haskell diretamente
  • Hydra é um framework DSL open source que evoluiu a partir do trabalho com dados em grafo na Uber
    • Ele é bootstrapado em Haskell e gera implementações semanticamente equivalentes em Java, Python, Scala e outras linguagens
    • Uma suíte de testes compartilhada garante a equivalência das implementações por linguagem
  • A H-E-B prototipou uma DSL em Haskell para cálculos financeiros sensíveis que poderiam ser compartilhados por equipes de Haskell, TypeScript e Java
  • Também criou uma DSL bidirecional de schema JSON
    • Ela é semelhante ao autodocodec, mas usa uma codificação tagless final que permite ao usuário estender a semântica central com suas próprias type classes
    • Padroniza versionamento de schema, geração de documentação e OpenAPI, além de testes de regressão e golden tests
    • É possível escrever intérpretes temporários para converter schemas JSON em definições de tabelas PostgreSQL ou substituir aeson por simdjson e aplicar validações adicionais

Recrutamento e cultura de engenharia

  • Linguagens modernas também oferecem muitos recursos de segurança de tipos, pureza e concorrência influenciados por Haskell; por isso, a diferença real está na cultura de engenharia que a linguagem incentiva
  • Haskell atrai desenvolvedores que valorizam correção e projeto de abstrações
  • Contratar para funções em Haskell não foi tão difícil quanto a liderança esperava
    • Mesmo sem interesse especial por cadeia de suprimentos, havia candidatos que se inscreviam por causa da própria Haskell

Limites do orçamento de complexidade

  • Haskell é uma linguagem antiga e tem várias falhas, por isso é importante acompanhar as versões mais recentes do GHC
  • Sem especialistas na equipe, uma única deficiência da linguagem pode se espalhar por todo o projeto
  • No início, consultores experientes estabeleceram guardrails para impedir o uso excessivo de extensões da linguagem e operadores personalizados
  • Antes das edições de linguagem GHC2021 e GHC2024, cada equipe gerenciava por conta própria o conjunto básico de extensões
    • Isso funcionava como um orçamento de complexidade, limitando o escopo da linguagem que novos contratados precisavam aprender antes de contribuir
  • As próprias dependências também consomem o orçamento de complexidade, o que dificulta a imposição em nível organizacional
    • servant expressa APIs como uma DSL no nível de tipos, e estender combinadores personalizados envolve type families e erros difíceis de entender
    • haxl modela todas as fontes de dados como GADTs indexados pelo tipo de resultado para agrupar operações concorrentes em lotes
  • À medida que desenvolvedores ficam mais experientes, aumenta a tentação de introduzir padrões como GADT, type family, generics, tagless final, arrows, free structures e tipos de dados de kind superior
    • Quando esses conceitos se acumulam sobre um domínio de negócios já complexo, a promessa de manutenção fácil se enfraquece
    • Como recursos avançados aumentam gradualmente à medida que a equipe se familiariza com o ecossistema, o crescimento da complexidade pode aparecer tarde demais

Princípios operacionais de Haskell entediante

  • Em nível organizacional, é fácil recomendar Haskell entediante, mas difícil impor
  • Encapsular Haskell avançado por trás de interfaces razoáveis reduz o alcance do impacto e limita o orçamento de complexidade a pequenas bibliotecas mantidas por poucos especialistas
  • Complexidade no nível da linguagem não é um problema exclusivo de Haskell, mas Haskell oferece uma gama especialmente ampla de ferramentas avançadas
  • Mais do que número de linhas de código ou uso de tokens, a quantidade de código que quebra no próximo upgrade do GHC mostra melhor a complexidade de um projeto Haskell

Dois projetos em que a adoção não se consolidou

  • Haskell pode ampliar a capacidade de uma equipe e, ao mesmo tempo, virar barreira para outra; na H-E-B, ela não se consolidou em dois projetos por motivos diferentes
  • No primeiro caso, desenvolvedores experientes sem vivência em Haskell seguiram templates e convenções de projetos de outra equipe, mas um vazamento de espaço (space leak) travou o programa inteiro
    • Sem um desenvolvedor Haskell forte para orientar a equipe, esse único problema levou à interrupção do projeto
  • No segundo caso, os engenheiros que defendiam Haskell e criaram a aplicação foram movidos para outros projetos por mudança de prioridades
    • Esse motivo não tinha relação com a linguagem em si
  • Ambas as equipes tinham alternativas para voltar a tecnologias existentes e não estavam convencidas de que Haskell aumentava sua produtividade
  • Quando existe uma saída como um template Spring Boot, pode haver menos motivação para diagnosticar até o fim um vazamento de espaço difícil
  • Com LLMs capazes de traduzir mecanicamente bases de código inteiras, as opções de reescrita ficam ainda mais amplas
  • A linha de defesa de longo prazo não é um código inteligente demais para ser reescrito, mas uma equipe que queira continuar mantendo Haskell

Falhas de produção e diagnóstico

  • Mesmo nas equipes que adotaram Haskell, ocorreram vários problemas sérios
  • O runtime do GHC nunca foi a causa raiz de uma falha de produção na H-E-B
  • A vazão e o uso de memória em estado normal foram competitivos o suficiente para as cargas de trabalho da H-E-B, e os casos problemáticos foram exceções, não a situação comum
  • Os engenheiros resolveram problemas rastreando core dumps de falhas de segmentação, métricas de coleta de lixo e perfis de heap
  • Não se deve sacrificar cobertura de testes por causa do sistema de tipos forte
  • Como tipos simples de erros são eliminados na compilação em aplicações Haskell, a engenharia do caos pode expor de forma mais direta falhas reais de lógica e recursos

Ferramentas de desenvolvimento e ecossistema transformados

  • Os primeiros sistemas começaram com GHC 8.2 e, na época, era necessário escrever internamente a maior parte dos clientes de API e SDKs para plataformas populares
  • O Haskell Language Server ainda não existia, o GHCup estava apenas surgindo, e o profiling de runtime também era difícil
  • Desenvolvedores acostumados com IDEs Java achavam o ambiente de ferramentas de Haskell desconfortável, e a H-E-B chegou a patrocinar o desenvolvimento de suporte ao Debug Adapter Protocol para usuários do VS Code
  • Hoje, o desenvolvimento Haskell de nível de produção evoluiu para além do viável e chegou a um nível competitivo
  • As ferramentas de desenvolvimento incluem HLS, ghcid, ghciwatch, static-ls, tricorder e plugins de editor
    • Algumas equipes usam plugins do GHC para um desenvolvimento rico centrado no GHCi, enquanto outras usam VS Code e HLS
    • Os desenvolvedores podem escolher as ferramentas que preferem
  • Para observabilidade, são usados hs-opentelemetry e opentelemetry-auto
    • opentelemetry-auto é um plugin do GHC que insere automaticamente spans OTel em funções Haskell
    • Ele pode oferecer um ambiente de instrumentação semelhante ao de Java e Python

Bibliotecas de produção e melhorias do runtime

  • Os serviços usam bibliotecas como warp, aeson, attoparsec, stm, conduit, servant e orville-postgresql
  • Quando o ecossistema não oferece um recurso necessário, bibliotecas internas são desenvolvidas
    • arbiter é uma fila transacional de trabalhos PostgreSQL surgida do trabalho da H-E-B e atualmente em produção
  • O GHC vem melhorando diagnósticos de runtime, desempenho do compilador, recursos de monitoramento como eventlog streaming e anotações de exceção
  • Depois que o info table profiling foi introduzido no GHC 9.2, a preocupação com vazamentos de espaço diminuiu bastante

Comunidade interna e distribuição de conhecimento

  • A H-E-B trata bibliotecas internas como algo importante e incentiva desenvolvedores a participar tanto de projetos internos quanto de open source
  • Durante anos, manteve encontros quinzenais de Haskell para que engenheiros compartilhassem descobertas e treinassem outros membros
  • Para reduzir silos em uma organização corporativa, ideias e padrões precisam circular entre equipes
  • Fazer com que mais engenheiros leiam e sejam donos da base de código reduz o risco de bus factor causado pela saída de uma única pessoa

Critérios para permitir recursos avançados

  • Há regras básicas flexíveis, mas a decisão final sobre onde gastar o orçamento de complexidade cabe aos líderes técnicos
  • Se dados pessoais identificáveis (PII) armazenados precisam ser criptografados, uma garantia no nível de tipos que transforma vazamento de dados sensíveis em erro de compilação, e não em incidente de runtime, pode valer o investimento
  • Unificar quatro contratos de API com o padrão trees-that-grow pode não valer a ponto de ocultar schemas externos com type families
  • Haskell entediante não proíbe programação no nível de tipos nem recursos avançados do GHC; ela define convenções com princípios e avalia o custo de desviá-las
  • A principal convenção é “sem ação inesperada à distância
    • Evitar geração de código com TemplateHaskell e lógica de serialização baseada em Generic
    • Escrever boilerplate manualmente para mostrar explicitamente o comportamento ao programador
    • Isso não proíbe completamente deriving por quasiquoter ou Generically
  • Ao implementar máquinas de estado no nível de tipos para formulários web ou usar GADTs onde ADTs comuns bastariam, é necessário ceticismo saudável e contestação em nível de equipe
  • Haskell avançado existe tanto em bibliotecas quanto em aplicações de produção, mas o escopo dos experimentos deve ser limitado
  • A engenharia real acontece no processo de equilibrar trabalho e brincadeira técnica

O futuro de Haskell e dos agentes de codificação

  • Ao longo de vários anos usando GHC, foram encontrados e reportados alguns poucos bugs, mas nenhum problema grave a ponto de interromper o trabalho
  • Incidentes de produção são raros e ocorrem com muito mais frequência na lógica de negócios do que em erros de tipo ou de runtime
  • À medida que cresce a proporção de código escrito por agentes de codificação, o gargalo se desloca da escrita de código para a validação
  • O sistema de tipos do GHC ajuda pessoas a refatorar com segurança e, ao mesmo tempo, fornece um ciclo rápido de feedback que rejeita antes da execução códigos alucinados por agentes
  • Para ampliar o potencial de Haskell na indústria, mais casos reais de sucesso em produção precisam ser compartilhados

1 comentários

 
GN⁺ 8 시간 전
Opiniões no Lobste.rs
  • Fora do Texas talvez não seja muito conhecida, mas a H-E-B é uma instituição emblemática do Texas, com porte e influência tão grandes que quase poderia ser outro departamento do governo estadual.
    Muitas lojas têm instalações para produção de tortillas, e a qualidade é excelente para um produto feito em larga escala. Além disso, dizem que também usam Haskell

    • O nome vem das iniciais H.B. de Howard Butt, a família fundadora. Poderia ter recebido o nome do fundador, como Wegmans, Hannaford Market e Walmart, mas felizmente não virou Buttmart
    • Fico curioso se é algo como uma versão regional da Costco
  • É realmente surpreendente que uma empresa como a H-E-B tenha escolhido Haskell para substituir COBOL.
    As duas frases em que dizem que um agente de codificação consegue portar mecanicamente bibliotecas Go para Haskell, reduzindo a diferença de velocidade de desenvolvimento, e logo em seguida admitem que, sem prompts inteligentes, talvez não se aproveite suficientemente o sistema de tipos, expõem um problema contraditório.
    Por outro lado, como erros triviais são eliminados na etapa de compilação, quando a engenharia do caos injeta falhas de infraestrutura, aparecem erros reais de lógica e de recursos em vez do ruído típico de linguagens dinamicamente tipadas; isso parece ser o motivo mais convincente para considerar Haskell

    • A H-E-B, assim como o Walmart, tem uma organização de engenharia grande e com uma reputação bastante boa, então não é tão surpreendente. Ela até mantém um escritório dedicado a software em Austin para atrair talentos de software que relutariam em trabalhar na sede em San Antonio
  • Na semana passada tentei configurar builds Haskell isolados no Bazel, mas não encontrei uma solução pronta para uso.
    rules_haskell não é isolado por padrão, e a abordagem comum parece depender bastante de nixpkgs. Parece que Haskell depende do linker C++ do sistema; fico me perguntando se essa é a situação real hoje ou se há alguma alternativa que eu deixei passar