Se você está “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 está 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#:
VB.NET
Private Sub Rotina( )
Try
'Codigo a ser tratado
Catch exc As Exception
'tratamento de erro
Finally
'operação de limpeza
End Try
End Sub
C#
private void Rotina( )
{
try
{
// Codigo a ser tratado
}
catch (Exception exc)
{
// tratamento de erro
}
finally
{
// operação de limpeza
}
}
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:
Nota: Lembre-se de que o .NET Framework não fecha as conexões de banco de dados, arquivos, etc quando erros ocorrem. Esta responsabilidade é do programador (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.
2- Erros podem ser recuperados durante a execução do código de uma rotina/método?
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.
3- Uma informação importante pode ser anexada à exceção?
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 está sendo feito em 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:
VB.NET
Catch ex As Exception
Throw New Exception("mensagem do contexto", ex)
catch (Exception ex)
{
throw (new Exception("mensagem do contexto", ex));
}
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 em 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 visto 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
Abaixo temos um exemplo de uma classe que efetua o tratamento específico com mensagem de erros mais amigável:
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:
VB.NET e o tratamento de erros
Tratamento e personalização de erros
Tratamento de exceções de banco de dados com Try/Catch
VB.NET – Programando defensivamente
VB.NET – Tratando exceções de banco de dados
VB .NET – tratamento de erros usando o bloco try-catch-finally.
Criando exceções personalizadas