Programação é sobre trabalho
Acho que a maneira mais fácil de responder isso é entender o progresso que a OOP fez ao longo dos anos. Tudo feito em OOP (e a maioria dos paradigmas de programação, por exemplo) é modelado em torno de precisar de trabalho feito .
Toda vez que um método é chamado, o chamador está dizendo "Eu não sei como fazer este trabalho, mas você sabe como, então você faz isso por mim."
Isso apresentou uma dificuldade: o que acontece quando o método chamado geralmente sabe como fazer o trabalho, mas nem sempre? Nós precisávamos de uma maneira de nos comunicar "Eu queria te ajudar, eu realmente fiz, mas eu simplesmente não posso fazer isso."
Uma metodologia inicial para comunicar isso foi simplesmente retornar um valor "lixo". Talvez você espere um inteiro positivo, então o método chamado retorna um número negativo. Outra maneira de conseguir isso era definir um valor de erro em algum lugar. Infelizmente, os dois caminhos resultaram em código clichê let-me-check-over-here-to-make-sure-tudo-kosher . Conforme as coisas ficam mais complicadas, esse sistema se desfaz.
Uma Analogia Excepcional
Digamos que você tenha um carpinteiro, um encanador e um eletricista. Você quer encanador para consertar sua pia, então ele dá uma olhada nisso. Não é muito útil se ele disser apenas a você, "Desculpe, não posso consertá-lo. Está quebrado." Inferno, é ainda pior se ele der uma olhada, sair e mandar um carta dizendo que ele não poderia consertá-lo. Agora você precisa checar seu e-mail antes mesmo de saber que ele não fez o que queria.
O que você preferiria é que ele lhe dissesse: "Olha, eu não consegui consertar porque parece que você não está funcionando."
Com essas informações, você pode concluir que deseja que o eletricista analise o problema. Talvez o eletricista encontre algo relacionado ao carpinteiro, e você precisará que o carpinteiro o conserte.
Heck, você pode até não saber que você precisa de um eletricista, você pode não saber quem você precisa. Você é apenas uma empresa de médio porte em um negócio de consertos em casa e seu foco é o encanamento. Então você diz a seu chefe sobre o problema e, em seguida, ele diz ao eletricista para corrigi-lo.
Isto é o que as exceções estão modelando: modos de falha complexos de maneira dissociada. O encanador não precisa saber sobre eletricista - ele nem precisa saber que alguém na cadeia pode consertar o problema. Ele apenas relata o problema que encontrou.
Então ... um anti-padrão?
Ok, entender o ponto das exceções é o primeiro passo. O próximo é entender o que é um antipadrão.
Para se qualificar como um antipadrão, é necessário
- resolva o problema
- tem consequências negativas definitivas
O primeiro ponto é facilmente encontrado - o sistema funcionou, certo?
O segundo ponto é mais complicado. A principal razão para usar exceções como o fluxo de controle normal é ruim é porque esse não é seu objetivo. Qualquer peça de funcionalidade em um programa deve ter um propósito relativamente claro, e a cooptação desse propósito leva a uma confusão desnecessária.
Mas isso não é um dano definitivo . É uma maneira pobre de fazer as coisas e é estranho, mas um anti-padrão? Não. Apenas ... estranho.