Executando verificação de segurança...
7

Porque Rust é a linguagem que desenvolvedores backend estiveram esperando desde sempre

Eu não vou explicar o que é rust aqui, tem toneladas de conteúdo sobre isso já, então vamos direto ao ponto:

Macros

Vamos começar com a maior bruxaria do rust, os macros

Em linguagens como javascript, geralmente recorremos a programas externos que geram código, como o tsc (typescript), jsx (react), o antigo babel e etc... mas isso tem uma desvantagem, é preciso passar por um passo de pre processamento antes de executar o código.

No rust temos macros, podemos criar macros de maneira declarativa, que recebe alguns argumentos e faz um substituição simples parecido com macros em linguagens como C e C++, mas aqui entra a bruxaria, proc macros:

Proc macros são nada mais nada menos que funções que são executadas em tempo de compilação, o compilador compila essas funções e executa elas em tempo de compilação, e tudo que elas fazem é receber um punhado de tokens e cospe tokens, mas o fato de ser uma função, nos dá a possibilidade de interagir com o mundo externo, vamos olhar para um exemplo de biblioteca que faz uso desta funcionalidade.

SQLx, Cliente para banco de dados SQL

A biblioteca SQLx é um cliente para bancos de dados sql, como postgres, mysql, sqlite, entre outros.

A grande sacada do SQLx é que ele consegue se conectar no banco de dados em tempo de compilação e testar as queries no seu banco de dados local, vamos dar uma olhada nela:

let pool = PgPoolOptions::new().max_connections(5).connect("postgres://postgres:password@localhost/test").await?;

let user_id = "us_KnnOjOHsfy4454hLY3f22JutkuygK865uhy";
// Nenhum problema
let user = sqlx::query!("SELECT * from users WHERE id = $1", user_id)
  .fetch_one(&pool)
  .await
  .expect("Usuário não foi encontrado ou houve algum problema enquanto a query executava");

Aqui conectamos num banco de dados postgres com uma tabela chamada users e fazemos uma query simples de select, se o banco de dados retornar exatamente 1 resultado, o sqlx vai armazenar dentro da variavel user, e a macro query! inclusive gerou uma struct dentro do macro para tipar essa variavel e conseguimos ter auto complete sem precisar chamar ferramentas externas diretamente para gerar código 🎉, o valor retornado vai ter todas as colunas que o banco retornar nessa query, não é necessáriamente o schema da tabela, dependende do que pedir pro banco dentro da query e o sqlx te dá a liberdade de fazer o que você quiser.

Agora vamos ver o que acontece quando cometemos erros de sintaxe ou tipagem na query:

// Isso não compila:
let user = sqlx::query!("INSERT INTO users(year) VALUES ('Tiago Dinis') RETURNING *", user_id)
  .fetch_one(&pool)
  .await
  .expect("Usuário não foi encontrado ou houve algum problema enquanto a query executava");

Dá um erro aqui porque estamos tentando colocar uma string numa coluna que espera ter um numero, o sqlx conectou no nosso banco de dados local e testou a query numa transaction, o banco retornou um erro porque o tipo da coluna year INT não bate com o tipo do valor especificado para ser inserido ('Tiago Dinis'), e o sqlx vai dar erro e parar a compilação.

Se precisar de usar as suas proprias structs, você pode criar uma struct normalmente sem nenhum derive, e usar a macro query_as! inves de query! e passar o nome da struct no primeiro parametro assim: sqlx::query_as!(User, "SELECT ...", params...)

Com isso, o sqlx consegue completamente substituir um ORM completamente, ORMs hoje em dia não sao usados pra conseguir trocar de banco facilmente, são usados para fazer a conversão das colunas em objetos da propria linguagem, e o sqlx consegue fazer isso muito bem.

Veja mais sobre o sqlx no repositorio no github: https://github.com/launchbadge/sqlx

Se ficou preocupado que isso possa aumentar a complexidade para compilar o projeto, o sqlx tem a feature offline.

Você primeiro vai precisar instalar a CLI do sqlx com o comando cargo install sqlx-cli, após isso, ao rodar o comando cargo sqlx prepare, o sqlx vai gerar um arquivo chamado sqlx-data.json, com as informações de todas as queries do projeto, e precisa ser rodado sempre que adiciona ou remove alguma query no projeto, na sua maquina não precisa rodar toda hora, so vai precisar quando for commitar, e lembresse de comitar esse arquivo no git, é extremamente importante!

