Pense bem antes de usar o try catch
Tags: programming, testing, tdd, trycatch
Published: 2023-06-24 20:04:26

Acredito que todo leitor já usou ou já ouviu falar do **try catch**. As declarações try catch marcam um bloco de declarações para testar (try), e especifica uma resposta, caso uma exceção seja lançada.

Com isso, eu lhe pergunto: Existe algum mal em usar o try catch? E a resposta é, não. Eu poderia muito bem terminar por aqui. Porém, irei formular mais essa resposta. 

## O que me levou a escrever esse artigo?

Recentemente estava eu conversando com um amigo sobre a utilização de um try catch para a resolução de um problema no código. 

A utilização de um try catch resolve em grande parte a maioria dos problemas quando falamos de tratamento. Porém, vale a pena **sempre** utilizar o try catch? 

> Bloco try/catch serve para tratamento de exceções, tratamento de códigos que podem não ser totalmente atendidos e gerarem alguma exceção/erro. [Rafael Withoeft](https://pt.stackoverflow.com/questions/58536/para-que-servem-os-blocos-try-catch-e-quando-devem-ser-utilizados#:~:text=Bloco%20try%2Fcatch%20serve%20para,tratamento%20dos%20erros%20que%20aconteceram.)

Em casos onde se é totalmente entendível os cenários, por que não utilizar uma simples condicional? Ou seja, prefira o uso de condicionais ao try catch, e caso não seja possível, somente então utilize o try catch.

## Vamos entender através do código

```ts
const isDev = (about: string) => {
    return about.includes('developer')
}

const response = isDev('My name is Marlon, I am Brazilian, I live in Rio Grande do Sul and I work as a developer.')

console.log(response)
```

Vamos nos atentar a função **isDev**.

Vamos imaginar que recebemos o parâmetro de algum serviço. Com isso, existem grandes possibilidades de o parâmetro retornar _undefined_ ou _null_. O que aconteceria com a nossa aplicação caso chamássemos isDev recebendo via parâmetro um undefined? Isso mesmo, a aplicação quebraria!

Uma forma de resolver esse problema, seria colocando um try catch em volta da validação. Obviamente esse é um cenário muito simples para usar um try catch, mas para o objetivo do artigo, já serve.

```ts
const isDev = (about: string) => {
    try {
        return about.includes('developer')
    } catch(error) {
        return false
    }
    
}
```

Agora caso ocorra algum problema, sempre retornaremos um **false**.

Porém, outra forma de resolver esse problema é utilizando uma condicional.

```js
const isDev = (about: string) => {
    if(about) {
        return about.includes('developer')
    }
    return false 
}
```

A questão é, existem cenários que dificilmente você imagina que o parâmetro pode ser undefined ou null, levando a não tratar esses cenários. E quando trata, usa um try catch sem necessidade.

## Como resolver o problema do try catch?

Para mim a melhor solução é utilizar testes unitários. Assim, você consegue validar todos os tipos de cenários possíveis, mas ainda assim, você pode cair na armadilha de esquecer algum cenário e acabar gerando um problema em produção.

Para isso, costumo utilizar o TDD (Test-Driven Development), assim você consegue pensar em todos os cenários de erros enquanto está desenvolvendo. Devido o fato de o TDD se basear no fluxo: Red, Green, Refactor, que respectivamente, significa: Faça o teste quebrar, faça o teste passar e em seguida, refatore. O que faz o TDD ser tão útil para a evitar problemas é a etapa Red. Onde normalmente você acaba passando/pensando nos cenários de erros e assim, ir cobrindo os cenários com testes unitários.

Portanto, utilizo o try catch somente quando realmente necessário, quando estou consumindo algum serviço externo que não é claro os cenários que podem ocasionar erros. Se esse não for o caso, utilizo condicionais em conjunto com testes unitários, para cobrir todos os possíveis cenários de erros.