 .NET
- Organizando o tratamento de erros - Nível de método
.NET
- Organizando o tratamento de erros - Nível de método
Se você esta 'mais perdido do que cachorro em dia de mudança' quando a questão é o tratamento de erros em sua aplicação este artigo pode ser a sua tábua de salvação (ou perdição).
Vou começar com o tratamento de erros no nível de métodos e mostrar uma forma (existem muitas outras formas) de organizar as coisas quando os erros ocorrerem em sua aplicação.
Vou usar os recursos e vantagens do tratamento estruturado de exceções da plataforma .net , portanto , esqueça as cláusulas On Error goto/Resume do Visual Basic 6 pois vamos usar a estrutura try/catch/finally.
A estratégia adotada para tratamento de erros esta resumida a seguir de acordo com o cenário :
1- Erros potenciais estão previstos e sendo tratados em uma rotina
Solução - Usar uma combinação de blocos try Catch como mecanismo de retorno para tratamento de erros;
2- Uma informação importante deve ser incluída na ocorrência da exceção
Solução - Criar e lançar(throw) um nova exceção com a informação anexada;
3- As variáveis/objetos/recursos usados na rotina devem ser liberados da memória
Solução - Realizar a operação de limpeza em um bloco finally
4- Erros potenciais não estão sendo tratados em uma rotina
Solução - A recuperação deve ser tratada pela rotina que fez a chamada no seu tratamento de erros
A estrutura de tratamento de erros da plataforma .NET pode ser usada de diversas formas.
Vejamos a sintaxe básica do bloco Try/Catch para VB.NET e C#:
| Private Sub Rotina( )
    Try
          'Codigo a ser tratado
    Catch exc As Exception
          'tratamento de erro
     Finally
           'operação de limpeza
     End Try
End Sub 
 |       private void Rotina( )
      {
	try
	{
	    // Codigo a ser tratado
	}
	catch (Exception exc)
	{
	    // tratamento de erro
	}
	finally
	{
	      // operação de limpeza
	}
     }  | 
