Software · Design Patterns

Álgebra Booleana para Programadores: De Morgan, Tabelas-Verdade e Condicionais Limpas

A matemática da lógica proposicional aplicada à legibilidade de código: as leis de De Morgan, avaliação por curto-circuito e eliminação de pirâmides condicionais.

Diagrama conceitual ilustrando álgebra booleana para programadores: de morgan, tabelas-verdade e condicionais limpas
Neste artigo

A álgebra booleana, formalizada pelo matemático britânico George Boole em 1854, é a base matemática que torna possível tanto o funcionamento das portas lógicas em circuitos de silício quanto a estruturação de fluxos condicionais em linguagens de programação. No entanto, blocos complexos de if/else repletos de negações aninhadas continuam sendo a maior fonte de falhas sutis em regras de negócio de software corporativo.

flowchart TD
  subgraph DeMorgan["Equivalência das Leis de De Morgan"]
    NegAnd["Não (A E B)"]
    Eq1["<==>"]
    OrNeg["(Não A) OU (Não B)"]

    NegOr["Não (A OU B)"]
    Eq2["<==>"]
    AndNeg["(Não A) E (Não B)"]
  end

  NegAnd --- Eq1 --- OrNeg
  NegOr --- Eq2 --- AndNeg

As Leis de Augustus De Morgan

Ao refatorar expressões lógicas confusas contendo negações sobre múltiplos termos agrupados, as leis de De Morgan oferecem regras estritas de transformação:

  1. A negação de uma conjunção equivale à disjunção das negações: $$\neg (A \land B) \iff (\neg A) \lor (\neg B)$$
  2. A negação de uma disjunção equivale à conjunção das negações: $$\neg (A \lor B) \iff (\neg A) \land (\neg B)$$

Na prática da escrita de código limpo, essa lei permite distribuir o operador de negação (!) eliminando parênteses difíceis de interpretar mentalmente:

// Condicional convoluta e propensa a erros de interpretação
if (!(cliente.possuiSaldo && cliente.contaAtiva)) {
  bloquearTransacao();
}

// Versão refatorada aplicando a primeira lei de De Morgan:
if (!cliente.possuiSaldo || !cliente.contaAtiva) {
  bloquearTransacao();
}

Curto-Circuito (Short-Circuit Evaluation)

Compiladores e interpretadores modernos implementam a avaliação lógica por curto-circuito:

  • Na expressão A && B, se A for falso, o runtime nem sequer avalia B, pois o resultado final da operação será obrigatoriamente falso.
  • Na expressão A || B, se A for verdadeiro, a expressão B é ignorada, pois a verdade de um único termo é suficiente para satisfazer a disjunção.

Esse comportamento permite construir guard clauses seguras contra valores nulos:

// Seguro: se usuario for null, a segunda condição não é executada, evitando NullReferenceException
if (usuario !== null && usuario.temPermissaoAdmin()) {
  autorizarAcesso();
}

Tabelas-Verdade para Decisões Complexas

Quando um processo de negócios envolve três ou quatro variáveis independentes (ex: cliente VIP, primeira compra, saldo disponível, cupom válido), tentar acertar o código diretamente no editor quase sempre deixa brechas de segurança.

Cliente VIP (A) Primeira Compra (B) Cupom Válido (C) Desconto Concedido?
V V V Sim
V F F Sim (VIP tem desconto garantido)
F V V Sim
F F V Sim
F F F Não

Estruturar a tabela-verdade antes de programar permite extrair as combinações mínimas necessárias, substituindo pirâmides de if aninhados por guard clauses lineares e variáveis explicativas bem nomeadas.

Explorar este tema no Grafo de Conhecimento