Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

Entrada, processamento e saída: o desenho de todo programa

O modelo entrada-processamento-saída aplicado a uma calculadora de troco: o que entra, o que o programa decide e o que sai, com execução no Node.

Rodolfo Mori4 min de leitura

Entrada, processamento e saída são três papéis que todo programa desempenha: recebe dados, aplica uma regra e entrega um resultado observável. Separar esses papéis torna a mudança previsível e revela onde um erro começou.

O domínio desta lição é o caixa de uma livraria. O cliente entrega dinheiro, o sistema calcula a diferença e a tela informa o troco. Antes de pensar em sintaxe, escreva três caixas no papel: entra, transforma, sai. Esse mapa é um algoritmo em sua forma mais curta.

Todo programa é um funil: entra dado, sai resposta

Comece com números já disponíveis no programa. O exemplo mínimo deixa os três papéis visíveis:

js
const totalCompra = 37;
const valorRecebido = 50;
const troco = valorRecebido - totalCompra;
console.log(`Troco: R$ ${troco.toFixed(2)}`);
Troco: R$ 13.00

As duas primeiras linhas são entrada; a subtração é processamento; o console.log é apresentação da saída. Pense num funil apenas como desenho do fluxo. O limite da analogia é que programas reais podem produzir várias saídas, guardar estado e voltar a pedir dados.

Entrada existe antes de virar variável

Um dado pode vir do teclado, de um formulário, de um sensor, de um arquivo ou de outra API. Ao entrar em JavaScript, texto continua sendo texto. Simule o que um campo de formulário entregaria:

js
const digitado = '50.00';
console.log(typeof digitado, digitado);

const recebido = Number(digitado);
console.log(typeof recebido, recebido);
string 50.00 number 50

Converter não é detalhe do cálculo. É parte do contrato de entrada. Se a aplicação espera reais, precisa decidir se aceita vírgula, ponto, espaços, vazio e valor negativo antes de subtrair.

Processamento é a regra que ninguém vê

A regra pode ser uma conta, uma decisão ou uma sequência inteira. Coloque-a numa função que recebe valores e devolve valor, sem imprimir:

js
function calcularTroco(total, recebido) {
  return recebido - total;
}

console.log(calcularTroco(37, 50));
console.log(calcularTroco(82.4, 100));
13 17.599999999999994

O segundo resultado expõe ponto flutuante binário. O processamento matemático ocorreu, mas dinheiro pede uma representação mais segura. A decisão profissional é trabalhar em centavos inteiros e formatar apenas na saída.

Saída na tela não é o mesmo que devolver um valor

Uma função que só imprime não pode alimentar o próximo passo:

js
function mostrarTroco(total, recebido) {
  console.log(recebido - total);
}

const resultado = mostrarTroco(37, 50);
console.log(`retorno: ${resultado}`);
13 retorno: undefined

console.log conversa com quem observa o terminal. return conversa com o restante do programa. Quando você separa cálculo e apresentação, pode usar a mesma resposta numa tela, num recibo ou numa API.

A calculadora de troco nos três blocos

Agora normalize a entrada para centavos, processe com inteiros e apresente em reais:

js
function paraCentavos(valor) {
  return Math.round(Number(valor.replace(',', '.')) * 100);
}

function calcularTroco(total, recebido) {
  return recebido - total;
}

function formatar(centavos) {
  return `R$ ${(centavos / 100).toFixed(2)}`;
}

const total = paraCentavos('37,40');
const recebido = paraCentavos('50,00');
console.log(formatar(calcularTroco(total, recebido)));
R$ 12.60

Cada função tem uma responsabilidade observável. Aceitar centavos muda a conversão de entrada, não a subtração. Trocar o formato do recibo muda a saída, não o cálculo.

Trocando só a entrada sem tocar na regra

O mesmo processamento aceita dados de um pedido ou de uma promoção, desde que ambos entreguem centavos:

js
const calcularTroco = (total, recebido) => recebido - total;

const entradas = [
  { origem: 'caixa', total: 3740, recebido: 5000 },
  { origem: 'app', total: 8290, recebido: 10000 },
];

for (const entrada of entradas) {
  console.log(entrada.origem, calcularTroco(entrada.total, entrada.recebido));
}
caixa 1260 app 1710