O sqlx vai ler esse arquivo caso a variavel DATABASE_URL não esteja definida ou SQLX_OFFLINE=1, e assim ele permite que você compile o projeto mesmo sem ter um banco de dados rodando.

Tambem recomendo que se for utilizar esta funcionalidade, coloque o comando cargo sqlx prepare --check na sua pipeline/CI para verificar se o arquivo sqlx-data.json está atualizado.

Error Handling

Exceptions são a pior coisa inventada na história, ainda mais no javascript! já não é a primeira vez que tento debuggar um bloco de catch porque nao sei qual é o tipo de erro e só quero fazer uma determinada coisa so em um caso de erro especifico.

Erros não deveriam ser excecionais, deveriam ser esperados, é um efeito colateral de interajir com o mundo externo.

Isso é uma coisa que GoLang tambem acertou muito, retornar os erros como valores das funções, mas, isso não é suficiente.

O rust lida com os erros com o enum Result<T, E>, onde T é o valor retornado no caminho feliz, e o E sendo o valor de Erro.

Enums no rust são um pouco diferentes dos enums de outras linguagens como C, C++ ou TypeScript, vamos ver como o enum Result é definido na std library:

enum Result<T, E> {
    Ok(T),
    Err(E)
}

Você: Ue? mas o que é esse (T) e (E)?

Pois é meu amigo, as variantes dos enums do rust podem armazenar valores dentro, isso mesmo! você não precisa fazer uma struct com um tipo e depois todas as fields, em que algumas so sao válidas em um certo estado!

Se recebermos um valor do tipo Result, não sabemos se é Ok(T) ou Err(E), e o rust vai nos obrigar a verificar qual dos dois nós recebemos, e como verificamos isso? E é ai que vem o próximo ponto deste post:

Modelando informações sem OOP, Pattern matching, e fazendo com que estados invalidos sejam inrepresentaveis.

Vou colocar um exemplo do Tris do canal No Boilerplate, que inclusive recomendo assistir se quiser saber ainda mais sobre o que estou falando aqui nesse post.

O Tris, enquanto olhava um manual de um jogo do mario, encontrou uma maquina de estados assim:

Podemos modelar os estados deste sistema com um enum:

#[derive(Debug, PartialEq)]
enum State {
    Mario,
    SuperMario,
    CapeMario,
    FireMario
}

Agora vamos modelar os powerups que o mário pode coletar e que faz o mario transitar entre os estados:

#[derive(Debug, PartialEq)]
enum PowerUp {
    Feather,
    Flower,
    Mushroom
}

E agora podemos tambem criar a nossa struct para o jogador, com o estado que modelamos antes:

#[derive(Debug)]
struct Player {
  state: State,
  lives: u16,
}

Agora entra a mágica, vamos criar uma função que é chamada quando o mario coleta um power up, e faz o mario mudar de estado:

impl Player {
    pub fn new() -> Self {
        Self { state: State::Mario }
    }
    pub fn collect(&mut self, collected_power: PowerUp) {
      match (&self.state, collected_power) {
          (Mario, Mushroom) => self.state = SuperMario,
          (_,     Flower)   => self.state = FireMario,
          (_,     Feather)  => self.state = CapeMario,
          (_,     Mushroom) => self.lives += 1
      }
    }
}

Aqui utilizamos o match, que é similar a um switch, mas é muito mais poderoso, ele pode desconstruir objetos e verificar valores como nenhuma outra linguagem faz.

No match criamos uma tupla com uma referencia para o estado no primeiro elemento, e o power up no segundo elemento, e nós verificamos dentro do match cada possibilidade, e o compilador vai obrigar o match a ser exaustivo, ou seja, ele precisa lidar com todas as possibilidades, e é assim que nunca mais temos edge-cases.

Velocidade

Isso não é nenhuma surpresa para ninguem, mas o fato que conseguimos ter todas essas funcionalidades e ainda ter uma performance muito proxima de C, é simplesmente incrivel, é pena as pessoas so não terem visto todo esse poder ainda.

Ferramentas

