Nomeando, mas não da maneira que você pensa.

Phil Karlton disse uma vez,“existem apenas duas coisas difíceis em Ciência da Computação: invalidação de cache e nomeação de coisas.”
Um é um problema real; o outro é um problema de definição da realidade.
Um algoritmo de cache com comportamento inadequado compromete a integridade do sistema. Nomes inadequados podem comprometer toda a existência do sistema.
Superficialmente, isso pode parecer um grande salto. Ainda assim, faz sentido quando você analisa como aprendemos e construímos uma compreensão compartilhada do mundo.
Nosso conhecimento vem da experiência e interpretação da realidade ao nosso redor. Com software, construímos mundos, virtuais. Não quero dizer mundos virtuais no sentido de metauniversos. Quero dizer mundos virtuais em nossas mentes.
Construímos novos mundos porque a realidade é preenchida com, bem, tudo. Ao representar uma experiência do mundo real em um mundo virtual, esse processo de construção passa por três fases distintas:
- Replique a experiência ou atividade como está.
- Identifique e remova etapas e tarefas estranhas que não contribuem para a experiência
- Adicione recursos úteis que não têm equivalentes no mundo físico.
Tome como exemplo as compras online.
Essa experiência online incorpora muitos aspectos da realidade, como procurar itens e pagar por eles. Outros conceitos, como dirigir até a loja, não agregam valor e não fazem parte da experiência virtual. E há conceitos que só são úteis — e possíveis — no mundo virtual, como armazenar um número de cartão de crédito para compras futuras.
À medida que construímos essas novas realidades, devemos primeiro inventar coisas e depois nomeá-las. Uma percepção pouco clara, não convencional ou insuficiente da realidade resulta em nomes confusos.
Nomes confusos tornam difícil compartilhar o conhecimento por trás desses nomes. Sem pessoas suficientes compartilhando a mesma interpretação da realidade, os sistemas invariavelmente falham.
Este tópico fica filosófico antes de ficar técnico.
Atualização em 20/02/2023: Se você gostou desta postagem, escrevi uma sequência, “Reescrevendo o sistema mais crítico do mundo”.
A semântica da realidade
Antes de entender por que nomear é difícil (e crucial), devemos entender como nossos cérebros “traduzem” o mundo ao nosso redor em conhecimento.
Mais do que sequências de símbolos e sons, os nomes representam conceitos naquilo que os psicólogos chamam de esquema .
Os esquemas podem ser um pouco abstratos para o desenvolvimento de software, por isso prefiro usar uma forma específica de esquema chamada redes semânticas .
A forma mais simples de rede semântica contém entidades e relacionamentos:
- Uma entidade representa um tipo de artefato distinto, seja real ou conceitual. Se estamos falando de árvores, algumas entidades reconhecíveis seriam “tronco”, “galhos”, “folhas”, “frutas”, “flores” e “sementes”.
- Um relacionamento descreve a associação entre duas entidades. Por exemplo, uma folha “se conecta a” um galho e as frutas “crescem” nas árvores.

Enquanto uma rede semântica representa o mundo, existem representações diferentes e igualmente válidas. Algumas representações diferem em profundidade (ver o mundo com mais detalhes) e outras diferem em perspectiva (ver o mundo de diferentes ângulos).
Vamos começar com um exemplo de como ensinar alguém sobre a origem das frutas.
Uma criança que pergunta sobre a origem das frutas pode se contentar com uma simples rede semântica de “árvores”, “galhos”, “flores” e “frutas”.
Mais tarde na vida, talvez como estudante de biologia, esse mesmo aluno estará pronto para entender um modelo mais complexo. Esse modelo terá novas entidades, como “sementes”, “pólen”, “tubos polínicos”, “ovários” e “sacos polínicos”. Essas novas entidades exigirão relacionamentos de rede mais semânticos, conectando entidades pré-existentes e novas. Por exemplo, o pólen “reside em” um “saco de pólen” e um saco de pólen é “parte de” uma flor.
Essas duas redes semânticas diferem em profundidade .
Os apiólogos – especialistas em abelhas – examinando árvores certamente têm muitos desses conceitos em suas redes semânticas. No entanto, as redes semânticas podem incluir entidades menos comuns, como “tampões florestais” e “quebra-ventos”, relacionados ao sustento das abelhas e à viabilidade geral em um ecossistema. Essas redes semânticas ainda contêm informações extras sobre árvores, mas apenas quando essas informações são relacionadas às abelhas.
Essa é uma diferença de perspectiva .

Essas diferenças introduzem dois desafios fundamentais ao lidar com a realidade, que você pode começar a reconhecer no desenvolvimento de software:
- Diferentes níveis de habilidade significam diferentes profundidades de redes semânticas . Algumas pessoas podem ver mais nuances em um cenário de cliente do que outras. Isso não significa que a percepção extra sempre terá um efeito material na solução final, mas está lá.
- Diferentes prioridades influenciam como classificamos a mesma informação sensorial . Os desenvolvedores de software podem reconhecer entidades que sustentam todo o sistema em uma complexa rede física e lógica de servidores, conexões e mecanismos de renderização. Para o usuário, talvez tudo o que ele veja seja “um aplicativo”, uma entidade menor em sua rotina diária.
Estamos mais ou menos familiarizados com as diferenças de profundidade. Não estamos tão adaptados às diferenças de perspectiva.
Um mundo virtual onde tudo é novo
Neste ponto, você pode dizer que a parte difícil não é o ato final de nomear algo.
Por trás de um bom nome está uma percepção clara da realidade e a formação de uma rede semântica. Conceitos e relacionamentos devem surgir da observação antes que possamos nomeá-los.
Em algum momento da história registrada, alguém deve ter olhado para uma vara alta no chão e a chamado de árvore – para ser exato, eles a chamavam de outra coisa .
Mas o que acontece quando a realidade de alguém não obedece às regras de espaço, matéria e tempo?
Esse é o enigma do software, ênfase em “soft” (virtual) em oposição a “hard” (concreto). Os desenvolvedores de software não atribuem simplesmente nomes a entidades em seu mundo. Freqüentemente, eles criam essas entidades.

Como tal, os desenvolvedores de software enfrentam decisões de nomeação com mais frequência do que pessoas em outras profissões.
Para usar alguns exemplos de como outras profissões enfrentam o desafio de nomear uma coisa nova, devemos observar com que frequência elas se deparam com coisas novas.
Os físicos precisam dissecar os fundamentos do universo usando instrumentos que perscrutam as profundezas das partículas subatômicas. Os astrônomos procuram por toda parte usando recursos limitados, na esperança de descobrir um objeto que precisa de um novo nome . Os empreendedores devem criar empresas e novos produtos antes de poderem nomeá-los.
O tema é claro: muito trabalho, longos períodos de descoberta, restrições do mundo real e talvez o topo de seu respectivo campo receba um punhado de oportunidades de nomeação a cada ano (ou década).
Desenvolvedores de software? Eles têm essa oportunidade dezenas, possivelmente centenas de vezes por dia.
As oportunidades vêm de lidar com um meio que pode representar pensamentos e conceitos em um programa. Essas representações devem ser referenciadas de forma rígida e inequívoca por outros programas.
Atualização em 13/02/23 : Marcos Sandrini adicionou o aspecto da língua nativa na seção de comentários, onde as bases de código escritas em inglês são compreendidas de forma diferente dependendo do nível de domínio da língua inglesa. Seu exemplo específico foi a palavra “Marshaller”, que transmite um significado que pode não ser claro para pessoas não tão versadas no idioma, fazendo com que pensem nela como uma representação menos específica, como “controlador”, “dados ”, “tipo” ou “processamento”. De certa forma, é também um problema de diferença em profundidade, embora originado na comunicação e não no domínio do conhecimento.
Transferência de conhecimento, da teoria à prática
Depois que tudo novo for nomeado, é hora de apresentar esses novos mundos ao restante da equipe de desenvolvimento.
Com a maioria dos desenvolvedores de software sem formação formal em educação, eles geralmente contam com uma combinação de suas experiências em aprender e ensinar outras pessoas.
Embora o treinamento formal em ensino possa ser uma possibilidade distante, podemos pelo menos examinar alguns aspectos da teoria da aprendizagem .
Uma análise mais profunda da teoria da aprendizagem merece sua própria postagem. Ainda assim, mesmo uma leitura rápida de um conceito como “transferência de aprendizado” mostra o potencial para explicar e melhorar os métodos tradicionais de compartilhamento de designs de software.
Vale a pena notar que esses métodos tradicionais ainda devem ser a base para qualquer transferência de conhecimento:
- Documentos de design
- Diagramas de componentes
- Dicionários de terminologia
- Diagramas de interação
Faça uma pausa para observar que as sessões de quadro branco são complementares aos documentos de design, não um substituto.
Para ser claro, uma sessão ao vivo é uma ótima ferramenta cognitiva. Os “alunos” podem interagir com o “instrutor” para testar conceitos e aumentar gradualmente suas redes semânticas.
Por outro lado, a entrega de treinamento depende muito da experiência do instrutor. Uma entrega pessoal leva a resultados inconsistentes entre as sessões. A entrega individualizada também escala mal e marginaliza os colegas fora dos limites das redes sociais, geografias e fusos horários.
Metáforas: Cuidado com as redes semânticas “comerciais”.
Pessoas diferentes formam redes semânticas de maneiras diferentes. No desenvolvimento de software, isso é especialmente verdadeiro em situações em que você lida com conceitos abstratos que se encaixam em várias categorias possíveis.
Não é nenhuma surpresa que designers e desenvolvedores de vez em quando preferem usar metáforas para modelar ou descrever seus sistemas . O pensamento é que as metáforas podem agilizar as transferências de conhecimento construindo sobre redes semânticas semelhantes que as pessoas já aprenderam anteriormente.

Um exemplo de metáfora simples é usar um ícone de “lixo” para excluir arquivos de um computador. Um exemplo mais elaborado de metáfora é a cooptação do conceito de “filas” em sistemas de mensagens.
Existem (pelo menos) dois problemas com o uso de metáforas.
Questão da metáfora nº 1: Bem conhecido por quem?
O primeiro problema é que um conceito familiar não é necessariamente universal.
Um exemplo perfeito vem de um episódio de Star Trek chamado “ Darmok ”.
O exemplo é perfeito porque os fãs de Star Trek já entenderam o que eu quis dizer, e nada mais precisa ser dito. Enquanto isso, os não fãs ficam se perguntando por que esse episódio é significativo.
Nesse episódio, uma raça alienígena se comunica por meio de metáforas enraizadas em eventos históricos em seu mundo natal, em uma versão planetária de uma história interna. Como resultado, a comunicação com qualquer outra sociedade foi prejudicada pela falta de um contexto compartilhado, levando a longas e infrutíferas tentativas de contato.
Por outro lado, a história também mostra o incrível poder do contexto compartilhado, onde dicas verbais mínimas podem rapidamente transmitir informações densamente compactadas.
Sokath, seus olhos descobertos!
Questão da metáfora nº 2: Profundidade e perspectiva.
Mais uma vez, enfrentamos nossos vilões da rede semântica.
Se eu disser que algo “funciona como a Internet”, o pessoal técnico pode saber mais ou menos sobre a Internet. Ao mesmo tempo, alguns usuários avançados da Internet sem um histórico de infraestrutura em nuvem podem vê-lo como uma série de tubos .
Mesmo dentro de uma comunidade técnica de engenheiros de infraestrutura em nuvem, algumas pessoas podem nunca ter ouvido falar do BGP (Border Gateway Protocol) até a grande interrupção do Facebook em 2021 . E pessoas como eu, que tinham acabado de aprender sobre o BGP lendo artigos na época, podem ter adicionado o BGP às suas redes semânticas como uma versão solta [daquele protocolo que conecta grandes empresas à Internet pública].
Também há evidências da teoria da aprendizagem de que a transferência de conhecimento através de diferentes experiências não é uma habilidade universal:
A transferência de aprendizagem é a ideia de que o que se aprende na escola, de alguma forma, é transferido para situações diferentes daquela época e ambiente específicos… Ele descobriu que, embora a transferência seja extremamente importante para a aprendizagem, é um fenômeno que raramente ocorre.
Na verdade, ele realizou um experimento em que fazia com que os sujeitos estimassem o tamanho de uma forma específica e depois trocavam a forma. Ele descobriu que as informações prévias não ajudavam os sujeitos; em vez disso, impediu seu aprendizado.[17]
Abstrações. São abstrações (quase) até o fim.
Pense nas abstrações como um agrupamento de redes semânticas inteiras em menos entidades em uma nova rede semântica.
Uma abstração permite a comunicação de alto nível, seja entre humanos ou entre humanos e máquinas.
Como exemplo de abstração do mundo real, pense em compras online, onde a experiência de compra é representada por imagens e botões na tela do computador.

Embora as abstrações não sejam exclusivas do software, a indústria de software é única na rapidez com que empilha abstrações sobre abstrações. Esse empilhamento cria camadas inescrutáveis de redes semânticas que exigem curvas de aprendizado acentuadas.
Para ilustrar o quão “altas” essas pilhas de abstração de software podem chegar, vamos tentar explicar um cluster Kubernetes para um leigo:
Um cluster do Kubernetes agrupa vários nós do Kubernetes em uma unidade de computação lógica com a capacidade de computação agregada desses nós. Um nó do Kubernetes é uma abstração da capacidade de computação, que pode ser uma máquina virtual em execução em um hipervisor , um servidor bare-metal real ou até mesmo um pequeno rack de Raspberry Pis em uma mesa.
Você pode executar um programa em um nó do Kubernetes. Mas primeiro você precisa entender a abstração de “ pods ”, que são grupos de “ containers ” implantados juntos.
A explicação poderia continuar até que inevitavelmente subjugue a capacidade de alguém de estender sua rede semântica.
A conclusão aqui é que mais simples não significa simples . Algumas tecnologias são inerentemente complexas porque resolvem problemas complexos.
E como precisamos raciocinar e nos comunicar com eficiência sobre a solução para esses problemas, continuamos colocando abstração sobre abstração até que as explicações pareçam muito com o agora famoso conto das “tartarugas até o chão ” .
Os desenvolvedores de software, ou pelo menos os arquitetos de software, fariam bem em passar os olhos pelos conceitos de Carga Cognitiva — O tópico da carga cognitiva aplicada ao design de software é o assunto de uma postagem futura.
De onipresente a único
As redes semânticas crescem em número e tamanho à medida que aprendemos. Eles também crescem como árvores, com novos conceitos ligados aos já existentes. Podemos reorganizar porções de árvores semânticas em nossos cérebros, mas “reescrever” completamente não é fácil ou comum.
As redes semânticas para dois indivíduos podem convergir mais próximas em seus núcleos, especialmente quando esses indivíduos compartilham muitos contextos.
À medida que os níveis de abstração aumentam, esse contexto compartilhado diminui e essas redes semânticas tornam-se cada vez mais diferentes nas bordas. Quando essas redes se tornam suficientemente diferentes, esses indivíduos não compartilham mais pontos de vista semelhantes.
Como um exercício de aquecimento no desenvolvimento de software, vamos examinar o escopo restrito de nomear variáveis dentro de uma função. As redes semânticas dentro de uma função são muito limitadas em propósito, com os programadores tentando ajustar os nomes a um loop de controle localizado ou parte de um algoritmo.
Os controles de loop exigem variáveis de índice de nomenclatura ou elementos enumerados. Essas decisões de nomeação são em grande parte derivadas e inconseqüentes. Por exemplo, quando se trata de variáveis de índice, a decisão padrão geralmente segue o padrão histórico de nomes de um único caractere como “ i ”, “ j ” e “ k ”.

Ultrapasse os controles de loop e estaremos lidando com a nomeação de entidades com um propósito semântico superior. Nesse ponto, provavelmente estamos tentando fazer com que os nomes se encaixem no propósito da função que contém as variáveis.
À medida que os exercícios de nomenclatura sobem na hierarquia de conceitos, começamos a alinhar os nomes com os conceitos do sistema. Por exemplo, se um sistema tiver um componente representando um carrinho de compras, provavelmente teremos um arquivo ou uma classe de sistema nomeada de forma semelhante a carrinhos de compras.
O importante aqui é que pessoas diferentes criam redes semânticas diferentes para uma mesma realidade. Quando essa realidade é muito estreita, como “loop through this array”, as redes semânticas são igualmente limitadas e tendem a se alinhar perfeitamente.
À medida que os escopos se ampliam gradualmente (fluxos de controle, modelagem de um algoritmo como programas ou definição de um sistema), o alinhamento se desgasta em relação direta a esse escopo.
Quando consideramos o alinhamento com os modelos mentais de como um cliente vê o sistema, a palavra alinhamento nem chega a cobrir a lacuna. O que constitui o centro do nosso mundo e especialização pode ser simplesmente “aplicação número 3 do fornecedor número 6” para um cliente.
Voltando ao nosso exemplo de carrinho de compras, dois programadores diferentes tomariam as mesmas decisões sobre a representação das funções do carrinho de compras como arquivos de código-fonte? Provavelmente não.
Mais importante, eles concordariam com a decisão de outra pessoa e ajustariam seus modelos mentais? Possivelmente.
Acordo significa “alinhar” redes semânticas entre diferentes pessoas da equipe, e existem algumas boas técnicas para isso. Alguns métodos formais foram mencionados anteriormente (documentação de projeto, dicionário de termos, diagramas de componentes, diagramas de sequência).
Eu acrescentaria educação cruzada frequente e até programação em pares como atividades que podem complementar a documentação formal.
Atualização em 03/01/23 : Discutir métodos para aumentar o “acordo semântico” em uma equipe de desenvolvimento — como Análise de Negócios , Domain Driven Design ou RUP — é outro tópico para uma postagem futura. Eu intencionalmente deixei esses processos fora desta discussão. Esses processos exigem a criação de modelos de negócios e de domínio da realidade, trazendo-nos de volta aos mesmos desafios já abordados nesta postagem.
O tópico das diferentes redes semânticas nos leva à próxima seção.
Reescrevendo a realidade através do código
Refazer o trabalho de alguém é uma prática comum na indústria de software.
O retrabalho é, à primeira vista, uma atividade de desperdício. Superficialmente, e talvez da perspectiva de um gerente de projeto, se um bloco de código está fazendo seu trabalho, os desenvolvedores devem deixá-lo de lado. Se um bloco de código precisar de modificações mínimas para adicionar um novo recurso, deve fazer mais sentido aumentar esse componente com os deltas e deixar o restante intocado. Certo?
A desconexão aqui é que os gerentes de projeto estão pensando em construir coisas. Instintivamente ou por treinamento, os gerentes de projeto esperam que, quando você constrói algo no mundo real, isso seja feito.
No entanto, mais uma vez, os desenvolvedores de software não estão construindo coisas no mundo real; eles estão interpretando a realidade para criar um mundo virtual .
Deixando de lado as razões legítimas para a refatoração de código , um desenvolvedor de software que “herda” bases de código de outro desenvolvedor ainda pode sentir o desejo de reescrever partes significativas dessa base de código.
Por que é que?
Em uma palavra: construtivismo .
Em poucas palavras, o código pré-existente em um sistema não é um artefato estático. É uma interpretação da realidade. Em um mundo virtual, torne isso uma realidade em mudança . Nessas condições, é quase impossível alcançar um entendimento compartilhado e estável da realidade em toda a equipe.
Reescrever código não é um exercício inútil de reconstruir o que já está em um repositório de código. É um exercício de criar um equilíbrio entre o que o desenvolvedor sabe e a representação escrita desse conhecimento. Esse alinhamento permite que o desenvolvedor trabalhe com a base de código de forma mais produtiva. A base de código reescrita é um subproduto de uma atividade de aprendizado .

