Tratamento de erros sem exceções

Ao pesquisar SO para abordagens de manipulação de erros relacionadas à validação de regra de negócios, tudo o que encontro são exemplos de manipulação de exceção estruturada.

MSDN e muitos outros recursos de desenvolvimento respeitáveis ​​são muito claros que as exceções sãonão deve ser usado para lidar com casos de erros de rotina. Eles devem ser usados ​​apenas para circunstâncias excepcionais e erros inesperados que podem ocorrer de uso indevido pelo programador (mas não pelo usuário). Em muitos casos, erros de usuário, como campos deixados em branco, são comuns e coisas que nosso programadevemos esperar e, portanto, não são excepcionais e não são candidatos para o uso de exceções.

CITAR:

Lembre-se de que o uso do termo exceção na programação tem a ver com o pensamento de que uma exceção deve representar uma condição excepcional. Condições excepcionais, por sua própria natureza, normalmente não ocorrem; assimseu código não deve lançar exceções como parte de suas operações diárias.

Não lance exceções para sinalizar eventos comuns. Considere usar métodos alternativos para comunicar a um chamador a ocorrência desses eventos edeixe a exceção jogando quando algo realmente fora do comum acontecer.

Por exemplo, uso adequado:

private void DoSomething(string requiredParameter)
{
if (requiredParameter == null) throw new ArgumentExpcetion("requiredParameter cannot be null");
// Remainder of method body...
}

Uso impróprio:

// Renames item to a name supplied by the user.  Name must begin with an "F".
public void RenameItem(string newName)
{
   // Items must have names that begin with "F"
   if (!newName.StartsWith("F")) throw new RenameException("New name must begin with /"F/"");
   // Remainder of method body...
}

No caso acima, de acordo com as melhores práticas, seria melhor passar o erro para a interface do usuário sem envolver / exigir os mecanismos de manipulação de exceção do .NET.

Usando o mesmo exemplo acima, suponha que um precisaria impor um conjunto de regras de nomenclatura em relação aos itens. Qual abordagem seria melhor?

Ter o método retornar um resultado enumerado? RenameResult.Success, RenameResult.TooShort, RenameResult.TooLong, RenameResult.InvalidCharacters, etc.

Usando um evento em uma classe de controlador para relatar para a classe de interface do usuário? A interface do usuário chama o método RenameItem do controlador e, em seguida, manipula um evento AfterRename que o controlador gera e que tem status renomear como parte dos argumentos de evento?

A classe controladora faz referência direta e chama um método da classe da interface do usuário que lida com o erro, por exemplo, ReportError (texto da string).

Algo mais... ?

Essencialmente, eu quero saber como executar uma validação complexa em classes que podem não ser a própria classe Form, e passar os erros de volta para a classe Form para exibição - mas eu não quero envolver o tratamento de exceção onde não deveria ser usado (embora pareça muito mais fácil!)

Com base nas respostas à pergunta, sinto que terei que declarar o problema em termos mais concretos:

UI = Interface do usuário, BLL = Business Logic Layer (neste caso, apenas uma classe diferente)

O usuário insere valor na interface do usuário.Valor de relatórios da interface do usuário para BLL.A BLL realiza a validação de rotina do valor.BLL descobre violação de regras.BLL retorna violação de regra para a interface do usuário.A interface do usuário recebe o retorno da BLL e informa o erro ao usuário.

Como é rotina para um usuário inserir valores inválidos, as exceções não devem ser usadas. Qual é o caminho certo para fazer isso sem exceções?