BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Não misture as Tintas! Primitivas e compostas no mundo do software

Não misture as Tintas! Primitivas e compostas no mundo do software

Pontos Principais

  • Os materiais (código, interfaces, requisitos, entre outros) são derivados de primitivas sintéticas;

  • A natureza sintética dos materiais mostra que não podemos confiar neles;

  • Para usar os materiais, precisamos adotar uma mentalidade de questionar tudo;

  • Não podemos confiar em nós mesmos para usar consistentemente a mentalidade de questionamento;

  • Podemos usar sistemas para atualizar o mindset, criando confiabilidade onde não havia.

Qual cor vem a sua mente quando ouve a palavra "vermelho"?

Pergunte a 100 pessoas, e teremos 100 respostas diferentes. Mesmo tendo uma referência para ajudar, como uma lata de Coca-Cola, vamos ter respostas diferentes.

Assim começa o livro "The Interaction of Color" escrito por Josef Albers, onde o autor utiliza esse estudo das cores para mostrar a complexidade das interações. Ele observa que até mesmo os artistas profissionais ficam surpresos quando apresentados os exemplos, o que indica o quão inconstante é a mente humana na interpretação das cores.

Para treinar o olho, Albers faz com que os alunos realizem experimentos que demonstram conceitos como intensidade, brilho, reversão, transparência, adição, subtração, mistura e assim por diante. Ao fazer esses experimentos, os alunos trabalham em vários cenários, manipulando combinações de cores para revelar as interações.

É interessante notar que Albers não usa pigmento ou tinta para tais experimentos, mas recortes de papel, pois fornecem a maneira mais confiável de testar cenários repetidamente. As cores impressas são fixas e indivisíveis.

Os elementos indivisíveis são críticos para a experimentação porque são irredutíveis, criando um alto grau de confiabilidade, que é necessário para trabalhar com testes e também para comparar os resultados.

No software, também nos envolvemos intensamente em experimentos e também precisamos de elementos indivisíveis para trabalhar. Nós chamamos de "primitivas" e se dividem dois tipos. Dinâmicas e semânticas.

Primitivas dinâmicas

O software é construído em camadas de abstrações. O machine learning é abstraído usando primitivas de microcódigo, que é apresentado como linguagens de alto nível e assim por diante. Em cada nível, são apresentados elementos simples que abstraem a complexidade das operações implícitas.

O desenvolvimento de software moderno envolve principalmente a sintetização de uma variedade de elementos externos: software open source, serviços de terceiros, APIs de infraestrutura e assim por diante. Nós juntamos tudo isso usando código para criar os sistemas. É um mundo composto e os sistemas são misturas de módulos colados com código.

Idealmente, gostaríamos de ter elementos projetados para serem usados como primitivas. Se ler a literatura que remonta a mais de 50 anos, verá os mesmos conselhos sobre arquitetura: Pratique o design modular, criando blocos de construção primitivos, separando bem a implementação da interface. "Não misture as tintas"!

Esta é a lógica que impulsionou o desenvolvimento da AWS, oferecer aos clientes uma coleção de primitivas para que possam escolher a forma preferida de utilizar os serviços, ao invés de uma única estrutura que te force uma forma específica de trabalho, que inclui quase tudo o que possa imaginar.

Claro, tudo isso na prática não é tão fácil, muito menos se precisar escalar. Veja a Lei de Hyrum, que diz que, com um número suficiente de usuários, todos os comportamentos observáveis dependerão de alguém. Em outras palavras, não existe uma implementação privada. Fingimos que tudo que está abaixo da interface pode ser escondido, mas não é a realidade.

Talvez pudéssemos confiar nas interfaces como o artista confia nas leis da química e da física, todavia as coisas que construímos também não são muito confiáveis. Acidentes podem acontecer em várias camadas abaixo de que estamos trabalhando, resultando em mudanças massivas em toda a pilha (veja Spectre ou Meltdown).

