Percebe-se que muitos estudam Rust, experimentam e se apaixonam, mas na prática não usam profissionalmente. A famosa pesquisa anual do Stack Overflow prova isso - há um grande percentual no quesito de linguagem amada, mas baixo quando comparado ao uso.
Por ser uma linguagem relativamente nova e pouco popular, Rust acaba sofrendo algumas barreiras para ser adotado de forma mais ampla. Nesse artigo gostaria de compartilhar a minha experiência para conseguir conciliar o Rust e usar no trabalho ao lado de outras linguagens.
Se preparando para ser questionado
Exceto se você possuir um poder de decisão dentro da empresa, você terá que convencer seus colegas a adotar. No meu caso me preparei para isso, tentando prever todos questionamentos que eu receberia. Até vale a pena abrir um parênteses: tudo deve ser questionado, não podemos nos ofender com isso - uma ideia para se mostrar consistente deve ser questionada, sendo assim ela prevalecerá.
Devemos formular a reposta para explicar qual a vantagem das empresas desenvolvedoras usar Rust - que tipo de problema ele veio solucionar.
Primeiramente é importante compreendermos que existem diversas linguagens para alcançar diferentes objetivos - e elas podem coexistir e se complementar. Então vamos explorar onde o Rust se encaixa perfeitamente.
Necessidade por aplicação compilada
Além da demanda enterprise - para execução de grande aplicações de negócio - existe um outro tipo de necessidade, que podemos exemplificar pelas rotinas de baixo nível, de apoio e infraestrutura (devops). Aqui consideramos aplicações com código binário nativo, sem runtime (ou VM), de baixo consumo de recursos e de alta performance.
Até a pouco tempo atrás esse tipo de aplicação seria feito em linguagem C++ quase como regra geral. Mas dada essa necessidade crescente da indústria de software foram criadas alternativas de desenvolvimento mais simples, um pouco mais familiar ao mundo enterprise. Um fruto disso foi a linguagem Go, hoje utilizada por gigantes como Google, Netflix, Uber, etc. Claramente estas empresas adotaram o Go para aplicar em pontos onde havia necessidade processamento crítico e com pouco consumo de recursos. Java, Kotlin e cia estão lá processando regras de negócio, porém agora dividindo o backend com Go.
Necessidade por "safe systems programming"
A Microsoft estima que cada bug grave do Windows tem um custo de US$ 150,000. Por ano ocorrem 468 bugs como esses, ou seja, são US$ 70,2 milhões. Porém indiretamente esses bugs podem causar outros problemas, tal como abrir brechas para Ransoware.
Então estima-se que por ano esses bugs podem causar prejuízos em torno de 4 bilhões de dólares.
Engenheiros da Microsoft e do Google chegaram a conclusão que em torno de 70% dos bugs são causados por erros ao manipular ponteiros e objetos.
Num primeiro momento esse número pode parecer exagerado, mas percebam que aqui incluímos os Null Pointer References (The Billion Dollar Mistake), memory leaks, acesso indevidos a referências de objetos, etc. Ou seja, não é exclusividade do C++, mesmo Java e outras linguagem contribuem com essa estimativa.
Então surgiu uma nova necessidade da indústria: Safe programming.
Isso se confirma pela tendências de algumas linguagens para tentar reduzir problemas de Null Pointer References utilizando option types (ou maybe types). Um bom exemplo é a linguagem Dart, que está incluindo comportamento null safety.
Linguagem compilada e segura: onde Rust brilha
Rust é a linguagem mais segura que existe pois nele não ocorrem problemas de referências tal como:
- Null pointer reference
- Access violation
- Invalid type cast
- Memory leak
- Double free
Rust também é seguro a ponto de garantir que execução de threads sejam livre de race condition - quando duas threads tentam alterar o mesmo dado compartilhado ao mesmo tempo.
Lembrando que 70% dos bugs são causados por problemas ao manipular manipular ponteiros e objetos. Rust não tem esses problemas.
Mas não é só a segurança e qualidade do código do Rust que é maior. Rust é uma das linguagens mais rápida que existe:
- Não possui Garbage Colector e por consequência não sofre com suas implicações
- Boa parte da memória é alocada stack, que é bem mais rápida que a heap
- Por garantir a segurança em tempo de compilação a execução é livre de overhead de checagens
- Compilação com Zero-cost abstraction, onde estruturação do fonte em formato mais "humano" não interfere no código compilado
Vou citar um exemplo para vocês compreenderem o quão rápido estamos falando. Um colega comentou que uma aplicação em Go conseguia validar um milhão de CPFs em 200 milissegundos. Por curiosidade acabei fazendo esse mesmo teste, criei um programa que lê um arquivo txt com 1 milhão de CPFs formatados (com tamanho de 15 Megabytes), desformata e valida todos registros. Em Rust demorou 60 milissegundos, incluindo a leitura do arquivo.
"Rust? Nunca ouvi falar. É mantido por quem?"
Rust foi desenvolvido dentro da Mozilla, mas atualmente está sendo feita uma transição ser criada uma fundação independente. Seu projeto foi iniciado a 10 anos, então em termos de maturidade sua idade se assemelha ao Go.
Rust possui uma uma comunidade muito grande:
- De acordo com Github é a segunda linguagem com maior crescimento. Está na posição 13, na frente de Swift, Kotlin, Dart, etc.
- Pelo 5° ano seguido é eleita a linguagem mais amada no Stack Overflow
- Nas últimas versões 900 desenvolvedores diferentes contribuíram. No histórico total são 2930 contribuídores
- Para comparação, Java nos últimos 6 meses 200 desenvolvedores contribuíram
- Só o Language Server são 200 contribuidores
Vários gigantes apoiam o projeto, tal como AWS, Microsoft, Google, etc. Muitos inclusive com apoio financeiro.
Recentemente Facebook e Microsoft anunciaram ofertas de trabalho para contribuir diretamente no compilador.
"Mas afinal, quem usa em produção?"
Google, Microsoft, Facebook, Amazon, Apple e Discord são alguns dos casos.
Em geral é usado para rotinas de infraestrutura tal como controles críticos de segurança, devops, operações para suportar alta transferência de I/O, processamento paralelos, serviços web de alta performance, etc.
Vale a pena citar também que Rust está sendo aplicado em várias outras bibliotecas e frameworks:
- Fucsia, substituto do Android, onde vários módulos estão sendo escritos em Rust
- Chromium, o engine utilizado nos navegadores Google Chrome e Microsoft Edge, está desenvolvendo novos módulos em Rust
- Deno, substituto do Node, também está sendo desenvolvido em Rust
- Linus Torvands se mostrou favorável para permitir usar Rust para desenvolver módulos do Kernel
- Time core do React está avaliando reescrever rotinas internas em Rust
"Quais são outras características positivas do Rust?"
- Sintaxe moderna
- Não permite null
- Conceito de Ownership e Borrowing
- Conceito de mutabilidade
- Enumerados algébricos
- Generics avançados
- Tuplas (conjunto de tipos heterogêneos)
- Inferência de tipagem inteligente
- Pattern match
- Meta-programação
- Teste unitário no próprio fonte
- Gratuíto e Open Source (licença MIT e Apache 2.0)
- Gera código binário nativo sem runtime ou VM para várias plataformas
- Gera bibliotecas dll/so
- Gerenciamento de thread Work-Stealing
- Gerenciador de pacotes moderno
- Muitas bibliotecas gratuítas
- Várias opções de editores
- Language Server moderno
- Ótima experiência no VSCode, inclusive de debug
"Ouvi falar que Rust não é orientado a objetos"
Vamos revisar quais são os aspectos da OO: abstração, encapsulamento, polimorfismo e herança.
Rust só não possui herança. Vale lembrar que nos tempos atuais herança é considerado um anti-pattern. Se for necessário, é possível conseguir resultado semelhante se utilizando de interfaces e composição. Então a questão sobre Rust ser OO ou não pode ser subjetiva. Independente disso podemos afirmar que Rust é uma linguagem multi-paradigma: procedural, funcional e com elementos da orientação a objetos. Rust também possui outras vantagens que não existem na OO, tal como ownership.
"Sendo tão bom, por que Rust não é usado em regras de negócio?"
Rust introduz alguns conceitos novos que acabam por gerar uma curva de aprendizado maior em comparação a outras linguagens. Alguns desses conceitos exigem o programador a adotar um mindset que antes não era necessário. É interessante comentar: esse tipo de mindset é algo que acaba agregando ao programador uma maneira melhor de programar, sendo útil até para programar em outras linguagens.
Então, dependendo da capacidade do programador, ele pode ter dificuldade para conseguir assimilar algumas coisas - em geral é necessário um certo nível de dedicação e estudo, que talvez nem todos tenham perfil para isso.
Outro aspecto é sobre o reduzido ecossistema de bibliotecas e frameworks para soluções enterprise, que outras linguagem já possuem alternativas já consolidadas.
Em resumo, Rust possui um nicho mais semelhante ao C++ e Go. Entretanto existem sim casos de aplicações web desenvolvidas totalmente em Rust, tanto no backend quanto frontend.
"Rust deve ter uma curva de aprendizado bem grande"
Como foi esclarecido acima, Rust possui sim elementos que não existem em outras linguagens que por sua vez precisam ser estudados.
Porém as características mais complexas podem ser contornadas. Por exemplo: se tiver dificuldade com lifetime use os smart pointers Rc
ou Arc
. Se tiver dificuldade para implementar interfaces (traits) ou sintaxe funcional (closures) use forma a estruturada tradicional.
Ou seja, mesmo sem dominar a linguagem você pode de alguma forma ou outra sobressair e já obter resultados enquanto adquire conhecimento para fazer coisas mais avançadas.
"Então a produtividade deve ser baixa"
No início é natural não se sentir tão produtivo comparando a outra linguagem que você tem mais experiência. Para garantir a segurança do código, o compilador possui algumas regras mais rígidas que o programador pode tomar mais tempo para se adaptar.
Mas muitos já relataram que a longo prazo a tendência é o programador ganhar tempo, pois terá que dar menos manutenção pelo fato do programa ter menos bugs.
Criando uma prova de conceito e definindo onde aplicar
No meu caso procurei um problema real que Rust poderia resolver onde nenhuma outra linguagem conseguiria superar. O caso que escolhi foi reescrever uma rotina feita em Ruby que demorava 20 minutos. O resultado não poderia ser mais satisfatório: a mesma rotina feita em Rust demorou 20 segundos.
Ao invés de reescrever uma rotina existente eu poderia criar uma rotina nova para servir como uma prova de conceito? Sim, mas sem ter uma referência ficaria difícil de dizer o quanto era melhor que outra linguagem. O resultado poderia ser subjetivo e levantar deduções indevidas.
Mas vou querer reescrever todas rotinas Ruby em Rust? Isto é bom ficar claro: não. Ruby tem seu papel bem definido e na maioria das vezes obtém resultados satisfatórios. Porém para rotinas que necessitam de alto poder de processamento Rust pode servir como uma alternativa. Outra possibilidade é para rotinas críticas, mesmo que sem necessidade de alto desempenho, que necessitam de segurança extrema, Rust também pode ser útil para alcançar uma robustez superior.
Conclusão
Quando vamos falar de Rust é importante considerar dois aspectos que devemos nos preparar:
-
Aspecto psicológico. A natureza humana é de restrição a mudanças e aprender coisas novas. Ao descrever Rust cuidado para não mostrar features avançadas demais para não assustar ninguém - deve ficar claro que é possível aprender.
-
Aspecto econômico. Pode existir o receio em perder tempo reescrevendo código legado. É interessante passar a ideia do Rust ser um aliado, e não ser uma solução "bala de prata" para substituir o legado. Saber que existe ganho para a empresa é essencial, a mudança deve resultar em uma vantagem real. Explore ideia de velocidade de processamento, menor consumo de recursos, menos erros, etc.
Quem trabalha com desenvolvimento certamente já escutou isso: "tem que ser rápido", "não pode consumir tanta memória", "não pode ter erro", etc. Eu, sendo um engenheiro de software, não posso ver todos benefícios computacionais do Rust e não imaginar onde pode ser aplicado.
Rust é uma linguagem moderna, inovadora, production ready, que conseguiu combinar segurança e desempenho numa mesma tecnologia. Grandes corporações estão usando e apoiando, que é um fator positivo para sua adoção, criando uma perspectiva de futuro muito sólida. Rust pode ser um poderoso aliado para funcionar em conjunto com outras linguagens. Seu aprendizado requer um pouco mais de dedicação, mas ao final você ganha um prêmio - você conseguirá criar aplicações de alta performance e extremamente consistente.