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

[Dúvida] Exercício: Mensagem pós-processamento

Nesta versão, o usuário pode inserir seu nome no terminal, bem como selecionar (escolhendo 1, 2 ou 3) seu tipo de conta. Além disso também há um setTimeout de 3s simulando um processamendo real, que não atrapalha o rl.close() pois este também possui um setTimeout de 3.1s.

Gostaria de saber o que poderia melhorar no código no geral e como eu poderia fazer uma validação do formato do nome (assim como faço com números inteiros e entradas NaN). Obrigado :)

import { createInterface } from "readline";

const processarPedido = (nomeCliente, tipoCliente, callback) => {
  console.log(`Processando pedido de ${nomeCliente}...`);

  setTimeout(() => {
    console.log(callback(nomeCliente, tipoCliente));
  }, 3000);
};

const escreverMensagem = (nomeCliente, tipoCliente) => {
  if (tipoCliente === 1)
    return `Bem-vindo(a), ${nomeCliente}! Aproveite um cupom de boas-vindas!`;
  if (tipoCliente === 2) return `Obrigado pela sua compra, ${nomeCliente}!`;
  return `Obrigado pela preferência, ${nomeCliente}! Você ganhou frete grátis.`;
};

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

rl.question("Qual seu nome?\n> ", (nomeCliente) => {
  rl.question(
    "Você é um cliente... \n[1]Novo\n[2]Comum\n[3]VIP\n> ",
    (input) => {
      const tipoCliente = Number(input);

      if (tipoCliente !== 1 && tipoCliente !== 2 && tipoCliente !== 3) {
        console.log("Escolha uma das 3 opções disponíveis.");
        rl.close();
        return;
      }

      processarPedido(nomeCliente, tipoCliente, escreverMensagem);

      setTimeout(() => {
        rl.close();
      }, 3100);
    },
  );
});
2 respostas
solução!

Olá, Vitor Hugo! Como vai?

Parabéns pelo código! Você elevou o nível do exercício ao implementar o módulo readline e simular o assincronismo com o setTimeout. O uso de callbacks é um conceito fundamental no JavaScript, e você o aplicou com perfeição.

Sobre a sua dúvida de como validar o formato do nome e o que melhorar, aqui estão algumas sugestões práticas:

1. Validação de Nome (String)

Para validar se o nome é válido (não apenas se existe, mas se faz sentido), você pode usar Expressões Regulares (RegEx) ou métodos simples de string.

  • Comprimento mínimo: Garantir que o nome não seja apenas uma letra.
  • Apenas letras: Evitar que o usuário digite "12345" como nome.

Exemplo de lógica de validação:

if (nomeCliente.trim().length < 3 || !/^[a-zA-ZÀ-ÿ\s]+$/.test(nomeCliente)) {
    console.log("Por favor, insira um nome válido (mínimo 3 letras, sem números).");
    rl.close();
    return;
}

2. Melhoria na Gestão do rl.close()

Sincronizar o fechamento do terminal com um setTimeout de 3.1s funciona, mas é um pouco arriscado. Se você mudar o tempo do processamento para 5s, o programa vai fechar antes de exibir a mensagem.

Uma prática melhor é colocar o rl.close() dentro do próprio callback ou logo após a execução da lógica final. Como seu processarPedido usa um setTimeout interno, você poderia passar o rl para dentro dele ou emitir o fechamento lá.

3. Substituindo o if por um Objeto (Clean Code)

Sua função escreverMensagem está ótima, mas quando temos muitas opções, o código pode ficar cheio de ifs. Uma alternativa elegante é usar um objeto de mapeamento:

const mensagens = {
  1: (nome) => `Bem-vindo(a), ${nome}! Aproveite um cupom!`,
  2: (nome) => `Obrigado pela sua compra, ${nome}!`,
  3: (nome) => `Obrigado pela preferência, ${nome}! Você ganhou frete grátis.`,
};

const escreverMensagem = (nome, tipo) => mensagens[tipo](nome);

4. Dica de Ouro: Async/Await

No Node.js moderno, lidar com múltiplas perguntas no readline pode gerar o que chamamos de "Callback Hell" (uma função dentro da outra). No futuro, dê uma olhada no readline/promises, que permite usar await rl.question(), deixando o código linear e muito mais fácil de ler!

Seu raciocínio lógico está muito maduro. Essa preocupação com a validação de entrada é o que diferencia um desenvolvedor que apenas "faz funcionar" de um que constrói "sistemas resilientes".

Espero que possa ter lhe ajudado! Alguma dessas validações com RegEx pareceu complicada ou você já tinha tido contato com elas?

Oi, Evandro! Tudo bem?

Obrigado pelo feedback e pelas sugestões, gostei bastante das explicações.

Sobre as validações com RegEx, ainda não conheço muito esse recurso, mas certamente vou estudar mais sobre isso no futuro.

Sobre o rl.close(), confesso que já tinha percebido que depender de um setTimeout não é o ideal mesmo, já que não está atrelado diretamente a uma ação do fluxo. Só não sabia exatamente como encerrar a interface do readline depois dos 3 segundos que usei na simulação de processamento. Agora ficou mais claro como posso organizar isso melhor nas próximas implementações.

Em relação à ideia de substituir os if por um objeto, ainda tenho um pouco de dificuldade com o acesso a chaves via colchetes. Pesquisando, entendi melhor essa diferença entre acessar por ponto e por colchetes, principalmente no caso de chaves numéricas, que não funcionam com mensagens.1(), por exemplo. Também entendi que quando usamos uma variável como chave, o uso de colchetes é necessário justamente para permitir esse dinamismo. Acho esse padrão bem interessante, só preciso praticar mais para me acostumar.

Sobre async/await, ainda não pude treinar efetivamente com essa estrutura nem com o await rl.question(), mas vou chegar nessa parte conforme for avançando nos estudos.

Obrigado mais uma vez pelas dicas!