Ter uma API de exceção robusta e bem projetada que seja consistente é muito apropriado. Usar isso para impor regras de negócios também pode ser apropriado. De fato, na minha experiência, quanto mais complicada a regra de negócios, maior a probabilidade de ser tratada dessa maneira. Geralmente, é tão fácil, se não mais fácil, escrever um sistema em que são esperadas exceções do que escrever uma lógica de ramificação autorizada.
Isso significa que regras simples que podem ser descritas em uma única frase geralmente devem ser implementadas de maneira preventiva ou autoritária, dependendo de qual seja. No entanto, se você tiver uma regra que seja multidimensional e exija mais de três ou quatro fatores (especialmente se a seleção desses fatores for baseada em um ou mais dos outros fatores), a codificação de exceção poderá ser mais sustentável. Freqüentemente, nesses casos, o caminho lógico terá muitas exceções precursoras que precisam ser lançadas (verifica o motivo pelo qual a ação não pode ser executada); então (ou vice-versa) há uma falha na segurança (para verificar se a ação está autorizada). ), às vezes haverá alguma lógica de acumulação autorizada que precisa ser verificada (disponibilidade de descendente / ancestral, precursor declara que os objetos devem ser colocados etc.)
Um benefício que deriva desse tipo de lançamento de exceção é que ele permite separar e reutilizar as exceções precursoras em várias áreas do seu projeto. (Essa é a essência da programação orientada a aspectos.) Ao fazer isso, você está encapsulando um aspecto específico das regras gerais de negócios em um componente independente e sustentável. Em geral, esses componentes corresponderão 1-1 às mensagens de erro lançadas. (Embora às vezes você tenha um componente que lança várias exceções diferentes, quase nunca deve ter a mesma exceção lançada de vários componentes.)
Na minha opinião, é mais difícil projetar sistemas baseados em exceções e o tempo de desenvolvimento inicial é mais longo, pois é necessário criar o processo de exceção em todos os N níveis. No entanto, esses sistemas geralmente acabam sendo muito mais estáveis. Embora nunca seja possível projetar um sistema que 'não falhe', o benefício do design baseado em exceções é que você está sempre antecipando falhas. Para a maioria das pessoas, o processo pode ser contra-intuitivo. É como pedir orientações e pedir que alguém lhe diga todas as ruas que você não deve ligar.