Architecture Decision Record

Active theme: Light

← Exemplos de registros de decisão

Linguagens de programação

Sumário:

Resumo

Questão

Precisamos escolher linguagens de programação para o nosso software. Temos duas grandes necessidades: uma linguagem de programação de front-end adequada para aplicações web e uma linguagem de programação de back-end adequada para aplicações de servidor.

Decisão

Estamos escolhendo TypeScript para o front-end.

Estamos escolhendo Rust para o back-end.

Estado

Decidido. Estamos abertos a novas alternativas à medida que surgirem.

Detalhes

Premissas

As aplicações de front-end são típicas:

  • Usuários e interações típicos

  • Navegadores e sistemas típicos

  • Desenvolvimentos e implantações típicos

É provável que as aplicações de front-end evoluam rapidamente:

  • Queremos garantir desenvolvimentos, implantações, iterações etc. rápidos e fáceis.

  • Valorizamos a comprovabilidade, como a segurança de tipos, e aceitamos fazer um pouco mais de trabalho para alcançá-la.

  • Não precisamos de compatibilidade com sistemas legados.

As aplicações de back-end estão acima do típico:

  • Metas de qualidade acima do típico, especialmente comprovabilidade, confiabilidade, segurança etc.

  • Metas de quase tempo real acima do típico, ou seja, não queremos pausas devido à coleta de lixo da máquina virtual.

  • Metas de programação funcional acima do típico, especialmente para paralelização, processamento multinúcleo e segurança de memória.

Aceitamos velocidades de compilação menores em favor da segurança em tempo de compilação e das velocidades de execução.

Restrições

Temos uma forte restrição quanto às linguagens que são utilizáveis com os serviços de funções dos principais provedores de nuvem, como o Amazon Lambda.

Posições

Consideramos estas linguagens:

  • C

  • C++

  • Clojure

  • Elixir

  • Erlang

  • Elm

  • Flow

  • Go

  • Haskell

  • Java

  • JavaScript

  • Kotlin

  • Python

  • Ruby

  • Rust

  • TypeScript

Argumento

Resumo por linguagem:

  • C: rejeitada por causa da baixa segurança; o Rust consegue fazer quase tudo melhor.

  • C++: rejeitada porque é uma bagunça; o Rust consegue fazer quase tudo melhor.

  • Clojure: excelente modelagem; melhor aproximação de Lisp; ótimo ambiente de execução na JVM.

  • Elixir: excelente ambiente de execução, incluindo capacidade de implantação e concorrência; excelente experiência do desenvolvedor; ecossistema relativamente pequeno.

  • Erlang: excelente ambiente de execução, incluindo capacidade de implantação e concorrência; experiência do desenvolvedor desafiadora; ecossistema relativamente pequeno.

  • Elm: parece muito promissora; a IBM está publicando grandes estudos de caso com bons resultados; ecossistema menor.

  • Flow: melhoria interessante em relação ao JavaScript; no entanto, os desenvolvedores estão se afastando dela.

  • Go: excelente experiência do desenvolvedor; excelente concorrência; mas com um histórico de más decisões que prejudicam a linguagem.

  • Haskell: melhor linguagem funcional; comunidade de desenvolvedores menor; não alcançou sucessos de produção publicados suficientes.

  • Java: excelente ambiente de execução; excelente ecossistema; experiência do desenvolvedor abaixo da média.

  • JavaScript: a linguagem mais popular de todos os tempos; ecossistema mais difundido.

  • Kotlin: corrige muita coisa do Java; excelente apoio da JetBrains; bons casos publicados de migração do Java para o Kotlin.

  • Python: linguagem mais popular para administração de sistemas; ótimas ferramentas de análise; bons frameworks web; mas abandonada pelo Google em favor do Go.

  • Ruby: melhor experiência do desenvolvedor de todos os tempos; melhores frameworks web; comunidade mais simpática; mas muito lenta; um tanto difícil de empacotar.

  • Rust: melhor linguagem nova; ênfase em abstração zero; ênfase em concorrência; no entanto, ecossistema relativamente pequeno; e tem limites deliberados em alguns tipos de aceleração do compilador, p. ex., o acesso direto à memória precisa ser explicitamente inseguro (unsafe).

  • TypeScript: adiciona tipos ao JavaScript; ótimo transpilador; ênfase crescente dos desenvolvedores na migração do JavaScript para o TypeScript; forte apoio da Microsoft.

Decidimos que as VMs têm um conjunto de trade-offs de que não precisamos agora, como a complexidade adicional que fornece capacidades em tempo de execução.

Acreditamos que nossa decisão central é impulsionada por duas preocupações transversais:

  • Para a maior velocidade de execução e o acesso mais estreito ao sistema, escolheríamos JavaScript e C.

  • Para uma velocidade de execução próxima da maior e um acesso ao sistema próximo do mais estreito, escolhemos TypeScript e Rust.

Menções honrosas vão para as linguagens de VM e os frameworks web que escolheríamos se quiséssemos uma linguagem de VM:

  • Clojure e Luminus

  • Java e Spring

  • Elixir e Phoenix

Implicações

Os desenvolvedores de front-end precisarão aprender TypeScript. Essa provavelmente é uma curva de aprendizado fácil se a experiência principal do desenvolvedor for com JavaScript.

Os desenvolvedores de back-end precisarão aprender Rust. Essa provavelmente é uma curva de aprendizado moderada se a experiência principal do desenvolvedor for com C/C++, e uma curva de aprendizado difícil se a experiência principal do desenvolvedor for com Java, Python, Ruby ou linguagens semelhantes com gerenciamento automático de memória.

TypeScript e Rust são ambas relativamente novas. Isso significa que muitas ferramentas ainda não têm documentação para essas linguagens. Por exemplo, o pipeline de devops precisará ser configurado para essas linguagens e, até agora, nenhuma das ferramentas de devops que estamos avaliando tem exemplos padrão para elas.

Os tempos de compilação de TypeScript e Rust são bastante lentos. Parte disso pode se dever à novidade das linguagens. Podemos querer examinar como atenuar tempos de compilação lentos, como por compilação sob demanda, concorrência de compilação etc.

O suporte de IDE para essas linguagens ainda não é onipresente nem de primeira classe. Por exemplo, a JetBrains vende a IDE PyCharm com suporte de primeira classe ao Python, mas não vende uma IDE com suporte de primeira classe ao Rust; em vez disso, a JetBrains pode usar um plugin de Rust que fornece talvez 80% do suporte à linguagem Rust em relação ao suporte à linguagem Python.

Relacionado

Decisões relacionadas

Buscaremos escolhas de ecossistema que se alinhem a essas linguagens.

Por exemplo, queremos escolher uma IDE que tenha boas capacidades para essas linguagens.

Por exemplo, para o nosso framework web de front-end, é mais provável que decidamos por um framework que tende a mirar o TypeScript (p. ex., Vue) do que por um que tende a mirar o JavaScript puro (p. ex., React).

Requisitos relacionados

Toda a nossa cadeia de ferramentas deve dar suporte a essas linguagens.

Artefatos relacionados

Esperamos que possamos exportar alguns segredos para variáveis de ambiente.

Princípios relacionados

Meça duas vezes, construa uma. Estamos priorizando alguma segurança em detrimento de alguma velocidade.

O tempo de execução é mais valioso do que o tempo de compilação. Estamos priorizando o uso pelo cliente em detrimento do uso pelo desenvolvedor.

Notas

Quaisquer notas aqui.