Bem, se você abriu esse artigo, então, tenho certeza que está interessado em entender um pouco mais sobre o ecossistema de Crystal. Antes de mais nada, vamos primeiramente introduzir o que é Crystal e onde se aplica.
Índice
- O que é Crystal?
- Ruby e Crystal
- Integração nativa com LibC
- Ferramentas
- Frameworks
- Projetos com Crystal
- Finalização
O que é Crystal?
Crystal é uma linguagem de programação de código aberto, com sintaxe inspirada no Ruby, que visa a produtividade e o desempenho. Ele tem uma sintaxe elegante e uma tipagem estática, mas sem a necessidade de declarar tipos de variáveis. O Crystal é compilado para código nativo, e não para bytecode, e usa LLVM para gerar o código binário.
A aplicabilidade de Crystal é vasta, podendo ser visto de diferentes formas, mas, consigo afirmar que a ênfase de aplicabilidade ocorre para aplicações web, na qual consegue se destacar em pontos específicos exatamente por ser uma linguagem de programação compilada.
O principal motivo para o surgimento de Crystal foi para resolver alguns problemas bem específicos que Ruby possuia, porém, seriam solucionados deixando de lado a dinamicidade que Ruby proporcionava para abrir espaço para uma linguagem de programação totalmente nova, com a possibilidade de inferência de tipos, sendo compilada. Assim, em 2011 surge o projeto de uma nova linguagem de programação, criada por Ary Borenszweig, Juan Wajnerman e Brian Cardiff, contando hoje com mais de 450 colaboradores do mundo todo, tendo seu código fonte disponibilizado no repositório oficial do GitHub.
Ruby e Crystal
Como citado anteriormente, Ruby por sua vez possui uma sintaxe muito elegante, na qual Crystal se inspirou em sua maior parte exatamente pelo contexto de desenvolvimento da época, desejando uma linguagem de programação elegante na sintaxe como Ruby, veloz como C, podendo ainda realizar otimizações nativas com interoperabilidade utilizando a LibC e o melhor: sem escrever uma linha de código em C. Parece mágica não é? Bem, é apenas Crystal!
Uma analogia para entender melhor a compatibilidade de ambas as linguagens de programação que gosto de fazer é: imagine que você hoje é dono de uma empresa que possui N desenvolvedores Ruby, que consequentemente são a maioria dentro da empresa. Em um belo dia você em uma conversa com seus arquitetos de software decidem que uma linguagem compilada é necessária em apenas alguns serviços que estão funcionando hoje. Ao invés de simplesmente reescrever todo o código em alguma outra linguagem compilada, você pode reaproveitar toda a base de código para utilizar e compilar em Crystal, assim, a curva de aprendizado para seus desenvolvedores Ruby será praticamente nula, afinal, apenas alguns pontos específicos requerem maior cuidado ao se trabalhar com Crystal, como por exemplo a verificação de tipos, que pode ser um pouco estranho no início, mas, garanto que com o passar do tempo será mais prática a manutenção de seu código.
Entenda que Crystal não veio para substituir o Ruby, mas, para que ambos possam ser utilizados em conjunto, visando um melhor aproveitamento de código, melhor eficiência e melhor ambiente de desenvolvimento. O exemplo que deixarei abaixo demonstra a diferença de dois códigos que fazem a mesma coisa, porém, Crystal possui uma peculiaridade específica que vou retratar logo abaixo.
def soma(a, b)
a + b
end
print "Digite o primeiro número inteiro: "
a = gets.chomp.to_i
print "Digite o segundo número inteiro: "
b = gets.chomp.to_i
puts "A soma dos números é #{soma(a, b)}"
O código acima é bem simples: pedimos para o usuário informar dois números, a
e b
respectivamente, na qual chomp
remove o enter (\n
ou \r
) e o to_i
converte o valor para inteiro. Agora, em Crystal precisamos apenas adicionar uma validação bem simples:
def soma(a, b)
a + b
end
print "Digite o primeiro número inteiro: "
a = gets
print "Digite o segundo número inteiro: "
b = gets
# É necessário validar se o valor é nil!
if a.nil? || b.nil?
puts "Você deve digitar dois números inteiros."
exit
end
puts "A soma dos números é #{soma(a.chomp.to_i, b.chomp.to_i)}"
A validação é necessária para não enviarmos um valor nulo para o método chomp
, afinal, ele está esperando receber uma String
e sem a validação estaremos enviando um String | Nil
, não validando com o tipo esperado. Nesse momento você deve estar pensando: mas, os tipos enviados foram validados em tempo de compilação? Isto é, a inferência dos tipos foi feita sem eu precisar falar nada? Bem, a resposta é sim, o compilador automaticamente adivinhou de quais tipos se tratavam.
Certo, agora você deve perguntar: nossa mas eu também consigo inferir os tipos manualmente? Como por exemplo na função soma
, informando os tipos dos parâmetros que espero receber, além do tipo do retorno? A resposta é sim, e neste caso ficaria algo como o exemplo abaixo:
def soma(a : Int32, b : Int32) : Int32
a + b
end
Interessante, certo?
O principal ponto é dar nas mãos do desenvolvedor a possibilidade de nivelar exatamente o que um método deve ter e/ou deve retornar.
Integração nativa com LibC
Se você quer utilizar ferramentas da LibC, mas, sem a necessidade de escrever código em C, então Crystal pode te ajudar com isso. Com bindings nativas você pode utilizar bibliotecas externas, incluindo a LibC, para utilizar ferramentas que seriam possíveis apenas escrevendo código nativo em C.
Para entender um pouco melhor sobre o funcionamento, recomendo seguir a documentação oficial, porém, deixarei um exemplo abaixo,
lib C
# Em C: double cos(double x)
fun cos(value : Float64) : Float64
end
O exemplo acima demonstra o uso da função
cos
Ferramentas
Como todo desenvolvedor, nada melhor do que saber como preparar seu ambiente de desenvolvimento com Crystal, não é mesmo? Bem, vamos então navegar por algumas tecnologias que vão te ajudar nessa jornada.
Language Server Protocol (LSP)
Como todo bom desenvolvedor, sabemos que um LSP pode nos auxiliar muito durante o desenvolvimento de software, por isso, o LSP que estarei recomendando para uso com Crystal é o Crystalline, na qual você poderá configurar de forma simples na maioria dos editores de código que esteja utilizando.
Basicamente o Crystalline vai disponibilizar um executável simples, sendo totalmente escrito em Crystal. Você pode seguir os passos deixados no próprio repositório para configurar seu ambiente, porém, gostaria de dizer que um dos guias de configuração que contribuí foi para o Emacs, utilizando o emacs-lsp.
Minhas recomendações para editores de código são bem pessoais, porém, recomendaria alguns como Visual Studio Code, Sublime Text, Vim e Emacs.
Read-Eval-Print Loop (REPL)
Desenvolver ao lado de um REPL é uma experiência simplesmente magnífica e recomendo sempre que possível, por isso, Crystal não fica de fora no mundo de REPLs e possui o icr como REPL oficial, vindo hoje já embutido no próprio Crystal, podendo ser acessado com o comando crystal i
!
Basicamente a funcionalidade principal do REPL é ser seu companheiro durante o desenvolvimento, possibilitando a execução de trechos do código de forma isolada sem muitos problemas.
Code style linter
Mais importante do que escrever código para si mesmo é escrever código para outras pessoas, por isso, sempre que possível é recomendado escrever códigos de acordo com as convenções de cada linguagem de programação. Dessa forma, Crystal possui uma convenção de estilo de código incrível, logo, nada mais justo do que uma ferramenta que te ajude no processo de escrita.
Assim surge o projeto Ameba, sendo um linter para validar seu código e verificar se está adequado de acordo com as convenções apresentadas oficialmente.
Debugger
Nada melhor do que poder rodar seu código passo por passo para validar problemas e rotinas, não é? Pois bem, o projeto debug surge com objetivo de ser um debugger completo para seu desenvolvimento, sendo escrito completamente em Crystal.
Gerenciador de dependências
Dependências podem ser definidas como um conjunto de pacotes/bibliotecas que são necessárias para a execução de determinada aplicação. Gerenciar dependências de forma elegante é algo que Crystal não decepciona utilizando o projeto Shards.
Basicamente existe um arquivo chamado shard.yml
, utilizado para definir de maneira simples pontos como nome do projeto, autores, dependências, versão atual e licença em que determinado projeto é distribuído.
Livro
Um livro sobre a linguagem é necessário, não apenas para ser utilizado como referência, mas, para ser utilizado no processo de aprendizado do leitor.
Assim surge o projeto crystal-book, sendo um livro completo com referências da documentação oficial.
Documentação
A documentação oficial é necessária para qualquer tecnologia, assim, Crystal possui dois tipos de documentações que podem ser encontradas, sendo elas:
A segunda referência geralmente é utilizada para um detalhamento maior dos métodos e funcionalidades nativas que Crystal proporciona.
Patterns
A definição de patterns e padrões de código é necessária, por isso, existe um repositório com exemplos didáticos de implementações com Crystal utilizando os patterns GOF (Gang of Four), chamado crystal-patterns.
Frameworks
Atualmente, Crystal conta com diversos frameworks para diversos propósitos, porém, irei citar os mais conhecidos para desenvolvimento de aplicações web no geral.
Kemal
Sendo um dos frameworks mais conhecidos, Kemal se destaca por ser inspirado no estilo de outro framework já existente para Ruby, o Sinatra, sendo utilizado para ser uma solução simples, com tratamento de rotas elegante, possibilitando um middleware que pode ser ampliado.
Sua implementação ocorre de forma simples, sendo bem minimalista, assim, uma comparação deixada no site oficial do Kemal compara a quantidade de requisições por segundo de uma aplicação com Kemal comparada com uma aplicação Ruby com Sinatra: enquanto o Sinatra conseguiu chegar em 5268 requisições por segundo, Kemal conseguiu atingir invejadas 122697 requisições por segundo (magnífico, não é?).
Amber
Com uma proposta um pouco diferente do Kemal, porém, levando tanto o Kemal quanto Rails e Phoenix como inspiração, temos o Amber, um framework para aplicações robustas, possuindo templates de renderização HTML prontos, possibilitando um desenvolvimento mais produtivo.
O framework conta com a possibilidade de uso de três ORMs distintos, sendo eles Jennifer, Granite e Crecto.
Lucky
Sendo um framework inspirado principalmente no Rails, o Lucky é um framework que está no coração de grande parte dos desenvolvedores que alguma vez já trabalharam com Crystal, trazendo infinitas possibilidades, sendo extremamente rápido e produtivo!
O repositório oficial está disponível no GitHub, tendo consigo também um artigo interessante falando sobre o uso do Lucky na perspectiva de um desenvolvedor que já trabalhou alguma vez com Rails. O nome do artigo é Ruby on Rails to Lucky on Crystal: Blazing fast, fewer bugs, and even more fun e recomendo a leitura.
Marten
Um framework novo, porém com propostas interessantes, trazendo conceitos novos para o mundo de desenvolvimento com Crystal, ampliando a simplicidade e produtividade dentro do seu código. Este é o Marten, tendo seu repositório oficial publicado no GitHub já está tomando espaço e crescendo cada vez mais como um dos frameworks para Crystal que tende a melhorar ainda mais.
Já ganhou um espaço especial no meu coração e tenho certeza que você vai adorar utilizar o Marten em seu cotidiano como desenvolvedor.
Projetos com Crystal
Bem, como foi possível observar, a aplicabilidade de Crystal é bem vasta e existem diversas ferramentas para te auxiliar durante todo o processo, mas, quais projetos reais já existem e levam como base o uso de Crystal? Bem, vamos passar citando alguns maneiros se você talvez esteja pensando em começar a contribuir...
- Awesome Crystal: conjunto de repositórios, bibliotecas e ferramentas para uso no desenvolvimento com Crystal, trazendo tudo de melhor que o ecossistema pode te proporcionar
- Invidious: um projeto que tem crescido muito e traz consigo o objetivo de ser uma alternativa para o front-end do YouTube, reduzindo a quantidade de JavaScript a ser renderizado, sendo distribuído sob licença AGPL 3.0
- Slang: uma linguagem de template inspirada no Slim para construção de páginas web sem a necessidade de escrever HTML puro
- Immutable: uma implementação completa de uma coleção de estruturas de dados imutáveis, thread-safe e persistente, possibilitando uma melhor segurança no processamento e acesso de memória
- Hetzner k3s: um CLI completo para gerenciamento de cluster Kubernetes na Hetzner Cloud utilizando a distribuição k3s
- Hackacrow: um CLI completo para validação de entradas e saídas de comandos, sendo útil principalmente para validações de respostas em hackathons
-
Crystal ZSH: um plugin completo para utilizar junto do
oh-my-zsh
, permitindo uma integração magnífica com seu terminal durante o desenvolvimento com Crystal -
Editor Plugins: sendo uma área específica de outro repositório (
awesome-crystal
nesse caso) conta com plugins interessantes para diferentes editores de código, por isso, recomendo conhecer
Existem diversos outros projetos com Crystal, porém, acredito que vale a pena conferir o primeiro repositório citado anteriormente para conhecer outros projetos que utilizam Crystal.
Finalização
O intuito desse artigo foi apresentar um pouco mais sobre a proposta que Crystal traz no mundo de desenvolvimento de software, citando ferramentas e projetos que podem fazer parte do seu cotidiano de desenvolvimento.
Se você quer aprender um pouco mais sobre Crystal com um conteúdo totalmente gratuito, em português, escrito com muito amor e carinho, recomendo a leitura do crystal4noobs, um conteúdo parte do projeto 4noobs da He4rt Devs, trazendo conteúdo de qualidade para todos de forma gratuita.
Agradeço imensamente se você chegou até aqui e espero que tenha gostado da leitura. Não se esqueça de deixar sua estrelinha os repositórios apresentados. Espero que esse artigo possa crystalizar ainda mais sua rotina de desenvolvimento. Meu muito obrigado e até a próxima!
Da comunidade para a comunidade 💜💛