Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Dúvida] Exercício: Mensagem com atraso

Em um caso de callback como esse, qual é a melhor prática: declarar a função callback separadamente ou passar uma arrow function direto na chamada?

Por exemplo, qual abordagem é mais recomendada?

responderUsuario(nome, mostrarResposta);

ou

responderUsuario(nome, (nomeUsuario) => {
  console.log(`Pronto, ${nomeUsuario}! Essa é sua resposta!`);
  rl.close();
});

Existe alguma diferença relevante entre elas em termos de boas práticas ou isso depende mais do contexto (reutilização, legibilidade etc.)?

Solução do exercício:

import { createInterface } from "readline";

const rl = createInterface({
  input: process.stdin,
  output: process.stdout,
});

const validarNome = (nome) => {
  nome = nome.trim();

  const nomeValido = nome.length > 1 && /^[a-zA-ZÀ-ÿ\s'-]+$/.test(nome);

  if (!nomeValido) return null;
  return nome;
};

const validarPergunta = (pergunta) => {
  pergunta = pergunta.trim();

  const perguntaValida = pergunta.length >= 2;

  if (!perguntaValida) return null;
  return pergunta;
};

const responderUsuario = (nome, callback) => {
  console.log("Processando sua pergunta...");

  setTimeout(() => {
    callback(nome);
  }, 3000);
};

const mostrarResposta = (nome) => {
  console.log(`Olá, ${nome}! Aqui está a resposta para sua dúvida.`);
  rl.close();
};

rl.question("Qual seu nome?\n> ", (input) => {
  const nome = validarNome(input);

  if (nome === null) {
    console.log("Nome inválido");
    rl.close();
    return;
  }

  rl.question("Faça sua pergunta.\n> ", (input) => {
    const pergunta = validarPergunta(input);

    if (pergunta === null) {
      console.log("Pergunta inválida");
      rl.close();
      return;
    }

    responderUsuario(nome, mostrarResposta);
  });
});
2 respostas
solução!

Olá, Vitor. Como vai?

Essa é uma excelente dúvida de arquitetura! No JavaScript, como as funções são "cidadãs de primeira classe", temos essa flexibilidade total, mas a escolha entre uma abordagem ou outra geralmente segue alguns critérios de Clean Code.

Não existe uma regra absoluta, mas podemos dividir a decisão com base em três pilares:

1. Reutilização de Código

Se a função mostrarResposta for usada em outros lugares do seu sistema, a declaração separada é obrigatória.

  • Declarada separadamente: Melhora a manutenção. Se você precisar mudar o texto da saudação, muda em um só lugar e reflete em todo o projeto.
  • Arrow function (Inline): É "descartável". Se você precisar da mesma lógica em outro arquivo, terá que copiar e colar, o que fere o princípio DRY (Don't Repeat Yourself).

2. Legibilidade e "Callback Hell"

Analisando o seu código, você já tem um aninhamento de rl.question.

  • Arrow function: Se você passar a lógica direto na chamada, o código tende a crescer para a direita (identação), tornando a leitura cansativa.
  • Função Nomeada: Como você fez com responderUsuario(nome, mostrarResposta), o código fica muito mais limpo. Você lê a chamada e entende o que acontece ("responda ao usuário e depois mostre a resposta") sem precisar ler a implementação da lógica naquele momento.

3. Testabilidade

Para quem trabalha com testes unitários, declarar a função separadamente é muito melhor. Você consegue exportar apenas a mostrarResposta e testar se ela imprime o que deveria, sem precisar disparar todo o fluxo do readline.


Resumo de Boas Práticas

CritérioFunção Nomeada (Separada)Arrow Function (Inline)
ComplexidadeIdeal para lógicas longas.Ideal para lógicas de uma única linha.
ContextoQuando o nome da função ajuda a explicar o código.Quando a lógica é óbvia e simples.
**Escopo de this**Segue a regra de funções tradicionais.Mantém o escopo léxico (útil em classes).

Veredito: No seu exercício, como a lógica envolve o fechamento da interface (rl.close()) e uma string composta, a sua escolha de declarar separadamente (mostrarResposta) é considerada a melhor prática. Ela deixa o fluxo principal do programa (o question) muito mais fácil de seguir.

Um detalhe técnico: note que na sua função responderUsuario, você usou uma arrow function dentro do setTimeout. Ali, a arrow function é perfeita, pois ela serve apenas como um "embrulho" para atrasar a execução da sua callback nomeada!

Espero que possa ter lhe ajudado!

Oi, Evandro! Obrigado pelo feedback e pelas observações.

Os cenários de uso de cada formato de função ficaram mais claros pra mim agora, mas com certeza ainda preciso praticar um pouco pra fixar bem.

Vou levar suas dicas em conta nas próximas implementações.

Obrigado pela explicação!