| VB .NET | C# | 
O bloco Try inclui o código que implementa o método.
O bloco Catch é opcional, e inclui o código que trata erros específicos que são identificados e recuperados quando possível.
O bloco finally é opcional,e realiza a operação de limpeza requerida antes que o método encerre devido a um erro ou não. Geralmente as operações referem-se ao fechamento de conexões com banco de dados , liberação de objetos criados no método, etc. O bloco finally sempre será executado quer ocorra ou não uma exceção.
Os blocos Catch e finally são opcionais mas você deve usar um deles obrigatoriamente.
De forma geral você deve usar a estrutura de tratamento de erros em qualquer método um erro possa ocorrer mas a técnica exata depende da circunstância. Veja abaixo um resumo dos possíveis cenários:
| Erros podem ocorrer ? | São Recuperáveis? | Uma informação importante deve ser anexada ? | A limpeza é necessária ? | Combinação recomendada de blocos try, catch, e finally | 
|---|---|---|---|---|
| Não | N/A | N/A | Sim | TRy e finally somente | 
| Sim | Não | Não | Não | Nenhum | 
| Sim | Não | Não | Sim | TRy e finally somente | 
| Sim | Não | Sim | Não | try e catch somente | 
| Sim | Não | Sim | Sim | try, catch, e finally | 
| Sim | Sim | N/A | N/A | try e catch only | 
Nota: Lembre-se que o .NET Framework não fecha as conexões de banco de dados , arquivos ,etc quando erros ocorrem. Esta responsabilidade é do programados (ou seja SUA), e, você deve fazer isso no bloco finally pois esta é a última oportunidade de realizar as ações de limpeza antes que a infraestrutura do tratamento de exceção tome o controle da aplicação.
Para ajudá-lo a definir melhor a implementação de uma estratégia de tratamento de erros temos a seguir algumas questões cujas respostas podem ajudá-lo a tomar esta decisão:
1- Erros podem ocorrer durante a execução do código de uma rotina/método ?
Se a resposta for SIM, então implemente o tratamento usando o bloco try/catch.
Se um erro ocorre e nada pode ser
feito durante a execução do código, você deve propagar a
exceção a rotina que fez a chamada da rotina/método onde o
erro ocorreu. 
Por exemplo se uma rotina tenta escrever um registro em uma
tabela de um banco de dados e encontra o registro bloqueado você
pode tentar efetuar a gravação mais uma vez (este erro é
recuperável).
Se um valor é passado para a rotina e durante a execução da
operação ocorre um erro de estouro de pilha a recuperação
não é possível na rotina mas pode ser tratada pela rotina que
fez a chamada do método no seu tratamento de erros.
Exceções que ocorrem na plataforma .NET contém informação detalhada relacionada ao erro; mas as exceções não fornecem qualquer informação de contexto sobre o que esta sendo feito a nível de aplicação no tratamento do erro ou no fornecimento de informação importante ao usuário.
Neste caso uma nova exceção pode ser criada e lançada com a informação necessária. O primeiro parâmetro para a nova exceção deverá conter a mensagem do contexto e o segundo deverá ser a exceção original. O mecanismo de tratamento de exceção da plataforma .NET cria uma linked list de objetos Exception de forma a criar um rastro a partir da exceção raiz até o nível onde a exceção foi tratada. Exemplo:
| Catch
        ex As Exception Throw New Exception("mensagem do contexto", ex) | catch (Exception ex) 
{ 	
   throw (new Exception("mensagem do contexto", ex)); 
}  | 
| VB.NET | C# | 
Um bloco Catch não deve ser usado no fluxo normal da sua aplicação.
O fluxo normal do programa deve ser colocado somente no bloco try e o fluxo anormal deve ser colocado no bloco Catch.
O mecanismo de tratamento de exceções da plataforma .NET é eficiente e poderoso; eu tratei neste artigo das exceções que ocorrem a nível de método/rotina mas outras exceções específicas podem ser capturadas e processadas diferentemente.
Você pode criar uma classe para tratamento de exceções que herda da classe base Exception e pode incluir funcionalidades requeridas pela sua aplicação nesta classe. Um exemplo desta técnica pode ser vista no código a seguir onde uma nova tentativa de atualização é feita após ocorrer o erro:
| Imports System
Imports System.Configuration
Imports System.Data
Imports System.Data.OleDb
	
	Private Sub atualizaDados(ByVal problemID As Integer,  ByVal sectionHeading As String)
		Const MAX_TENTATIVAS As Integer = 5
		Dim dbConn As OleDbConnection = Nothing
		Dim dCmd As OleDbCommand = Nothing
		Dim strConnection As String
		Dim cmdText As String
		Dim updateOK As Boolean
		Dim rContador As Integer
		
		Try
			'obtem a string e conexão do arquivo web.config e abre a conexão
			strConnection = ConfigurationManager.ConnectionStrings("dbConnectionString").ConnectionString
			dbConn = New OleDbConnection(strConnection)
			dbConn.Open( )
			'cria um comando SQL update para atualizar o registro no banco de dados
			cmdText = "UPDATE EditProblem " & "SET SectionHeading='" & sectionHeading & "' " &_
             				  "WHERE EditProblemID=" &problemID.ToString( )
			dCmd = New OleDbCommand(cmdText, dbConn)
			'fornece um laço com o bloco try/catch para facilitar a tentativa de atualizar o banco de dados
			updateOK = False
			rContador = 0
			While ((Not updateOK) And (rContador < MAX_TENTATIVAS ))
				Try
     				    dCmd.ExecuteNonQuery( )
       				    updateOK = True
				Catch ex As Exception
      				    rContador += 1
	      			   If (rContador >= MAX_TENTATIVAS) Then
		       	   	   'lança uma nova exceção com a mensagem de contexto informando 
			          	    'o número máximo de tentativas que foram realizadas
				        Throw New Exception("Número máximo de tentativas alcançada", ex)
				End If
			         End Try
		          End While
	           Finally
	  	  'realiza a operação de limpeza
	  	   If (Not IsNothing(dbConn)) Then
			dbConn.Close( )
		    End If
	           End Try
End Sub  | 
| Option Explicit On Option Strict On ''' <summary> ''' Esta classe fornece uma classe de exceção com suporte a mensagem amigáveis ''' </summary> Public Class ExcecaoAmigavelVB Inherits System.ApplicationException 'define variável para copiar a mensasgem amigavel Private mMensagemAmigavel As String = "" '''*********************************************************************** ''' <summary> ''' Fornece o acesso a mensagem a ser exibida de forma amigável ''' message. ''' </summary> Public Property MensagemAmigavel ( ) As String Get Return (mMensagemAmigavel ) End Get Set(ByVal Value As String) mMensagemAmigavel = Value End Set End Property '''*********************************************************************** ''' <summary> ''' Fornece um construtor com suporte a mensagem de erro, uma referencia a ''' a exceção que lançou esta exceção e uma mensagem amigável. ''' </summary> Public Sub New(ByVal message As String, ByVal inner As Exception, _ ByVal MensagemAmigavel As String) 'chama o construtor da classe base MyBase.New(message, inner) mMenagemAmigavel = MensagemAmigavel End Sub 'New End Class | 
Com esses conselhos espero ter contribuído para auxiliá-lo no gerenciamento do tratamento de erros da sua aplicação. Aguarde em breve um artigo sobre tratamento de erros em páginas ASP .NET.
Referências:
José Carlos Macoratti