(Photo by Roman Spiridonov on Unsplash)Sistemas definidos, podemos agora definir Programação de Sistemas como o ato de construir Software de Sistemas usando Linguagens de Programação de Sistemas. Suficientemente simples, certo?
Bem há uma coisa que saltamos, as linguagens. As pessoas frequentemente falam sobre Linguagens de Programação de Sistemas de maneiras como “X é ótimo, é rápido, compilado, e uma linguagem de programação de sistemas”. Mas todos estão na mesma página do que é uma linguagem de programação de sistemas?
Dadas as nossas definições de Sistemas eu definiria o critério para que uma Linguagem de Programação de Sistemas fosse:
- Compilada com binários nativos
- Pode ser construída sem dependências de outros softwares (incluindo um kernel)
- Características de desempenho similares a outras linguagens de programação de sistemas
Disclaimer: Esta é a minha definição. Como não há critérios definidos, eu estou derivando uma definição do que faz sentido para mim dado o contexto no qual eu defini software de sistema.
Compile to Native Binary
Se uma linguagem não pode compilar para um executável que é diretamente interpretável pelo CPU então ela, por definição, está rodando em uma plataforma (por exemplo, JVM, Ruby VM, Python VM, etc). Pode haver alguns argumentos a serem feitos aqui, mas por simplicidade penso que este é um critério adequado.
Sem dependências
O argumento é semelhante à compilação de um binário nativo. Se a linguagem sempre requer que algum outro software esteja presente para ser executado, então ele está sendo executado em uma plataforma. Um exemplo disto é Go e está incluída a biblioteca padrão. Ela requer suporte do sistema operacional para executar ações básicas como alocação de memória, desova de threads (para os goroutines rodarem), para o seu poller de rede embutido e outras ações. Embora seja possível reimplementar estas funções centrais, isto cria uma barreira para o uso neste contexto e é fácil de imaginar porque nem todas as linguagens, mesmo aquelas que compilam para binários estáticos, são destinadas como linguagens de programação do sistema.
Características de Desempenho Similares
Esta é um pouco de cop-out. No entanto, é para dizer que dentro do sistema de linguagens tipicamente classificadas como linguagens de programação de sistemas, não deve haver grandes diferenças (ordem de grandeza) nas características de desempenho. Por características estou me referindo explicitamente à velocidade de execução e eficiência da memória.
O padrão dourado para comparação é C e/ou C++ como é frequentemente representado em benchmarks comparativos, que medem a velocidade de execução em quantas ordens de grandezas as linguagens são mais lentas que C/C++.
Nomeando um Pouco
As linguagens que vêm à mente imediatamente, dada a definição acima são C e C++. Mas existem também novas linguagens como Rust e Nim, que também preenchem este nicho. De facto, já existe um SO escrito inteiramente em Rust (RedoxOS) e um kernel em Nim (nimkernel).
Let’s Talk About Go
Earlier Eu insinuei que Go pode não se enquadrar na família de “linguagens de programação de sistemas”. No entanto, assim como nem todas as aplicações se encaixam bem em software de aplicação e software de sistema, nem as linguagens.
Muitas pessoas chamarão Go de linguagem de programação de sistemas e até golang.org é citado como:
Go é uma linguagem de uso geral projetada com a programação de sistemas em mente.
No entanto, mesmo isto não é uma afirmação direta de que Go é uma linguagem de programação de sistemas, simplesmente que é projetada com isto em mente. Eu acho que ela está no meio.
While Go compila binários nativos, contém conceitos úteis de baixo nível (ponteiros em bruto/insegurança, tipos nativos como bytes e int32, e suporte a montagem em linha), e é relativamente performativa; ainda tem alguns desafios a superar. Go navios com um tempo de execução e um coletor de lixo.
Um tempo de execução significa que bootstrapping/overriding do tempo de execução será necessário para rodar em ambientes sem kernels. Isto entra mais na implementação interna da linguagem, o que pode mudar em lançamentos futuros. Mudanças requerem trabalho de bootstrapping adicional conforme a linguagem evolui.
A garbage collector (GC) significa que o Go é restrito em quais domínios de aplicação ele pode ser usado ou que o GC deve ser desabilitado e substituído por gerenciamento manual de memória. No caso do GC não poder ser substituído, o domínio em tempo real (definido por operações que devem ser completadas dentro de determinados limites de tempo e/ou o desempenho é medido em nano-segundos) não seria capaz de arriscar tempos de pausa não determinísticos de um GC.
Software de Sistemas Distribuídos
Com a crescente conversa sobre sistemas distribuídos, e aplicações como Kubernetes se tornando muito popular, podemos ouvir uma série de vocabulário novo que (se estivermos sendo honestos) a maioria de nós não entende completamente.
Até este ponto, eu vi os termos programação de sistemas e engenheiros de sistemas usados em contextos onde o que eles realmente significavam era programação de sistemas distribuídos e engenheiros de sistemas distribuídos.
Nós definimos software de sistemas, linguagens de sistemas, e programação de sistemas neste post. Entretanto, quando falamos de sistemas distribuídos, o significado de sistema muda. E embora eu não vá mergulhar nas diferenças específicas aqui (principalmente porque eu mesmo ainda preciso de as entender melhor), é importante que façamos essas distinções mentais e usemos um discurso mais exacto quando pudermos evitar confusão para aqueles que ainda estão a aprender o espaço.