Motivação

Como sabemos, não compilamos código em JavaScript - um ponto negativo que camufla determinados erros que só acontecem em situações especiais e/ou quando o usuário já está usando a aplicação. Por isso a adoção de boas práticas e políticas de testes em JavaScript é fundamental. Vejamos um exemplo de boas práticas em JavaScript, exibindo mensagens de erro através de abstração.

Saiba mais sobre JavaScript e Testes

Passo 1: O problema de não usar abstração

Métodos de abstração são funções que ocultam os detalhes de implementação das mesmas. Vamos ver como a abstração pode ajudar na vida real.

Abordagem incorreta: Por exemplo, na Listagem 1 temos um tipo de mecanismo de exibição de avisos sistêmicos.

Listagem 1. Exemplo de função para tratamento de erros/avisos.

1.  function converterIdade(idade) {
2.   if (!_.isString(idade)) throw new Error("Uma string era esperada");
3.   var a;
4.   console.log("Tentativa de converter uma idade ");
5.   a = parseInt(idade, 10);
6.   if (_.isNaN(a)) {
7.     console.log(["Não pode converter a idade:", idade].join(' '));
8.     a = 0;
9.   }
10.   return a;
11.  }

Essa função, embora não seja abrangente o suficiente para converter strings de idade, é bem ilustrativa. O uso da função converterIdade pode se dar da seguinte maneira:

1. converterIdade("42");
2. converterIdade(42);
3. converterIdade("abc");

Linha 1: O primeiro exemplo recebe um valor em string e efetua a conversão com sucesso, exibindo o resultado 42 no console.

Linha 2: lança um error: Uma string era esperada em vista do tipo de dado do parâmetro não ter sido enviado corretamente.

Linha 3: lança uma mensagem “Não pode converter a idade: abc” justamente porque o dado passado sequer representa um número, seja em string ou tipo numérico.

Problema: A função converter idade funciona como está escrito, mas se você desejar modificar a maneira em que os avisos são apresentados, as mudanças precisarão ser feitas nas linhas apropriadas, e em qualquer outro lugar onde padrões semelhantes são usados – levando a reescrita desnecessária de código.

Passo 2: Usando abstração

Solução: Uma abordagem melhor é “abstrair” a noção de avisos em funções, padronizando assim o código, tal como temos na Listagem 2.

Listagem 2. Exemplo de funções para tratar erros e mensagens.

1. function fail(msg) {
2.  throw new Error(msg);
3. }
4. function warn(msg) {
5.  console.log(["AVISO:", msg].join(' '));
6. }
7. function note(msg) {
8.  console.log(["NOTA:", msg].join(' '));
9. }

Veja que apenas encapsulamos o comportamento que antes estava solto no código, assim podemos reusar tais funções em qualquer lugar ao longo da nossa implementação. Usando essas funções, a função converterIdade pode ser reescrita da mesma forma que vemos na Listagem 3.

Listagem 3. Nova função converterIdade com uso das funções de erro/aviso.

1. function converterIdade(idade) {
2.  if (!_.isString(idade)) fail("Uma string era esperada");
3.  var a;
4.  note("Tentativa de converter uma idade ");
5.  a = parseInt(idade, 10);
6.  if (_.isNaN(a)) {
7.    warn(["Não pode converter a idade:", idade].join(' '));
8.    a = 0;
9.  }
10.  return a;
11. }

Portanto, ao tentar executar o novo código, seu comportamento se dará de forma semelhante, porém com logs mais apropriados:

1. converterIdade("frob");
2.   // (console) AVISO: Não pode converter a idade: frob
3.   // Saída: 0

Não é muito diferente do antigo comportamento, exceto que agora a ideia de erros de report foram abstraídas. O report pode, assim, ser modificado completamente a bel prazer, tal como vemos na Listagem 4.

Listagem 4. Modificando comportamento das mensagens.

1. function note() {}
2. function warn(msg) {
3.  alert("Isso não parece uma idade válida");
4. }
5. converterIdade("abc");
6. // (alert box) Isso não parece uma idade válida
7. // Saída: 0

Saiba mais sobre Programação funcional com JavaScript