As implementações também precisam mudar com o tempo, à medida que aprendemos sobre os sistemas, os usuários e como os utilizam. O que estamos implementando são ideias de como fazer "algo", e elas podem e devem mudar com o passar do tempo. E aqui chegamos ao segundo tipo de primitiva.

Primitivas semânticas

Todo sistema de software é uma solução para um determinado problema. Mas se começarmos com suposições sobre a solução, ao invés de declarações claras dos problemas, talvez nunca possamos descobrir qual o melhor uso de tempo e recursos para fornecer valor aos clientes.

Mesmo se tivéssemos uma bola de cristal e soubéssemos exatamente como resolver os problemas dos usuários, ainda não seria o suficiente. Também precisamos saber como chegar lá. Os acréscimos de valor a serem entregues ao longo do caminho. Precisamos encontrar o caminho para o produto final, e cada passo dessa caminhada deve estar alinhada com algo que o cliente deseja.

Como faremos isso? Novamente, tentamos trabalhar a partir de elementos indivisíveis, também chamados de "primitivas semânticas". Queremos que essas matérias-primas sejam discretas e possam ser avaliadas de forma independente. Novamente, "não misture as tintas!"

Eles são implementados de várias maneiras. A palavra "requisitos" é muito odiada atualmente, as "histórias de usuários" são populares, enquanto os "casos de uso" saíram de moda. Depois de uma postagem no blog Medium, "tarefas a serem realizadas" se transformou da noite para o dia em "um framework das necessidades do cliente".

Independentemente de como os concebemos, o objetivo é o mesmo: Servir como blocos de construção para entender o problema que queremos resolver e ajudar-nos a ser criativos à medida que avançamos ao longo de jornada do produto.

Ao começar com um conjunto de primitivas semânticas, podemos aprender com um, cometer erros com outro, tropeçar em uma terceira, pivotar entre as demais e assim por diante. Na teoria, elas permitem que o processo de desenvolvimento se torne mutável e continuamente alinhado para fornecer valor incremental aos clientes.

Mas, novamente, na prática, é um desafio trabalhar com elas, pois não são absolutas como as leis da mecânica. São suposições e estimativas, geralmente baseadas em probabilidades feitas com uma amostra mal feita e de causalidade questionável, elaboradas vagamente com muita linguagem redundante. Elas são abstratas que vieram e vivem dentro das nossas mentes.

Sistemas sintéticos

Vamos voltar à diferença entre o "vermelho" no papel e o "vermelho" da mente. No papel, a cor é estável, é factual e replicável. Mas, em nossa mente, a cor é instável e ambígua. Este é o mundo dos objetos em relação ao mundo das nossas mentes.

No software, não temos o luxo das primitivas com dinâmicas estáveis como as encontradas no mundo físico. Nossos sistemas são sintéticos, feitos de compostos cognitivos sujeitos a alterações sem nenhum tipo de aviso prévio. Trabalhamos apenas dentro do mundo da mente, do abstrato.

A dinâmica do sistema que observamos hoje pode não ser a mesma amanhã. A semântica que escrevemos hoje pode não ser mais válida amanhã. Vivemos em um mundo de constantes incertezas.

Para trabalhar com essa incerteza, precisamos adotar um mindset que combine com essa realidade.

Uma grande parte da jornada em software é aprender a suspender os modelos heurísticos e mentais dos quais dependemos ao interagir com o mundo físico. Sentir-se mal pela confiança perdida ou suposições não testadas faz parte da evolução do júnior para o sênior.

Portanto, aprendemos a pensar de forma diferente, aprendemos a desafiar tudo o que vemos. Mas isso é o suficiente?

É pior do que pensávamos!

No livro Thinking Fast and Slow, Daniel Kahneman fala detalhadamente sobre a facilidade com que nos enganamos acreditando em resultados improváveis e como somos particularmente suscetíveis a ilusões de cognição.

