.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