DEV Community

Alberto Luiz Souza
Alberto Luiz Souza

Posted on

A Lei da Proximidade Operacional

Disclaimer

Antes de chegar aqui, eu investi muito tempo testando ideias, observando código alheio e também falando com outras pessoas do mercado.

Para concluir, eu falei com três pessoas doutoras diferentes, sendo uma delas doutora em matemática. Uma vez que todas me deram feedback positivo, sinto que o tema aqui pode ser útil. As pessoas foram:

Introdução

Já faz um tempo que percebo a mesma coisa em várias atividades que realizo onde preciso me basear em informações que existem num determinado contexto: Quanto mais distante da origem da informação eu estou, mais complexo fica o processo para que eu realize determinada atividade.

Definições Importantes

É muito importante que antes de prosseguirmos, deixemos especificada a definição de complexidade para este post. Retirada do dicionário de Oxford, temos:

diz-se de ou conjunto, tomado como um todo mais ou menos coerente, **cujos componentes funcionam entre si em numerosas relações de interdependência ou de subordinação.

Outra coisa muito importante antes de prosseguirmos: Não é porque você acha algo fácil de entender, que torna este algo mais simples. Complexidade contabilizada é diferente de Complexidade Percebida. Alguém pode achar algo fácil de entender simplesmente porque já teve que lidar com aquilo inúmeras vezes, estudou, etc…

Exemplos no Contexto de Desenvolvimento de Software

Dado que temos um acordo sobre complexidade, vou deixar alguns exemplos aqui sobre o aumento de complexidade/dificuldade quando pensamos em código.

  • Buscar informações dentro da memória do meu programa é mais simples do que buscar a mesma informação em outro processo. Por exemplo, é mais simples do que buscar no banco de dados, num provedor de cache externo etc.
    • Preciso atravessar a rede
    • Lidar com protocolos específicos
    • Eventuais falhas de acesso
  • Fazer um código específico que atua diretamente sobre determinado conjunto de dados é mais simples do que fazer um código genérico que vai precisar atuar sobre este mesmo conjunto de dados em diferentes implementações.
    • A versão direta me permite mandar uns ifs e já foi
    • A versão mais genérica vai necessitar de dynamic dispatch(polimorfismo, passagem de função como argumento etc) e também no mínimo um ponto de tomada de decisão sobre o que chamar em função da entrada do dado. O aceite da chamada pode estar espalhado pelas implementações. Existe também a chance de usar metaprogramação para decidir o caminho baseado em alguma definição
  • Escrever a lógica de negócio para um fluxo direto na camada de entrada de dados é mais simples do que criar uma camada extra e reaproveitá-la entre camadas de entradas de dados diferentes. Por exemplo: Via HTTP ou via protocolo de Mensageria.
    • Escrever a lógica direto no meu controller/listener/etc exige menos elementos do que delegar isso para outras partes do programa. Inclusive com implicações relacionadas a transformar o retorno destas lógicas de negócio para o formato adequado, dado o protocolo.
  • Escrever o teste para uma funcionalidade logo depois de implementar a funcionalidade é mais simples do que deixar para depois.
    • É mais simples porque por mais que os elementos necessários para a escrita dos testes sejam os mesmos(código de produção, descrição da tarefa, etc), você vai precisar de uma tática mais elaborada para lembrar disso tudo depois.

Exemplos em Outros Contextos

Agora, podemos ir além ir explorar a possível lei em outros cenários:

  • Quanto mais longe do momento do acontecido, mais complexo é dar um feedback efetivo sobre o tópico.
    • É mais complexo porque você vai ter que puxar pela sua memória o que aconteceu exatamente e, para isso, vai precisar ter criado alguma estrutura extra mínima para de fato conseguir recuperar de maneira apurada tudo que aconteceu.
  • Quanto mais distante estamos da pessoa que deu uma ideia de funcionalidade, mais complexo é entender o que ela realmente quer.
    • Muitas vezes precisamos falar com pessoas intermediárias… Elas trazem a interpretação delas sobre o pedido, deixam coisas de fora etc. Ou seja, temos mais elementos para lidar e realmente extrair o que precisa.
  • Quanto maior a organização, mais distante fica a origem de informações importantes da pessoa receptora, o que deixa a entrega mais complexa.
    • Precisa ter um jeito de fazer a informação chegar até onde precisa. Isso pode ser feito utilizando múltiplos canais de entrega e por aí vai.
  • Escrever um resumo fica mais complexo se você deixar para escrever sobre cada dia apenas no final da semana.
    • Para fazer isso de maneira efetiva você vai precisar registrar de alguma forma o que aconteceu em cada dia, depois passar por estes registros de novo, buscar lembrar sobre cada nota e aí gerar o resumo final.
    • A mesma ideia se aplica às pesquisas sobre alimentação, quando tentam te perguntar sobre sua alimentação nos últimos três meses.
  • Anotar os gastos da semana apenas no final é mais complexo do que anotar os gastos no exato momento que ele ocorre.
    • Para saber no final da semana você vai precisar consultar seu histórico de pagamentos, lembrar do local etc.
  • Fazer a comunicação acontecer num ambiente de trabalho remoto é mais complexo do que no presencial.
    • No remoto precisamos de uma ferramenta extra para mandar mensagens, ferramenta extra para marcar reuniões mesmo entre pessoas que trabalham no mesmo time etc.

Complexidade Necessária

E só porque ficou mais complexo quer dizer que é pior? Não necessariamente. Muitas vezes somos obrigados a seguir pelo caminho mais complexo.

  • Um sistema que recebe dados de várias entradas não quer ficar copiando sua lógica de negócio em todo lugar.
  • Um sistema que usa uma tecnologia mais frágil quer se proteger de futuras mudanças daquela tecnologia.
  • Uma equipe quer decidir um padrão de implementação que usa uma estrutura mais complexa. Ela acha que ter um padrão é melhor e pronto.
  • Um feedback dado com mais tempo passado entre o feedback e a origem do fato pode ser dado com as emoções já mais equilibradas.
  • Não parece saudável uma empresa de mil pessoas ter apenas uma pessoa como chefe.
  • Deixar os dados em memória deixa o sistema mais frágil do que deixar os dados no banco de dados.
  • Colocar um cache no meio pode deixar mais rápido do que ficar indo no banco de dados genérico o tempo todo.
  • A comunicação em times remotos é mais complexa, mas pode valer a pena por conta da possibilidade de contratação em tudo que é lugar, liberdade para as pessoas se organizarem como querem etc.

A Lei da Proximidade Operacional

Depois de muito pensar, testar e perguntar para doutores que tenho contato, sinto que podemos ter aqui uma possível lei, que neste momento chamo de Lei da Proximidade Operacional: A complexidade de uma ação sobre um fato cresce conforme aumenta a distância (temporal, espacial ou lógica) entre a ação e o fato original.

Ela funciona para mim assim como outras leis que temos:

Como sabemos, elas não são leis no mesmo sentido da lei da gravidade, elas se parecem mais com uma força que está ali sempre presente e que, se você não prestar atenção, vai acabar se dando mal.

Formalização da Lei

Papeando com o Chat GPT, ele sugeriu até uma fórmula para expressar a lei.

A relação entre distância e complexidade pode ser expressa como:

C=K(D^P)

Onde:

  • C é a complexidade da ação sobre o fato.
  • D é a distância entre a ação e o fato.
  • k é um fator de proporcionalidade dependente do contexto (por exemplo, largura de banda em redes, eficiência de cache na computação).
  • P é um expoente que depende do domínio específico.

Exemplo da fórmula aplicada para comunicação

import numpy as np
import pandas as pd
import ace_tools as tools

# Simulação de comunicação remota em uma empresa crescente

# Assumimos que além da distância lógica (hierarquia), a distância espacial (escritórios remotos)   
# adiciona complexidade extra devido a fusos horários, barreiras linguísticas, e latência de comunicação.

# Parâmetros da simulação  

num_employees = np.array([50, 100, 500, 1000, 5000])  # Crescimento da empresa
hierarchical_levels = np.log2(num_employees)  # Simulação de camadas hierárquicas (log base 2)
remote_factor = np.array([1.0, 1.1, 1.3, 1.5, 2.0])  # Fator de dificuldade por comunicação remota

k = 1  # Fator de proporcionalidade (ajustável)
p = 2  # Assumimos que a complexidade cresce quadraticamente com a hierarquia. Você pode brincar como quiser. 



# Ajustamos a fórmula para incluir distância espacial  
complexity_remote = k * ((hierarchical_levels * remote_factor) ** p)

# Criar DataFrame com os resultados  
df_remote_communication_complexity = pd.DataFrame({  
    "Número de Funcionários": num_employees,  
    "Camadas Hierárquicas (D)": hierarchical_levels,  
    "Fator de Comunicação Remota": remote_factor,  
    "Complexidade da Comunicação Remota (C)": complexity_remote  
})

# Exibir os resultados  
tools.display_dataframe_to_user(name="Complexidade da Comunicação Remota", dataframe=df_remote_communication_complexity)
Enter fullscreen mode Exit fullscreen mode

Resultado da simulação

Número de Funcionários Camadas Hierárquicas (D) Complexidade da Comunicação (C)
50 5.64 31.85
100 6.64 44.14
500 8.96 80.39
1000 9.97 99.32
5000 12.29 150.99

Exemplo da fórmula aplicada para utilização de camadas no software

# Simulação de complexidade em código dividido em camadas

# Assumimos que quanto mais camadas existem entre a chamada inicial e a lógica de negócios,
# maior a complexidade da ação sobre o dado.

# Definição do número de camadas de abstração no código
num_layers = np.array([1, 2, 4, 6, 8, 10])  # Número de camadas (ex: controller → service → repository → database)
p = 1.2  # Cada camada adiciona 20% de sobrecarga. Podemos brincar a vontade aqui. 

# Vamos manter o fator de proporcionalidade fixo por enquanto.
k = 1

# Aplicando a fórmula C = k * D^p, onde D agora é o número de camadas
complexity_layers = k * ((num_layers * layer_complexity_factor) ** p)

# Criar DataFrame com os resultados
df_code_layer_complexity = pd.DataFrame({
    "Número de Camadas": num_layers,
    "Complexidade do Código (C)": complexity_layers
})

# Exibir os resultados
tools.display_dataframe_to_user(name="Complexidade do Código por Número de Camadas", dataframe=df_code_layer_complexity)

Enter fullscreen mode Exit fullscreen mode

Resultado da simulação

Número de Camadas Complexidade do Código (C)
1 1.44
2 5.76
4 23.04
6 51.84
8 92.16

Conclusão

Como próximo passo fica o pedido pelo feedback para você que chegou até aqui :). Além disso, vou tentar buscar formas de me juntar com pessoas de pesquisa para criarmos experimentos e verificar mais fortemente a validade da lei.

Para saber mais

Eu concentro a maior parte das minhas publicações no no canal do youtube Dev Eficiente. Fica aqui o convite para você navegar por lá e fazer sua inscrição :).

Top comments (0)