Por que modularizar: coesão, acoplamento e reutilização
Modularizar é organizar um algoritmo em partes menores (módulos) que podem ser entendidas, testadas e alteradas com menos risco. No pseudocódigo essencial, um “módulo” normalmente é uma função/procedimento ou uma seção bem delimitada do algoritmo principal. A modularização boa se apoia em três ideias práticas:
- Coesão: cada módulo faz uma coisa principal e faz bem (responsabilidade clara).
- Acoplamento: módulos dependem o mínimo possível uns dos outros (dependências explícitas e pequenas).
- Reutilização: módulos úteis podem ser reaproveitados em outros algoritmos sem reescrever.
Coesão na prática: como reconhecer um módulo “bem focado”
Um módulo coeso tem um objetivo fácil de explicar em uma frase. Se você precisa usar “e” muitas vezes para descrever o que ele faz, provavelmente está fazendo coisas demais.
- Boa coesão: “Calcular o total do carrinho”, “Validar um CPF”, “Ordenar uma lista”.
- Baixa coesão: “Ler dados e validar e calcular e imprimir relatório”.
Critérios práticos para decidir se algo merece virar módulo:
- Regra do parágrafo: se um trecho do algoritmo principal ficou grande o suficiente para exigir vários parágrafos mentais, extraia.
- Regra da repetição: se o mesmo padrão aparece 2+ vezes, transforme em utilitário.
- Regra da mudança: se um trecho tende a mudar por um motivo diferente do restante (ex.: regra de desconto muda, mas leitura de dados não), separe.
- Regra da testabilidade: se você gostaria de testar aquele trecho isoladamente com entradas variadas, ele é um bom candidato.
Acoplamento na prática: dependências explícitas e sem “mágica”
Acoplamento alto acontece quando um módulo só funciona porque “sabe demais” sobre o resto do algoritmo: usa variáveis globais, depende de ordem específica de execução, altera estruturas compartilhadas sem deixar claro, ou assume formatos implícitos.
Para reduzir acoplamento no pseudocódigo essencial:
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
- Evite variáveis globais: passe dados por parâmetros e receba resultados por retorno (ou parâmetros de saída, quando fizer sentido).
- Evite efeitos colaterais escondidos: um módulo não deve alterar dados que não estejam na sua assinatura.
- Prefira dados imutáveis como entrada: trate entradas como “somente leitura” sempre que possível.
- Defina contratos: documente pré-condições (o que deve ser verdade antes) e pós-condições (o que será verdade depois).
- Não misture camadas: regra de negócio não deve depender de detalhes de apresentação (ex.: formatação de texto) e vice-versa.
Reutilização: como criar módulos que servem em mais de um lugar
Reutilização não é “forçar” generalidade; é identificar utilidades naturais. Um módulo reutilizável costuma ter:
- Assinatura estável: entradas/saídas claras e pequenas.
- Baixo acoplamento: não depende do contexto externo.
- Nome orientado a intenção: descreve o que faz, não como faz.
- Sem I/O interno: módulos reutilizáveis geralmente não fazem leitura/escrita diretamente; recebem dados e devolvem resultados.
Critérios práticos para dividir algoritmos em módulos
1) Responsabilidades claras (uma frase)
Antes de extrair um módulo, escreva a intenção em uma frase. Se a frase ficar vaga (“processar dados”), refine até ficar específica (“calcular subtotal e impostos de uma compra”).
2) Nomes expressivos orientados a verbos
Use nomes que indiquem ação e resultado. Evite nomes genéricos como processa, fazCoisa, rotina1.
| Ruim | Melhor |
|---|---|
calcula() | calcularTotalComImpostos(itens, aliquota) |
valida() | validarEmail(email) |
ajusta() | aplicarDescontoPorCupom(total, cupom) |
3) Entradas e saídas bem definidas (contrato)
Para cada módulo, deixe explícito:
- Entradas: quais dados recebe e em que formato.
- Saídas: o que retorna ou altera (se alterar, que seja explícito).
- Erros/condições: como sinaliza falhas (ex.: retornar um registro com
sucessoemensagem).
Um padrão útil é retornar um registro de resultado:
REGISTRO ResultadoValidacao { sucesso: lógico, mensagem: texto }4) Tamanho e legibilidade: “módulos que cabem na cabeça”
Não existe número mágico de linhas, mas um módulo deve ser lido sem perder o fio. Se você precisa rolar mentalmente demais, divida em submódulos (por exemplo: “normalizar”, “validar”, “calcular”).
Organizando o pseudocódigo em módulos e seções
Uma organização simples e traduzível é separar em: (1) utilitários, (2) regras de negócio, (3) orquestração (fluxo principal). Mesmo quando tudo está no mesmo arquivo/texto, mantenha seções claras.
// ===================== UTILITÁRIOS =====================
FUNÇÃO arredondar2(valor: real) : real
RETORNE ...
FIM FUNÇÃO
FUNÇÃO ehEmailValido(email: texto) : lógico
RETORNE ...
FIM FUNÇÃO
// ===================== REGRAS DE NEGÓCIO =====================
FUNÇÃO calcularTotal(itens: lista de Item, cupom: texto) : real
...
FIM FUNÇÃO
// ===================== ORQUESTRAÇÃO =====================
ALGORITMO principal
...
FIM ALGORITMOEssa estrutura ajuda a localizar rapidamente o que é reaproveitável (utilitários), o que é regra (negócio) e o que é fluxo (orquestração).
Passo a passo: reduzindo acoplamento (removendo dependência de globais)
Cenário: cálculo de pedido com dependências implícitas
Exemplo de pseudocódigo com acoplamento alto: funções dependem de variáveis fora da assinatura.
// Variáveis globais (evitar)
GLOBAL itens
GLOBAL aliquotaImposto
GLOBAL cupom
FUNÇÃO totalComImposto() : real
total <- somarItens() // depende de GLOBAL itens
total <- aplicarCupom(total) // depende de GLOBAL cupom
total <- total + total * aliquotaImposto
RETORNE total
FIM FUNÇÃO
FUNÇÃO somarItens() : real
soma <- 0
PARA cada item EM itens
soma <- soma + item.preco * item.qtd
FIM PARA
RETORNE soma
FIM FUNÇÃO
FUNÇÃO aplicarCupom(total: real) : real
SE cupom = "DESC10" ENTÃO
RETORNE total * 0.90
SENÃO
RETORNE total
FIM SE
FIM FUNÇÃOPasso 1: tornar dependências explícitas por parâmetros
FUNÇÃO somarItens(itens: lista de Item) : real
soma <- 0
PARA cada item EM itens
soma <- soma + item.preco * item.qtd
FIM PARA
RETORNE soma
FIM FUNÇÃO
FUNÇÃO aplicarCupom(total: real, cupom: texto) : real
SE cupom = "DESC10" ENTÃO
RETORNE total * 0.90
SENÃO
RETORNE total
FIM SE
FIM FUNÇÃOPasso 2: compor funções com entradas/saídas claras
FUNÇÃO totalComImposto(itens: lista de Item, cupom: texto, aliquotaImposto: real) : real
subtotal <- somarItens(itens)
comDesconto <- aplicarCupom(subtotal, cupom)
total <- comDesconto + comDesconto * aliquotaImposto
RETORNE total
FIM FUNÇÃOPasso 3: isolar regras variáveis em módulos próprios
Se a regra de cupom crescer (vários cupons, datas, limites), extraia para um módulo dedicado e mantenha o restante estável.
FUNÇÃO calcularDesconto(total: real, cupom: texto) : real
SE cupom = "DESC10" ENTÃO
RETORNE total * 0.10
SENÃO SE cupom = "FRETEGRATIS" ENTÃO
RETORNE 0
SENÃO
RETORNE 0
FIM SE
FIM FUNÇÃO
FUNÇÃO aplicarDesconto(total: real, cupom: texto) : real
desconto <- calcularDesconto(total, cupom)
RETORNE total - desconto
FIM FUNÇÃOObserve que agora a regra de desconto pode ser alterada sem mexer no cálculo de imposto.
Guia de refatoração para modularização (mantendo legibilidade e traduzibilidade)
Refatoração 1: Extrair função (Extract Function)
Quando usar: um trecho tem intenção clara, aparece como “bloco” dentro de outro módulo, ou você quer nomear a intenção.
Passo a passo:
- Selecione um trecho contínuo que produza um resultado identificável.
- Liste quais variáveis ele lê (viram parâmetros) e quais ele produz (viram retorno).
- Crie a função com nome de intenção.
- Substitua o trecho pela chamada.
- Releia o módulo chamador: ele deve ficar mais “narrativo” (orquestração).
Exemplo (antes):
FUNÇÃO gerarResumoPedido(itens: lista de Item) : texto
totalQtd <- 0
totalValor <- 0
PARA cada item EM itens
totalQtd <- totalQtd + item.qtd
totalValor <- totalValor + item.qtd * item.preco
FIM PARA
RETORNE "Itens: " + totalQtd + ", Total: " + totalValor
FIM FUNÇÃODepois (extraindo cálculo):
REGISTRO Totais { qtd: inteiro, valor: real }
FUNÇÃO calcularTotais(itens: lista de Item) : Totais
t.qtd <- 0
t.valor <- 0
PARA cada item EM itens
t.qtd <- t.qtd + item.qtd
t.valor <- t.valor + item.qtd * item.preco
FIM PARA
RETORNE t
FIM FUNÇÃO
FUNÇÃO gerarResumoPedido(itens: lista de Item) : texto
t <- calcularTotais(itens)
RETORNE "Itens: " + t.qtd + ", Total: " + t.valor
FIM FUNÇÃORefatoração 2: Remover duplicação (DRY) com utilitários
Quando usar: duas ou mais partes repetem a mesma lógica com pequenas variações.
Passo a passo:
- Identifique o que é igual (núcleo) e o que varia (parâmetros).
- Crie um utilitário para o núcleo.
- Transforme as variações em parâmetros (ou em funções auxiliares pequenas).
- Substitua as duplicações por chamadas ao utilitário.
Exemplo: normalização repetida de texto.
// Antes (repetido em vários lugares)
nome <- removerEspacos(nome)
nome <- paraMaiusculas(nome)
cidade <- removerEspacos(cidade)
cidade <- paraMaiusculas(cidade)// Depois
FUNÇÃO normalizarTextoBasico(s: texto) : texto
s <- removerEspacos(s)
s <- paraMaiusculas(s)
RETORNE s
FIM FUNÇÃO
nome <- normalizarTextoBasico(nome)
cidade <- normalizarTextoBasico(cidade)Refatoração 3: Introduzir “módulo de domínio” (agrupar regras relacionadas)
Quando usar: várias funções pequenas tratam do mesmo conceito (ex.: “Pedido”, “Usuário”, “Pagamento”), mas estão espalhadas.
Como fazer:
- Crie uma seção no pseudocódigo para aquele domínio.
- Coloque ali funções que operam sobre o mesmo registro/estrutura.
- Mantenha nomes consistentes (prefixos ajudam):
pedidoCalcularTotal,pedidoAplicarDesconto.
// ===== MÓDULO: PEDIDO =====
FUNÇÃO pedidoCalcularSubtotal(itens: lista de Item) : real
...
FIM FUNÇÃO
FUNÇÃO pedidoCalcularTotal(itens: lista de Item, cupom: texto, aliquota: real) : real
...
FIM FUNÇÃORefatoração 4: Separar orquestração de regras
Sintoma: um módulo mistura decisões de negócio com passos de fluxo (montar menu, escolher caminho, chamar várias operações).
Diretriz:
- Orquestração: chama módulos, decide sequência, trata resultados.
- Regra: calcula/valida/transforma dados, sem conhecer o “roteiro”.
Isso melhora a traduzibilidade para qualquer linguagem, porque a regra vira uma função pura ou quase pura.
Checklist rápido de modularização (para revisar seu pseudocódigo)
- Consigo descrever cada módulo em uma frase sem “e… e… e…”?
- As dependências estão todas na assinatura (sem globais escondidas)?
- O módulo faz I/O? Se sim, ele é de orquestração e não um utilitário?
- Há duplicação de lógica que poderia virar utilitário?
- Os nomes indicam intenção e resultado?
- As entradas/saídas estão claras e pequenas?
- Se eu mudar uma regra específica, consigo alterar um único lugar?