Observe que abordo explicitamente um cenário em que a base de código é transferida de um desenvolvedor para outro. A propriedade do código , seja seguindo um modelo individual ou compartilhado, é um tópico para uma postagem futura.
Eu não poderia terminar esta seção sem um exercício de nomenclatura. Depois de concluir uma atividade de reescrita de código e formar novas redes semânticas para representar sua interpretação do mundo, as chances desse desenvolvedor escolher os nomes antigos para os novos conceitos são relativamente baixas.
O ego pode desempenhar um papel – nomear as coisas é como deixar uma pequena marca no mundo – mas há pelo menos uma razão muito pragmática para isso: um novo conceito com o nome antigo está fadado a confundir as pessoas familiarizadas com o antigo conceito. esta excelente sessão sobre o tópico de divulgação de ativação para referência.
Novas realidades geram novos nomes.
Conclusão
Nomear (algo) no desenvolvimento de software é a culminação de um processo complexo de criação de mundos abstratos.
Algumas partes desses mundos são representações diretas do mundo físico, enquanto outras partes são inteiramente novas.
O processo de nomeação inclui tarefas restritas (escrever um loop de controle curto) e exercícios cognitivos amplos (criar novas abstrações).
A falta de referências históricas — o desenvolvimento de software é uma disciplina relativamente nova — exige o emprego frequente de metáforas imperfeitas para explicar novos paradigmas.
O progresso tecnológico sem precedentes exige camadas de abstração cada vez maiores para estratificar a capacidade incompreensível dos sistemas modernos em camadas.
Muitos desses desafios são intrínsecos à tenra idade de nossa profissão, mas existem vários conceitos que podemos tomar emprestados de outras áreas para nos ajudar a explicar, reconciliar e resolver esses problemas.
Se você gostou de ler isso, também pode gostar de ler essas outras histórias sobre desenvolvimento de software.
Reescrevendo o sistema mais crítico do mundo
Mas primeiro, precisamos voltar à fonte.
dnastacio.medium.com
Como superar um desenvolvedor 10x
Primeira consciência. Então produtividade.
betterprogramming.pub
Referências
- Metáforas que calculamos por — https://websites.umich.edu/~jlawler/meta4compute.html
- O que são abstrações em engenharia de software com exemplos — https://thevaluable.dev/abstraction-type-software-example/
- Redes semânticas e ativação de difusão — https://www.khanacademy.org/test-prep/mcat/processing-the-environment/cognition/v/semantic-networks-and-spreading-activation
- Navegando pelo mundo cotidiano — uma perspectiva cognitiva por @DonnaRobertsPhD — https://link.medium.com/T9SHda0mWvb
- Você pode lidar com a complexidade. E daí? — https://medium.com/@hayavuk/you-can-handle-complexity-so-what-41f0aca4d097
- Propriedade do código — https://medium.com/blacklane-engineering/code-ownership-177566d93378
Programação
Desenvolvimento de software
Aprendizado de máquina
Aprendizado
Filosofia