Se você quiser usar rust para o seu próximo projeto, você tem tudo que precisa para começar, o ceu é o limite, todas as ferramentas para construir aplicações, APIs, CLIs, não está no futuro, elas estão agora presentes neste exato momento.

Frameworks web: actix, axum
Client de SQL: sqlx
ORMs: sea-orm, diesel
Frontend (webassembly): Dioxus, Yew, Leptos
Pagamentos com stripe: async-stripe
E muito mais!

Conclusão

E com isto termino este post gigantesco, onde mostro que rust está mais que pronto para ser usado nos seus proximos projetos e que vai ajudar a ter menos bugs nas suas aplicações.

Tem alguma coisa para dizer? Quer usar rust no seus proximos projetos? Ou você nem sequer é programador e não tem a minima ideia do que ta fazendo? Não deixe de deixar um comentário aqui!

Carregando publicação patrocinada...
2

Cara que post incrível, eu como um programador apaixonado por rust senti o coração ser aquecido com esse post, e pessoal que tem interesse, estou fazendo uma série de posts que cobrirá o livro de rust só que de forma linear (o livro é cheio das "ignore a linha x pq será explicado no capítulo y") e em português, link.

2

Eu gostava imenso de tocar um pouco em Rust, estou trabalhando atualmente com C++ na faculdade e depois de aprender as bases de uma linguagem do gênero fiquei com curiosidade do Rust por tudo de bom que falam dela, só não toquei nela ainda sobretudo por falta de tempo e porque não sei muito bem o que poderia fazer com a linguagem já que a maior parte de coisas que vejo fazerem são coisas low level (relacionados com drivers ou sistemas operativos, coisas que não tenho nada de conhecimento)

1

Se está trabalhando com c++ provavelmente está num dos lugares que o rust funciona melhor

Qualquer coisa que precisa de uma linguagem como c++, rust encaixa-se como uma luva. Inclusive é possivel ter interoperabilidade entre C++ e rust, então pode até ser usado em projetos c++ existentes

2
1

Estou estudando programação, tenho um pouco de conhecimento em desenvolvimento web, rust é uma boa para um iniciante?

1

🤔 olha amigo, acredito que talvez não seja a melhor opção. Talvez fosse melhor focar primeiro e, alguma outra coisa e depois ir pra Rust, já que ele tem uma curva de aprendizado inicial um pouco mais íngreme do que outras linguagens como Python e JS. Tentar abraçar muitas coisas no início pode acabar desanimando ao invés de animar.

Uma coisa que sempre recomendo é fazer o CS50x. Isso dá uma boa base para aprender qualquer outra coisa nova nessa nossa área. Além disso, com linguagem C, você vai poder experimentar o problema que Rust resolve.

No canal NoBoilerplate (mencionado no post) inclusive tem um vídeo respondendo essa pergunta que você fez.

1

Acho bom falar também sobre mercado, que é algo que Rust não tem. Apesar que eu tô aprendendo apostando no crscimento dele, como foco é sempre bom aprender algo que vai ter dar um emprego como JS, Java, PHP entre outros.

1

Parabéns pelo conteúdo, de fato Rust é minha lang favorita mas infelizmente ainda não tem muitas vagas pra ela.
Só esqueceu de colocar o rocket nos frameworks web.

1
1

De fato o versionamento do Rocket é um pouco diferente, mas ele recebe atualizações sim (mas são releases candidates), até saiu uma agora mês passado. Mas acho que também tem haver com a equipe por trás (parece ser só 1 cara, enquanto q no Actix tem mesmo uma organization com mais gente).
Eu pelo menos estou tentando contribuir um pouco lá com o projeto, terminei a pouco a implementação de uma lib/plugin para adicionar suporte ao protocolo tus, dps tenho que criar aqui uma postagem contando minha 1º experiencia desenvolvendo um projeto open source de verdade.
Achei a pegada do Rocket mais simples de usar e aprender então foi o framework que me indentifiquei mais, por isso que tou aqui defendendo ele kkk Mas sim como você disse o Actix parece estar ganhando mais espaço e as vezes pode ser uma escolha mais viável para projetos de produção. Sobre a velocidade eu n cheguei a comparar.

1

Muito bom! já tinha ouvido falar muito sobre Rust ser uma boa linguagem, esse post até agora foi a melhor explicação que vi sobre as vantagens dela!