Veja o exemplo da cor do vestido que gerou grande polêmica na internet. Depois de aprender sobre essa ilusão visual, ajustamos facilmente a compreensão. Uma vez que conhecemos a verdade, dizemos corretamente que a cor é preta e azul, embora nossos olhos ainda possam nos enganar. Fazemos isso duvidando conscientemente do que está presente diante de nós.

Mas quando se trata de ilusões de cognição, é uma história diferente. As evidências que invalidam o pensamento já convencido não são facilmente aceitas. Olhe para o efeito Dunning-Kruger, ou mesmo movimentos anti vacinas ou terra planistas pegando alguns exemplos extremos. Isso não é um bom presságio para nós.

Assim como os artistas profissionais que ficaram surpresos com os estudos de cores de Albers, mesmo os veteranos da engenharia de software farão suposições surpreendentemente incorretas sobre os sistemas, se as coisas vão funcionar, se vão continuar a funcionar, se criam valor, se atendem às necessidades do cliente e assim por diante.

E não é se admirar, afinal, viver em um mundo de dúvidas conscientes e constantes é difícil e exige muita energia. Precisamos ser implacáveis para resistir ao impulso de recorrer às heurísticas que aprendemos com o mundo dos objetos.

A dúvida consciente cria tensão cognitiva, e fazer isso constantemente é um fardo pesadíssimo. Este é provavelmente um dos motivos pelos quais o desenvolvimento de software tem uma alta taxa de "bornout". Então, o que fazemos?

Sistemas de gestão sintética

Vamos revisar o problema:

  • Os materiais (código, interfaces, requisitos, entre outros) são derivados de primitivas instáveis;
  • Para usar os materiais, precisamos adotar uma mentalidade de questionar tudo;
  • Não podemos confiar em nós mesmos para usarmos essa mentalidade de forma consistente.

A solução? Sistemas.

Primeiro, temos o incrível poder de programação. Podemos investir pesadamente nos dons dados a nós por meio de código. Podemos construir sistemas elaborados de automação de teste, integração contínua e monitoramento de produção para testar implacavelmente cada uma das suposições que fazemos sobre como as coisas deveriam funcionar.

Em segundo lugar, temos práticas de pensamento ágil, lean e design-thinking para nos orientar no gerenciamento da semântica. Desenvolvemos métodos orientados por pesquisas e estatísticas para gerar melhores primitivas. Podemos trabalhar iterativamente dentro de limites que limitam o escopo de erros inevitáveis. Podemos usar essas práticas para encontrar estados metaestáveis que nos permitem seguir em frente.

Ainda estamos amadurecendo esses sistemas de gestão sintética, desenvolvendo as competências necessárias para gerir e controlar a natureza sintética do trabalho. Vale a pena lembrar que se passaram apenas 20 anos desde a descoberta do Agile e menos ainda desde que a palavra DevOps foi cunhada. Nosso campo é novo e ainda não dominamos essas formas de trabalhar, embora, é claro, embarcamos facilmente em ilusões cognitivas que nos convencem do contrário.

Todos os tipos de trabalho envolvem a superação de ilusões. Mas o software tem o fardo adicional de resistir à ilusão de um mundo estável de primitivas dinâmicas e semânticas. Felizmente, podemos criar sistemas para escapar disso, e o desenvolvimento deles definirá o sucesso ao entregar valor em conjunto com o software.

Sobre o Autor

John Rauser é gerente de engenharia de software na Cisco Cloud Security, com sede em Vancouver, Canadá. Sua equipe está construindo a próxima geração de produtos de rede e segurança como serviços hospedados na nuvem. John passou os últimos 10 anos trabalhando em uma variedade de funções diferentes em todo o espectro de TI, de administrador de sistemas a gerente de tecnologia, engenheiro de rede a líder infosec, desenvolvedor a gerente de engenharia. É apaixonado por gerenciamento sintético, novas maneiras de trabalhar e colocar a teoria em prática. Dá palestras regulares em conferências locais e internacionais e escreve para publicações online.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT