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

Função e parâmetro: quebrar o problema em partes

Decompor um algoritmo grande em funções com nome honesto: parâmetro, argumento, retorno e o teste de cada parte isolada, executado no Node.

Rodolfo Mori4 min de leitura

Função encapsula uma tarefa com entradas e saída; decomposição transforma um problema grande em tarefas menores que podem ser nomeadas, testadas e combinadas. O ganho principal não é reduzir linhas, mas reduzir quantas regras você precisa manter na cabeça ao mesmo tempo.

O domínio é um boletim que valida notas, descarta a menor, calcula média e classifica a situação. Sem decomposição, cada mudança atravessa um bloco corrido. Com funções, a regra nova encontra um endereço.

Um problema grande é uma pilha de perguntas menores

Antes de código, escreva as perguntas em ordem:

text
1. As notas são válidas?
2. Qual nota deve ser descartada?
3. Qual é a média das restantes?
4. Qual situação corresponde à média?
5. Como apresentar o resultado?

Esse pseudocódigo revela cinco responsabilidades. Uma função pode responder cada pergunta. A lista não executa no Node; ela evita misturar raciocínio e sintaxe cedo demais.

Pense numa cozinha com estações: uma pessoa confere ingredientes, outra prepara, outra monta. A analogia ajuda a enxergar contratos. O limite é que funções não são pessoas e chamar muitas camadas também tem custo de leitura; separar sem motivo cria peregrinação pelo arquivo.

O nome é um teste de responsabilidade

Uma função chamada validarNotasCalcularMediaEClassificar admite três verbos. Separe os resultados:

js
function calcularMedia(notas) {
  return notas.reduce((soma, nota) => soma + nota, 0) / notas.length;
}

function classificar(media) {
  return media >= 7 ? 'aprovado' : 'recuperação';
}

const media = calcularMedia([8, 7, 9]);
console.log(media, classificar(media));
8 aprovado

O nome não precisa narrar a implementação. Ele declara o resultado. Se você troca laço por reduce, calcularMedia continua honesto porque o contrato não mudou.

Parâmetro, argumento e retorno

Na definição, notas é parâmetro. Na chamada, [8, 7, 9] é argumento. 8 é o retorno:

js
function calcularMedia(notas) {
  const soma = notas.reduce((total, nota) => total + nota, 0);
  return soma / notas.length;
}

const resultado = calcularMedia([8, 7, 9]);
console.log(resultado);
8

Parâmetro nomeia o papel, não um caso concreto. notas funciona melhor que notasDaAna, porque a função deve servir a qualquer aluno que cumpra o contrato.

Retorno encerra a chamada e entrega um valor. Uma função pode ter vários return, desde que todos representem caminhos compreensíveis. O fluxograma ajuda a enxergar caminhos sem resposta.

Imprimir não é devolver

Uma função que apenas mostra parece correta no terminal, mas não alimenta a classificação:

js
function calcularMedia(notas) {
  const media = notas.reduce((soma, nota) => soma + nota, 0) / notas.length;
  console.log(media);
}

const media = calcularMedia([8, 7, 9]);
console.log(`retorno: ${media}`);
8 retorno: undefined

console.log é saída para observação; return é saída da função para o programa. Corrija trocando o efeito por retorno e deixe a apresentação numa camada externa.

Quatro funções compõem o boletim

Cada parte recebe o mínimo necessário:

js
function validar(notas) {
  return notas.length >= 2 && notas.every((nota) => Number.isFinite(nota) && nota >= 0 && nota <= 10);
}

function descartarMenor(notas) {
  const copia = [...notas];
  copia.splice(copia.indexOf(Math.min(...copia)), 1);
  return copia;
}

function calcularMedia(notas) {
  return notas.reduce((soma, nota) => soma + nota, 0) / notas.length;
}

function classificar(media) {
  return media >= 7 ? 'aprovado' : 'recuperação';
}

const notas = [6, 8, 7.5, 8];
if (!validar(notas)) throw new RangeError('Notas inválidas');
const consideradas = descartarMenor(notas);
const media = calcularMedia(consideradas);
console.log(consideradas, media.toFixed(2), classificar(media));
[ 8, 7.5, 8 ] 7.83 aprovado

O resultado 7.83 foi executado no Node. Mais importante, a regra “descartar a menor” mora numa função isolada. Validar não conhece média; classificar não conhece a lista.

Teste cada parte sem executar o programa inteiro

Entradas pequenas dão diagnósticos específicos:

js
function classificar(media) {
  return media >= 7 ? 'aprovado' : 'recuperação';
}

for (const [entrada, esperado] of [[6.9, 'recuperação'], [7, 'aprovado'], [10, 'aprovado']]) {
  const obtido = classificar(entrada);
  console.log(entrada, obtido, obtido === esperado);
}
6.9 recuperação true 7 aprovado true 10 aprovado true

Se esse teste falha, você não precisa investigar descarte nem soma. Decomposição reduz a área de busca do erro. Depois transforme verificações em testes automatizados no framework do projeto.

Medindo o impacto da regra nova

No bloco corrido, descartar a menor exige encontrar o trecho de soma, copiar a lista e substituir a entrada do laço. Na versão decomposta, o fluxo recebe uma chamada nova e a função concentra a regra. Para não inventar medição, contamos um conjunto explícito de linhas marcadas como alteradas:

js
const alteracoesVersaoCorrida = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22];
const alteracoesVersaoDecomposta = [8, 9, 10];

console.log('corrida', alteracoesVersaoCorrida.length);
console.log('decomposta', alteracoesVersaoDecomposta.length);
corrida 11 decomposta 3

A contagem pertence a este exemplo controlado, não é lei universal. Uma arquitetura ruim pode ter muitas funções e ainda espalhar a mudança. A evidência útil é a localização: três linhas dentro de uma responsabilidade com nome.

Lista longa de parâmetros é sintoma

Parâmetros demais tornam a ordem frágil:

js
function resumo({ aluno, media, faltas, turma }) {
  return `${aluno} | ${turma} | média ${media} | faltas ${faltas}`;
}

console.log(resumo({ aluno: 'Lia', media: 8, faltas: 2, turma: 'A' }));
Lia | A | média 8 | faltas 2

Um objeto nomeia argumentos e permite mudar a ordem da escrita. Não use objeto para esconder que a função depende de quinze dados desconexos; nesse caso, reveja a responsabilidade e o modelo.

Missão: três funções para a nota final

Crie calcularMediaPonderada, atingiuFrequencia e definirSituacao. Antes de JavaScript, escreva entrada e retorno de cada uma. Teste a borda de média sete e frequência 75%.

js
const calcularMediaPonderada = (notas, pesos) => notas.reduce((soma, nota, i) => soma + nota * pesos[i], 0) / pesos.reduce((a, b) => a + b, 0);
const atingiuFrequencia = (presencas, aulas) => presencas / aulas >= 0.75;
const definirSituacao = (media, frequenciaOk) => media >= 7 && frequenciaOk ? 'aprovado' : 'recuperação';

const media = calcularMediaPonderada([6, 8], [1, 1]);
console.log(media, atingirFrequenciaSemErro(0));

function atingirFrequenciaSemErro() {
  const ok = atingiuFrequencia(75, 100);
  return definirSituacao(media, ok);
}
7 aprovado

Revise dependências depois de decompor. Uma função de cálculo não deve ler variável global de turma nem escrever no terminal. Receba tudo que precisa e devolva resultado. Essa pureza não é obrigação universal, mas facilita teste de lógica porque a mesma entrada produz a mesma saída.

Evite também funções que apenas repassam chamada sem acrescentar nome útil, validação ou composição. Cada camada aumenta distância entre problema e regra. Extraia quando reduz carga mental, concentra mudança ou permite testar uma decisão isolada.

No fluxo principal, leia as chamadas como pseudocódigo: validar, descartar menor, calcular média, classificar, apresentar. Se a sequência não conta a história do requisito, melhore nomes ou fronteiras antes de adicionar comentários extensos.

Contratos de erro fazem parte da decomposição. Decida se uma função lança exceção, devolve resultado discriminado ou retorna ausência. Não misture formas sem motivo; quem chama precisa saber como continuar em cada caso.

Teste a composição além das partes. Funções isoladas podem cumprir contratos incompatíveis: uma devolve reais, outra espera centavos; uma aceita lista vazia, outra divide pela quantidade. Um caso de ponta a ponta pequeno prova que as fronteiras se encaixam.

Quando a regra mudar, anote quais funções precisaram de edição. Se a mudança atravessa todas, talvez a divisão siga etapas técnicas em vez de responsabilidades de negócio. Use essa evidência para refatorar depois que os testes preservarem o comportamento.

O critério é testar cada função isolada e a composição. Depois compare decomposição com recursividade, pratique nos exercícios resolvidos, consulte o guia de lógica e siga a trilha.

  • funcao
  • parametro
  • decomposicao
  • retorno
  • abstracao

Perguntas frequentes

Quantas linhas uma função deve ter?
Não existe limite universal. Prefira uma responsabilidade com nome honesto, entradas claras e um resultado testável. Se o nome precisa de “e”, investigue duas funções.
Parâmetro e argumento são sinônimos?
Não. Parâmetro é o nome declarado pela função; argumento é o valor concreto fornecido em uma chamada. O argumento ocupa o papel previsto pelo parâmetro.

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. ECMAScript — Function Definitions — tc39.es
  2. ECMAScript — Return Statement — tc39.es

Continue por aqui