Quando usar Exceções

by caike

Um post interessante na lista GURU-PA:

(…) quando estamos desenvolvendo um projeto é geralmente uma boa estratégia desenvolver Exceções próprias, para tratar especificamente do problema em questão.
Queria saber se vcs têm algum padrão de implementação, como vcs trabalham com esta questão?
Segue minha resposta ao grupo:

Legal a dúvida!

Eu costumo escrever exceções quando sinto a necessidade de criar abstrações pra possíveis erros em um fluxo que normalmente não deve gerar erro. Por exemplo, se a sua aplicação depende de um arquivo de configuração, você pode lançar uma exceção específica caso o arquivo não exista. A alternativa seria retornar false, mas um simples boleano não diz muita coisa com relação ao erro em questão. Em linguagens não OO, tipo C, a alternativa é retornar error codes, o que enche o código de if/else e torna a manutenção um pesadelo.
No exemplo que o Felipe mencionou de Model.find(id), o AR lança um erro porque esse método é usado pra procurar por um record específico no banco, que necessariamente deve existir. Normalmente a gente usa Model.find(id) em actions oriundas de urls que foram geradas dinamicamente, resultados de uma query no banco. Por exemplo, uma listagem de produtos em /products, lista os products a partir de um Product.all  (SELECT * FROM products) e gera dinamicamente links para uma action que então chama Model.find(id).Nesse caso, o id do Model.find(id) está vindo de uma url, por exemplo  /products/1, que foi gerada por ids vindos originalmente do banco. Não foi o usuário que pensou “Ah.. deixa eu ver se existe esse id”. Pra casos como esse, onde pode ou não existir um record no banco, você usa Model.find_by_id(id), ou o novo Model.find_by(id: id) do Rails 4. Esses dois métodos “aceitam” o fato de não existir um resultado no banco, e simplesmente retornam nil caso não exista.
No geral, exceções são uma forma elegante em OO de falar que deu merda em algum lugar que não deveria ter dado merda, e oferecem ao client informações necessárias pra ele tratar o erro da forma como ele achar melhor.