O processamento não pergunta de onde o dado veio. Ele confia no contrato: inteiros em centavos. Essa fronteira reduz o número de linhas que mudam quando surge outra origem.

Quando a entrada não é o que o algoritmo esperava

Number('cinquenta') produz NaN sem lançar exceção. Se você não validar, o defeito atravessa o processamento e só aparece na saída:

js
function lerDinheiro(texto) {
  const valor = Number(texto.replace(',', '.'));
  if (!Number.isFinite(valor) || valor < 0) {
    throw new TypeError(`Valor inválido: ${texto}`);
  }
  return Math.round(valor * 100);
}

try {
  console.log(lerDinheiro('cinquenta'));
} catch (erro) {
  console.log(`${erro.name}: ${erro.message}`);
}
TypeError: Valor inválido: cinquenta

Leia a mensagem como diagnóstico: o processamento nem deveria começar. Corrija na fronteira e mantenha a regra central trabalhando com dados que cumprem o contrato.

Tudo grudado contra os três blocos separados

Uma alteração de formato mostra a diferença de manutenção. Na versão separada, o cálculo não muda:

js
const processar = ({ total, recebido }) => recebido - total;
const exibirReais = (centavos) => `R$ ${(centavos / 100).toFixed(2)}`;
const exibirCentavos = (centavos) => `${centavos} centavos`;

const saida = processar({ total: 3740, recebido: 5000 });
console.log(exibirReais(saida));
console.log(exibirCentavos(saida));
R$ 12.60 1260 centavos

Nos dois casos a regra é a mesma. Só a apresentação troca. Essa separação também melhora testes: você verifica 1260 sem depender de pontuação ou símbolo de moeda.

Missão: mapear um aplicativo que você usa

Escolha uma ação, como pedir transporte. Liste entradas (origem, destino, horário), processamento (rota, disponibilidade, preço) e saídas (estimativa, mapa, confirmação). Depois identifique uma entrada inválida e diga em qual fronteira ela deve parar.

Use este mapa como critério de revisão:

js
const mapa = {
  entradas: ['origem', 'destino'],
  processamento: ['calcular rota', 'estimar preço'],
  saidas: ['tempo', 'valor'],
};

console.log(Object.entries(mapa).map(([etapa, itens]) => `${etapa}:${itens.length}`).join(' | '));
entradas:2 | processamento:2 | saidas:2

Revise também a direção das dependências. A apresentação pode depender do resultado do cálculo, mas o cálculo não deveria depender de como a tela escreve reais. A validação conhece o formato recebido, enquanto a regra central conhece valores normalizados. Essa direção permite substituir terminal por formulário sem reescrever a subtração.

Em programas maiores, as três caixas aparecem em camadas: uma rota recebe a requisição, um serviço aplica a regra e uma resposta serializa o resultado. O desenho continua útil, desde que você não trate separação como obrigação de criar um arquivo por linha. Agrupe responsabilidades que mudam pelos mesmos motivos e teste os contratos entre elas.

Para conferir seu mapa, simule duas entradas que chegam por canais diferentes e exigem o mesmo processamento. Depois produza duas apresentações para o mesmo resultado. Se você consegue fazer cada troca sem alterar a regra central, as fronteiras estão claras. Se uma mudança de moeda obriga mexer na subtração, descubra onde unidade e formato foram misturados.

Quando as três caixas estiverem claras, avance para variável e tipo de dado, onde o contrato da entrada ganha nomes e tipos. O teste de mesa ajuda a seguir essas mudanças no papel, e o guia de lógica mostra a ordem completa.

  • entrada processamento saida
  • algoritmo
  • troco
  • dados de entrada

Perguntas frequentes

Console.log é sempre a saída de um programa?
Não. Ele é uma forma de apresentar dados no terminal. A saída lógica também pode ser um valor retornado, um arquivo salvo, uma resposta HTTP ou uma mudança de estado.
Validação faz parte da entrada ou do processamento?
A leitura pertence à entrada; verificar formato e limites costuma ficar na fronteira antes do processamento principal. O importante é impedir que dado inválido entre na regra central.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Node v26.3.0, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. Node.js — Process input and output — nodejs.org
  2. ECMAScript — Numeric Types — tc39.es

Continue por aqui