VB.NET - Programando defensivamente
Errar é humano.
Errar programando é mais humano ainda.
Como temos quase certeza de erros serão cometidos durante o desenvolvimento temos que rastreá-los e remove-los, quando possível.
Acontece que nem todo erro pode ser rastreado ou removido do seu programa. Existem casos nos quais os erros podem acontecer sem que você seja o culpado.
Uma das operações mais básicas e comun, é acessar um arquivo em disco. Parece uma tarefa simples , pois ao acessar um arquivo você supõe que ele esta disponível para você; que ele esta onde você o deixou ; que ele não esta corrompido nem contaminado por um vírus ; mas você já deve estar cansado de saber que as coisas não são tão simples assim, e, que o arquivo pode ter sido movido, apagado, corrompido, contaminado, danificado; e isto vai gerar um erro no seu programa.
Portanto, em uma tarefa simples como a descrita acima você deve adotar procedimentos básicos de verificação para contornar as possíveis causas dos possíveis erros. Você pode então fazer uma lista de tudo o que achar que deve verificar e mesmo assim pode não conseguir prever todos os erros possíveis. Na verdade você não pode se defender contra todos os possíveis erros que possam ocorrer.
È justamente por isto que o Visual Basic .NET lhe oferece o gerenciamento estruturado de exceção - GEE. Vejamos o código para realizar a tarefa descrita acima usando o GEE.
Dim arquivo As String Dim arquivoStream As System.IO.StreamReader Try 'tenta acessar e ler o arquivo teste.txt arquivoStream = System.IO.File.OpenText("teste.txt") arquivo = arquivoStream.ReadLine Catch ex As Exception 'se ocorrer uma exceção exibe a mensagem MessageBox.Show(ex.Message) Finally 'se o arquivo existe então fecha o arquivo If Not arquivoStream Is Nothing Then arquivoStream.Close() End If End Try |
A
estrutura do GEE - Try/Catch/Finally - A parte do código depois da declaração Try é o código que esta sendo tratado quanto a erros - Sé ocorrer um erro a parte Catch do código será executada. - A parte Finally SEMPRE será
executada ocorra erro ou não.
|
Nota: Para saber mais leia os artigos :
A base do GEE é o bloco Try/Catch/Finally - Tentar/Pegar/Finalizar ele substitui as declarações On Error Goto. Portanto se você pretende usar o VB.NET como linguagem de desenvolvimento use o GEE e não mais a estrutura On Error Goto pois ela esta disponível por questão de compatibilidade.(Não existe nada mais feio que um código VB.NET usando On error Goto...)
O GEE trouxe um novo jargão com o qual você deve se habituar. Não existe mais um erro (que bom...) mas uma exceção ; as exceções são lançadas por código mal comportado e o bloco Try/Catch pega a exceção emitida para tratamento.
Funcionamento básico do GEE :
Quando um erro ocorre no seu programa o VB.NET tenta encontrar uma declaração Catch no procedimento atual; se não encontrar nenhuma ele continua buscando através de declarações Catch no que código que chamou o procedimento atual. Esse processo continua por toda a pilha (stack) até que seja encontrado um bloco Catch que possa tratar o erro atual ou até que o recurso de busca atinja o nível mais externo superior do aplicativo. Neste ponto um erro em tempo de execução será gerado e o programa será encerrado.
O Objeto Exception
O objeto exception é base do GEE. O objeto exception básico é o System.Exception (foi usado no exemplo acima).
Este objeto também existe em muitas versões diferentes e mais especializadas que herdam de System.Exception.
No exemplo anterior a exceção que ocorreu poderia ter System.IO.FileNotFoundException se o arquivo não existisse ou System.IO.EndOfStreamException se o arquivo existisse mas não tivesse conteúdo.
Vamos examinar o objeto Exception de perto usando o código acima. Crie um projeto do tipo Windows Application no VS.NET usando a linguagem VB.NET e no evento Load do formulário copie o código acima. A seguir coloque um ponto de interrupção no bloco Catch. Veja abaixo como deverá ficar o código :
Quando você executar o programa deve ocorrer uma exceção, pois o arquivo teste.txt não deve existir na pasta local do aplicativo. É exatamente isto que queremos que ocorra. Quando chegar no ponto de interrupção ative a janela Locals.Vamos então espiar de perto a estrutura de objeto da exceção que pegou usando a Janela Locals.
Abaixo temos a exibição da janela Locals. Estamos interessados nos dados públicos do objeto Exception.
O objeto ex é um objeto do tipo Exception que usamos no código para tratamento das exceções é ele que devemos espiar.
Vejamos o que informações podemos extrair do objeto ex:
MessageBox.Show(ex.Message & vbCrLf & vbCrLf & ex.StackTrace)
Ao executar o programa teremos a seguinte mensagem:
Uma propriedade muito interessante é a propriedade InnerException (exceção interna) que embora não apareça no exemplo acima pode ser usada quando ocorre mais de um erro em uma sucessão rápida. O VB.NET permite empacotar um erro anterior na propriedade InnerException.
Neste nosso exemplo usamos uma rotina genérica de gerenciamento de erro que tratava com qualquer erro que ocorresse. Podemos no entanto identificar tipos específicos de exceções e tratá-las de separadamente. Para fazer isto devemos definir diversas declarações Catch , cada uma destinada a tratar com o tipo de exceção.
Vejamos como podemos fazer isto para o nosso exemplo:
Try 'tenta acessar e ler o arquivo teste.txt arquivoStream = System.IO.File.OpenText("teste.txt") arquivo = arquivoStream.ReadLine Catch ex As System.IO.FileNotFoundException 'se o arquivo não for encontrado exibe a mensagem MessageBox.Show("Arquivo não localizado" & vbCrLf & vbCrLf & ex.StackTrace) Catch ex As System.IO.EndOfStreamException 'se o conteudo do arquivo for inválido exibe a mensagem MessageBox.Show("Conteúdo do arquivo inválido." & vbCrLf & vbCrLf & ex.StackTrace) Catch ex As Exception 'se ocorrer qualquer outra exceção exibe a mensagem MessageBox.Show(ex.Message & vbCrLf & vbCrLf & ex.StackTrace) Finally 'se o arquivo existe então fecha o arquivo If Not arquivoStream Is Nothing Then arquivoStream.Close() End If End Try
|
Então ao escrever o seu código será muito útil você saber quais tipos de exceção pode esperar para assim poder tratá-las de uma forma mais adequada. Você pode ver todas as exceções para um determinado manespace selecionando no Debug a opção Exceptions(CTRL_ALT+E). A janela Exceptions mostra todas as exceções na biblioteca de classe .NET organizadas.
Esta janela pode ser usada como uma ferramenta de depuração muito útil. Podemos usar as opções oferecidas para ajustar individualmente opções de execução para cada tipo de exceção.
Filtragem por condições
Você pode usar o recurso de filtrar o seu código com base em qualquer expressão condicional usando a palavra-chave When. A utilização desta cláusula será útil quando o objeto Exception contiver múltiplos erros. Abaixo um exemplo da utilização da cláusula When.
Dim i As Integer = 10 Dim j As Integer = 0 Dim k As Integer Try k = i \ j Catch exc As Exception When j=0 Console.WriteLine("Não existe divisão por zero") Catch exc As Exception Console.WriteLine("Ocorreu um erro na operação") Finally Beep Console.ReadLine() End Try
|
Um outro exemplo poderia ser feito usando o código a seguir:
Do Dim tentativa As Integer Try ' aqui vai o código que terá o tratamento de erros Catch ex As IO.FileLoadException When tentativa < 3 ' Ao ocorrer a exceção pergunta se quer tentar novamente até o limite de 3 tentativas If MsgBox("Quer tentar novamente ?", MsgBoxStyle.YesNo) = MsgBoxResult.No Then Exit Do End If Catch ex As Exception ' Se ocorrer qualquer outro erro ou o número de tentivas for maior que 3 MsgBox(ex.Message) Exit Do End Try ' incrementa a tentativa tentativa += 1 Loop |
Usando asserções
O VB.NET possui um recurso chamado asserções que força o seu código a testar certas suposições que você crê que estejam ocorrendo para que erros potenciais sejam minimizados.
Asserções são declarações que você garante que são verdadeiras, pois de outro modo há algo errado com o código do seu aplicativo. Ao testar uma asserção e descobrir que ela é falsa , o VB.NET enviará uma mensagem de erro com uma pilha de código de diagnóstico e lhe dará a opção de interromper a execução ou de ignorar o problema e prosseguir.
As asserções só funcionam em modo de depuração e quando você compila e distribui o seu programa todas as asserções desaparecem. Com isto as asserções tem o nítido objetivo de ajudá-lo a localizar problemas durante o teste do seu aplicativo.
Para incluir uma asserção em seu código , use o método Assert a classe Debug.
Vamos supor que você deve informar o caminho e nome de um arquivo a ser acessado em uma caixa de texto. Podemos usar asserções conforme o código a seguir :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim arquivo As String Dim arquivoStream As System.IO.StreamReader Debug.Assert(TextBox1.Text = "") Try arquivoStream = System.IO.File.OpenText(TextBox1.Text) arquivo = arquivoStream.ReadLine Catch ex As System.IO.FileNotFoundException MessageBox.Show("Arquivo não localizado" & vbCrLf & vbCrLf & ex.StackTrace) Catch ex As System.IO.EndOfStreamException MessageBox.Show("Conteúdo do arquivo inválido." & vbCrLf & vbCrLf & ex.StackTrace) Catch ex As Exception MessageBox.Show(ex.Message & vbCrLf & vbCrLf & ex.StackTrace) Finally If Not arquivoStream Is Nothing Then arquivoStream.Close() End If End Try End Sub
|
Se o nome do arquivo informado estiver vazio iremos obter a mensagem abaixo:
Como as asserções depuradas são completamente removidas da versão final do seu programa não se preocupe que elas não vão tornar o seu programa mais lento. Tome cuidado , no entanto , em não permitir que uma asserção chame um procedimento que modifique um valor de alguma variável do seu programa , pois ai sim você terá grandes dores de cabeça com o seu código.
Além disto você pode usar também o rastreio de asserções. Neste caso o rastreio permanece no programa final . Geralmente você não irá precisar fazer isto em seu programa local mas pode usar o rastreio em um programa remoto. Exemplo de rastreio de asserção:
Trace.Assert(TextBox1.Text = "")
Como você pode usar estes conceitos na prática ?
Muitas vezes o cliente ou usuário do seu programa não sabe explicar como ou quando um determinado erro foi gerado em sua aplicação.
Você pode criar um arquivo de registro no seu aplicativo de forma que ele capture informações de sequência de execução do seu programa e grave em um arquivo . Quando ocorrer algum problema com seu aplicativo você somente terá que solicitar ao seu cliente que envie o arquivo de registro para analisar o trace gerado pela aplicação e descobrir o que causou o erro.
Para usar o rastreio você usa a classe Trace do namespace System.Diagnostics e para capturar as informações para um arquivo você usa um listener que será um arquivo texto que ficará recebendo todas as saídas do rastreio. Vejamos o exemplo abaixo :
Primeiro devemos criar o arquivo que será usado como registro do Trace. Abaixo criamos o Listener chamado log.txt
Dim arqTrace As New TextWriterTraceListener(File.Create("log.txt")) Trace.AutoFlush() = True Trace.Listeners.Add(arqTrace) |
Agora podemos usar os métodos da classe Trace para escrever o arquivo texto. Vamos escrever o trace na código exemplo que acessa um arquivo :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim arquivo As String Dim arquivoStream As System.IO.StreamReader Trace.WriteLine("Iniciando aplicação") Trace.Indent() Trace.WriteLine("Acessando o arquivo " & TextBox1.Text) Try arquivoStream = System.IO.File.OpenText(TextBox1.Text) arquivo = arquivoStream.ReadLine Catch ex As System.IO.FileNotFoundException Trace.WriteLine("Erro ao acessando o arquivo " & TextBox1.Text) MessageBox.Show("Arquivo não localizado" & vbCrLf & vbCrLf & ex.StackTrace) Catch ex As System.IO.EndOfStreamException MessageBox.Show("Conteúdo do arquivo inválido." & vbCrLf & vbCrLf & ex.StackTrace) Catch ex As Exception MessageBox.Show(ex.Message & vbCrLf & vbCrLf & ex.StackTrace) Finally Trace.WriteLine("Encerrando aplicação. Executando finally.") Trace.Unindent() Trace.Close() If Not arquivoStream Is Nothing Then arquivoStream.Close() End If End Try End Sub
|
O arquivo log.txt será gerado na pasta bin da aplicação e terá o seguinte conteúdo:
Iniciando aplicação
Acessando o arquivo
Encerrando aplicação. Executando finally.
Com isto você pode gerar um arquivo de log de monitoração para a sua aplicação.
Uma outra forma de monitorar a sua aplicação e usar o método Writeline da classe Debug para imprimir informações de diagnóstico na janela OutPut. Exemplo:
Debug.Writeline(" informação de diagnostico...")
Mas atenção , para que garantir que o rastreio da sua aplicação esteja ativo faça o seguinte :
Com os conceitos tratados neste artigos , mesmo que o seu código não fique totalmente livre de erros , com certeza ele será mais robusto e mais confiável. E quando os problemas surgirem você estará capacitado a resolvê-los com mais rapidez.
Ate o próximo artigo VB.NET ...
Veja os
Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique
e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências: