This content originally appeared on DEV Community and was authored by Francis Targanski
Introdução
Desde a Grécia Antiga, filósofos têm buscado reduzir a complexidade natural a princípios simples. Demócrito (c. 460–370 a.C.), por exemplo, foi um pioneiro do materialismo filosófico e tentou explicar o cosmos sem recorrer a mitos. Segundo sua visão, toda a matéria é composta por partículas mínimas e indivisíveis chamadas átomos, que se movem e se rearranjam no vazio. Para ele, diferenças entre substâncias (como a diferença entre terra e água) dependiam apenas do formato e da disposição desses átomos. Embora nossa ciência moderna descreva a matéria com mais detalhes, a essência dessa ideia, que sistemas complexos surgem da combinação de partes simples, permanece influente.
Em paralelo, a computação lida com sistemas complexos que precisam ser construídos a partir de componentes mais básicos. Podemos imaginar, então, que cada função pura ou módulo seja um “átomo de software”: blocos indivisíveis cujo arranjo determina o comportamento do programa. Neste artigo busco argumentar que a visão atomista de Demócrito inspira práticas do desenvolvimento moderno.
Além disso, apresento trechos de código para mostrar como aplicar os princípios atômicos na prática de programação. O objetivo é oferecer tanto aos desenvolvedores quanto a qualquer leitor interessado uma ponte entre filosofia clássica e engenharia de software contemporânea. Demonstro assim como conceitos antigos (modularidade, unidades mínimas, previsibilidade) dialogam diretamente com técnicas atuais de programação funcional, levando a sistemas mais robustos e fáceis de compreender.
Desenvolvimento
Demócrito, conhecido como o “filósofo que ri”, e seus predecessores imaginaram um universo mecanicista: tudo seria explicado por arranjos de átomos básicos, sem propósitos ocultos ou intervenções sobrenaturais. Para contexto, vale lembrar que a obra de Demócrito foi uma das primeiras tentativas de explicar o cosmos de forma natural: ele rejeitou explicações mitológicas, insistindo numa abordagem racional. Leucipo, seu mentor, já propusera que pequenas partículas indivisíveis formam a matéria; Demócrito aprofundou essa ideia, popularizando o termo átomo (do grego atomos, “indivisível”), para ele, “tudo que existe no universo é formado de átomos”. Em sua visão, cada substância diferia apenas pelos ajustes finos no formato e no modo como esses átomos se encaixavam.
Leffa et al. (2008) ilustram essa noção observando que, quando começamos a juntar esses blocos atômicos, o universo se assemelha a um jogo de Lego. Lopes (2014), citado por Leffa, descreve o cosmos como “um gigantesco jogo de Lego, formado por blocos pequeninos…”. Cada átomo teria “ganchos” para ligar-se a outros, metáfora que toca diretamente o design de software modular: podemos pensar funções e componentes como peças de Lego que se encaixam num sistema maior. No desenvolvimento de software, essa ideia inspira a modularidade extrema: cada função ou módulo deve cumprir uma única tarefa e se conectar a outros por interfaces bem definidas. Essa unidade mínima só ganha sentido dentro de um todo, mas, combinada com outras, forma funcionalidades ricas e variadas.
Curiosamente, Leffa destaca que a era digital ampliou essa perspectiva. Com o advento da informática e a transição de átomos físicos para bits, “as transformações ficaram bem mais fáceis”. No mundo físico, converter grafite em diamante exige pressão extrema, no digital, basta refatorar código ou reorganizar arquivos. Em software, portanto, rearranjar “átomos de código” não encontra os pesados obstáculos físicos do universo material, podemos reorganizar e reutilizar módulos quase sem custo. Em suma, no mundo digital a flexibilidade só aumenta: recombinar componentes torna-se trivial e eficiente, reforçando a modularidade e escalabilidade do sistema. Esses princípios filosóficos antigos, reforçados pela flexibilidade do ambiente digital, criam uma base teórica inspiradora para o desenvolvimento de software moderno.
Programação Funcional: Funções Puras e Imutabilidade
Na programação funcional, assimilamos claramente o espírito atomista. Seu núcleo são as funções puras, trechos de código que, dados os mesmos argumentos, sempre produzem o mesmo resultado, sem causar efeitos colaterais no sistema. Em outras palavras, são análogas a funções matemáticas: o valor de saída depende apenas dos parâmetros de entrada. Essa pureza torna o comportamento do programa determinístico: por exemplo, addOne(5) sempre retorna 6, sem “surpresas”.
Considere em JavaScript:
const addOne = x => x + 1;
const square = x => x * x;
Neste exemplo, addOne e square são funções puras: cada chamada addOne(5) retorna sempre 6, e square(5) retorna sempre 25, independentemente de qualquer estado externo. Essas funções não alteram variáveis globais nem dependem delas. Como consequência, temos determinismo e transparência referencial: podemos substituir addOne(5) por 6 diretamente em qualquer parte do programa sem mudar seu comportamento.
A pureza de funções acarreta diversos benefícios práticos, como:
- Determinismo: cada função pura retorna sempre o mesmo resultado para os mesmos parâmetros.
- Testabilidade: podemos testar cada função isoladamente, sem configurar estados ou dependências escondidas.
- Modularidade e Reutilização: funções atômicas podem ser combinadas de várias formas, promovendo código mais reutilizável e organizado.
- Concorrência facilitada: sem estados mutáveis compartilhados, é seguro executar funções em paralelo.
Além disso, a imutabilidade de dados é outro pilar funcional. Em vez de modificar estruturas existentes, criamos versões quando necessário. Em termos práticos, imutabilidade significa que, uma vez atribuído um valor, ele não pode ser alterado no local. Por exemplo, usando JavaScript moderno podemos manter objetos e arrays imutáveis:
const arr = [1, 2, 3];
const newArr = [...arr, 4]; // não alteramos `arr`, apenas criamos `newArr`
console.log(arr, newArr); // [1,2,3] [1,2,3,4]
Aqui, arr permanece [1,2,3] e um novo array_ newArr ([1,2,3,4])_ é retornado. Essa prática segue a analogia atômica: assim como átomos não mudam sua essência, dados imutáveis não “ganham vida própria”. A imutabilidade evita efeitos colaterais ocultos (um dado nunca é modificado inadvertidamente) e facilita a depuração. Em código funcional, se precisamos “mudar” algo, retornamos um novo valor em vez de alterar o antigo. Isso se traduz em maiores previsibilidade e segurança no software: reduzir estados mutáveis diminui bugs triviais de lógica. Como aponta o guia funcional da Microsoft, “imutabilidade significa que um valor não pode ser alterado no local”, o que leva programadores a produzir novos valores ao invés de modificar existentes, promovendo programas mais claros e consistentes.
Esses princípios de pureza e imutabilidade refletem a visão determinista de Demócrito: tudo o que acontece no programa resulta de combinações pré-definidas de componentes atômicos. Em linguagens puramente funcionais (Haskell, Elm, etc.), todos os valores são imutáveis por padrão e não há efeitos colaterais, exatamente como a filosofia atomista sugere. Mesmo em JavaScript ou TypeScript, adotamos gradualmente esses padrões, por exemplo, usando const e funções de alta ordem. O resultado é que o software desenvolvido assim costuma ser mais previsível, modular e fácil de manter.
Um exemplo prático do uso desses princípios está em frameworks modernos. No Redux (comum em aplicações React) por exemplo, o estado global da aplicação é imutável e somente alterado por reducers: funções puras que, dados o estado atual e uma ação, retornam um novo estado. Nesse modelo, nenhuma variável global é modificada de forma oculta, cada action produz previsivelmente um único resultado. Esse padrão reflete a filosofia atômica: nada “mágico” acontece por trás das cortinas, e o fluxo de dados permanece transparente e controlável.
Em suma, a programação funcional materializa o atomismo de Demócrito. Cada função pura atua como um átomo de software, previsível por definição, e a ausência de efeitos colaterais garante que as únicas mudanças no sistema ocorram pela combinação explícita desses átomos. Como consequência, criamos software mais robusto e confiável, reforçando a máxima de Demócrito de que a complexidade decorre da simples multiplicação de elementos básicos.
Composição de Funções e Modularidade
No cerne do atomismo de software está a composição: montar entidades maiores a partir de peças menores, assim como formar moléculas a partir de átomos. Eric Elliott (2024) resume bem: “todo desenvolvimento de software é composição”, isto é, sistemas complexos são construídos decompondo problemas em partes menores e depois remontando essas soluções. Em programação funcional, isso se traduz em encadear funções de maneira clara e declarativa, formando pipelines de processamento.
Por exemplo, imagine transformar uma lista de palavras: capitalizar a primeira letra e, em seguida, adicionar uma exclamação. Podemos definir:
const words = ["democritus", "leibniz", "haskell"];
const capitalize = w => w.charAt(0).toUpperCase() + w.slice(1);
const addExclamation = w => w + "!";
const excited = words.map(capitalize).map(addExclamation);
console.log(excited); // ["Democritus!", "Leibniz!", "Haskell!"]
Aqui, aplicamos capitalize em cada palavra e depois addExclamation, usando o encadeamento de map do JavaScript. Cada função trata exatamente uma operação de texto, como se fosse um átomo de processamento, e combinamos etapas puras em sequência. Não há loops complicados nem estados intermediários: criamos um fluxo composto onde cada etapa é isolada. O resultado é código legível e modular, em que podemos inserir ou alterar etapas sem grandes refatorações.
Outro recurso comum é definir funções de composição manualmente. Por exemplo:
const compose = (f, g) => x => f(g(x));
const addOne = x => x + 1;
const double = x => x * 2;
const incThenDouble = compose(double, addOne);
console.log(incThenDouble(3)); // 8
Essa pequena função compose mostra que podemos combinar qualquer par de funções puras arbitrariamente. No exemplo, compondo addOne com double, obtemos outra função incThenDouble que sempre soma 1 e depois dobra o número. Essa composição explícita reforça a ideia atômica: qualquer pipeline de operações pode ser visto como sucessivas funções puras.
Vale notar também como as funções de alta ordem (map, reduce, etc.) facilitam ainda mais essa composição. Por exemplo, para calcular a média de um vetor de números, poderíamos escrever:
const nums = [10, 20, 30, 40];
const sum = nums.reduce((a, b) => a + b, 0);
const avg = sum / nums.length;
console.log(avg); // 25
Embora simples, esse código usa reduce, uma função de ordem superior, para agregar valores sem loops explícitos. Cada passo é puro, e o resultado (média) é obtido pela composição dessas operações.
A analogia filosófica se completa: funções compostas resultam em comportamento coeso, assim como moléculas estruturadas a partir dos mesmos átomos produzem substâncias previsíveis. Leffa (2008) menciona que, na natureza, grafite e diamante são ambos carbonos puros, mas formados por arranjos atômicos diferentes. Analogamente, nosso software pode gerar comportamentos distintos apenas mudando a composição de suas funções. A diferença é que, ao contrário do mundo físico (onde converter grafite em diamante exige condições extremas), no universo de bits reorganizar funções puras é trivial e rápido.
Em termos de arquitetura, a composição reforça a coesão de cada parte e mantém baixo acoplamento entre elas. Cada função atômica tem uma responsabilidade única e interfaces claras, enquanto a combinação de funções simples dá origem a comportamentos complexos. Esse design modular facilita testes e manutenção: podemos refatorar ou substituir uma peça sem quebrar o sistema todo. Em suma, a analogia atômica se realiza em software: estruturas compostas de unidades puras resultam em programas coerentes, previsíveis e fáceis de evoluir.
Conclusão
A filosofia atomista de Demócrito, formulada há mais de dois milênios, ressoa fortemente no desenvolvimento de software atual. Ver o cosmos como constituído por partículas mínimas antecipou a ideia de construir programas a partir de blocos elementares. Conforme ele postulou, “tudo que existe no universo é formado de átomos”, de modo que cada fenômeno depende exclusivamente do arranjo dessas partículas. Analogamente, em um sistema funcional cada função pura pode ser vista como um átomo de software imutável: seu comportamento é determinado apenas pelos argumentos, e o sistema inteiro se define pela maneira como essas funções são combinadas.
Pensar o software em termos atômicos, compondo pequenas unidades puras sem estado compartilhado, oferece grande poder explicativo e prático. Nesse modelo, podemos reorganizar e reaproveitar componentes livremente, sabendo que não haverá efeitos colaterais ocultos. O resultado é um código mais modular, transparente e previsível. Em outras palavras, o legado filosófico de Demócrito fornece uma metáfora inspiradora para a engenharia de software: tratar funções e módulos como unidades atômicas puras resulta em código mais confiável e de fácil manutenção.
Mais ainda, aplicar essas ideias clássicas não é apenas um exercício teórico: é adotar valores fundamentais de engenharia, como simplicidade e clareza. Se Demócrito nos ensinou que a diversidade do universo surge da combinação certa de átomos básicos, nós desenvolvedores podemos seguir a mesma lição: ao compor aplicações a partir de funções atômicas puras, obtemos sistemas mais fáceis de entender e evoluir. Em suma, o átomo do filósofo antigo cede lugar à função do engenheiro, mas a mensagem permanece viva e relevante: construa a partir de partes mínimas e a complexidade se tornará previsível, mesmo no código mais moderno.
Referências
- Aristóteles. Metafísica. Tradução de Manuel Alexandre Júnior. Lisboa: Fundação Calouste Gulbenkian, 2001.
- Crockford, D. JavaScript: The Good Parts. O’Reilly Media, 2008.
- Chiusano, P., & Bjarnason, R. Functional Programming in Scala. Manning Publications, 2014.
- Google Developers. Guide to Functional Programming in JavaScript. Google Developer Blog (2022).
- Plutarco. Do Destino (fragmentos sobre Demócrito). In: Obras Morais e Filosóficas.
- Turing, A. M. Computing Machinery and Intelligence. Mind, Vol. 59, No. 236 (1950), pp. 433–460.
- Vallejo, C. Demócrito: Fragmentos. Tradução e comentários. São Paulo: Loyola, 2010.
- Wilson, R. Pure Functions and Composition in TypeScript. Medium (2023).
- You Don’t Know JS. Functional Programming Basics. GitHub repository (2024).
This content originally appeared on DEV Community and was authored by Francis Targanski

Francis Targanski | Sciencx (2025-07-27T22:14:41+00:00) Demócrito e o Software como Átomo: Modularidade, Composição e Funções Puras. Retrieved from https://www.scien.cx/2025/07/27/democrito-e-o-software-como-atomo-modularidade-composicao-e-funcoes-puras/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.