RSS feed
Dicas de Debugging (Depuração de Código) no Visual Studio 2010 - ScottGu's Blog em Português

Dicas de Debugging (Depuração de Código) no Visual Studio 2010


Este é o vigésimo sexto de uma série de posts que estou escrevendo sobre o próximo lançamento do VS 2010 e .NET 4.

O post de hoje aborda algumas dicas de depuração de código úteis que você pode usar com o Visual Studio. Meu amigo Scott Cate (que já escreveu dezenas de ótimas dicas e truques do VS aqui [em Inglês]) recentemente destacou as mesmas para mim como boas dicas que a maioria dos desenvolvedores que usam o Visual Studio parecem não ter conhecimento (apesar da maioria já estar presente no produto há algum tempo). Esperançosamente este post o ajudará a descobri-las se você ainda não estiver tirando vantagem delas. Elas são fáceis de aprender, e podem ajudar você a economizar bastante tempo.

Executar Até o Cursor (Ctrl + F10)

Muitas vezes vejo pessoas depurando aplicações atingindo um breakpoint (ponto de interrupção) no início da aplicação e, em seguida, a pessoa repetidamente usa as teclas F10/F11 para percorrer o código até chegar ao local específico que ela realmente quer investigar.  Em alguns casos, elas estão observando cuidadosamente cada instrução ao longo do caminho (neste caso, usar F10/F11 faz sentido). Muitas vezes, porém, as pessoas estão apenas tentando avançar rapidamente para a linha de código que elas realmente estão interessadas - e nesse caso usando F10/F11 não é a melhor maneira de fazer isso.

Ao invés disso, você pode querer tirar proveito do recurso "Run to Cursos" (Executar Até o Cursor) que o debugger (depurador) suporta. Basta posicionar o cursor do teclado na linha do seu código que você deseja que a aplicação execute e, em seguida pressione as teclas Ctrl + F10 juntas. Isto irá executar a aplicação até a localização da linha e, em seguida, interromperá o depurador - poupando-o de ter de apertar várias vezes as teclas F10/F11 para chegar lá. Isso funciona mesmo se a linha de código que você pretende executar estiver em um método ou uma classe separada daquela que você está atualmente depurando.

Breakpoints Condicionais

Outra coisa comum que frequente vemos em estudos de usabilidade são os casos onde os desenvolvedores definem breakpoints, executam a aplicação, tentam alguns valores de entrada, atingem um breakpoint, e manualmente verificam se alguma condição é true (verdadeira), antes de decidir se investigam mais ou não. Se o cenário não corresponde ao que eles estão interessados, eles pressionam a tecla F5 para continuar a execução da aplicação, tentam outros valores de entrada, e repetem o processo manualmente.

Os breakpoints condicionais do Visual Studio fornecem uma maneira muito, muito mais fácil para lidar com esse tipo de situação. Os breakpoints condicionais permitem que você interrompa o depurador somente se alguma condição específica que você setar seja atingida.  Eles ajudam você a evitar a inspeção manual/re-execução de sua aplicação, e tornam todo o processo de depuração muito menos manual e tedioso.

Como Habilitar um Breakpoint Condicional

Configurar um breakpoint condicional é realmente fácil. Pressione a tecla F9 no seu código para definir um breakpoint em uma linha específica:

imagem

Então clique com o botão direito do mouse no "círculo vermelho", à esquerda do editor e selecione a opção "Condition..." (Condição) no menu de contexto:

imagem

Isso abrirá uma janela de diálogo que te permite indicar que o breakpoint só deve ser atingido, se alguma condição for verdadeira. Por exemplo, podemos indicar que só queremos interromper o depurador se o tamanho da lista local paginatedDinners for inferior a 10 escrevendo a expressão de código a seguir:

imagem

Agora, quando eu re-executar a aplicação e fizer uma pesquisa, o depurador somente será interrompido se eu realizar uma pesquisa que retorne menos de 10 dinners (jantares). Se houver mais de 10 jantares, o breakpoint não será atingido.

Recurso Hit Count (Contagem de Hits)

Às vezes você só quer interromper a execução da aplicação em uma condição na qual a enésima vez é verdadeira. Por exemplo: somente interromper a aplicação na quinta vez em que menos de 10 jantares forem retornados em uma pesquisa.

Você pode ativar este recurso clicando com o botão direito do mouse em um breakpoint e selecionando o comando do menu de contexto "Hit count...".

imagem

Isso abrirá uma janela de diálogo que lhe permite indicar que o breakpoint somente será atingido na enésima vez que uma condição for atendida, ou a cada N vezes que a condição for verdadeira, ou toda vez após N ocorrências:

imagem

Filtragem por Máquina/Thread/Processo

Você também pode clicar com o botão direito do mouse em um breakpoint e selecionar a opção "Filter..." (Filtro) no menu de contexto para indicar que um breakpoint deve somente ser atingido se o mesmo ocorrer em uma máquina específica, ou em um processo específico, ou em uma thread específica.

TracePoints (Pontos de Rastreamento) - Ações Personalizadas Quando Um BreakPoint For Atingido

Um recurso de depuração que muita gente não conhece é a capacidade de usar TracePoints (em Inglês). Um TracePoint é um breakpoint que possui uma ação personalizada que é disparada quando o breakpoint é atingido. Este recurso é particularmente útil quando você quer observar comportamento dentro de sua aplicação, sem interromper o processo de depuração.

Vou usar uma simples aplicação Console para demonstrar como podemos ser capazes de tirar proveito dos TracePoints. A seguir está uma implementação recursiva da sequência de Fibonacci:

imagem

Na aplicação acima, estamos usando Console.WriteLine() para escrever o valor final da seqüência de Fibonacci para um valor de entrada específico. O que aconteceria se quissemos observar a sequência recursiva de Fibonacci em ação ao longo do processo dentro do depurador - sem realmente interromper a execução da aplicação? TracePoints podem nos ajudar a fazer isso facilmente.

Configurando um TracePoint

Você pode ativar um TracePoint usando a tecla F9 para definir um breakpoint em uma linha de código, e em seguida clicar com o botão direito do mouse no breakpoint e escolher a opção "When Hit..."(Quando Atingido...) no menu de contexto:

imagem

Isso fará com que a seguinte janela de diálogo apareça - a qual te permite especificar o que deve acontecer quando o breakpoint for atingido:

imagem

Acima, nós especificamos que queremos imprimir uma mensagem de rastreamento a qualquer momento em que a condição do breakpoint for atendida/verdadeira. Observe que nós especificamos que queremos imprimir o valor da variável local "x" como parte da mensagem. As variáveis locais podem ser referenciadas usando a sintaxe {nomeDaVariavel}. Há também comandos nativos (como $CALLER, $CALLSTACK, $FUNCTION, etc) que podem ser utilizados para imprimir valores de saída comuns dentro de suas mensagens de rastreamento.

Acima nós também marcamos a caixa de seleção "continue execution" (continuar a execução) na parte inferior da janela - o que indica que não queremos que a aplicação seja interrompida pelo depurador. Ao invés disso, continuaremos executando a aplicação - a única diferença é que a nossa mensagem de rastreamento customizada será mostrada na tela a cada vez em que a condição do breakpoint for atendida.

E agora, quando executarmos a aplicação, veremos que nossas mensagens de rastreamento customizadas aparecerão automaticamente na janela de "output" (saída) do Visual Studio - o que nos permite acompanhar o comportamento recursivo da aplicação:

imagem

Você pode, alternativamente, acoplar um rastreador ouvinte customizado em sua aplicação - caso em que as mensagens que você imprimir a partir dos TracePoints serão encaminhadas a ele, ao invés de serem enviadas para a janela de saída do VS.

TracePoints - Executando uma Macro Customizada

Em uma palestra que dei semana passada em Londres, alguém na plateia perguntou se era possível imprimir o valor de todas as variáveis locais quando um TracePoint fosse atingido. 

Esse recurso não é nativo no Visual Studio - mas pode ser ativado ao escrevermos uma macro no Visual Studio e, em seguida configurando um Tracepoint para chamar a macro quando este for atingido. Para permitir isso, abra o IDE de Macros no Visual Studio (Ferramentas->Macros->IDE para Macros). Em seguida, sob o nó MyMacros (Minhas Macros) no Project Explorer, selecione um módulo ou crie um novo (por exemplo: adicione um chamado "UsefulThings" [CoisasUteis]). Em seguida, cole o seguinte código de macro VB no módulo e salve o mesmo:

   Sub DumpLocals()

        Dim outputWindow As EnvDTE.OutputWindow

        outputWindow = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput).Object

 

        Dim currentStackFrame As EnvDTE.StackFrame

        currentStackFrame = DTE.Debugger.CurrentStackFrame

 

        outputWindow.ActivePane.OutputString("*Dumping Local Variables*" + vbCrLf)

        For Each exp As EnvDTE.Expression In currentStackFrame.Locals

            outputWindow.ActivePane.OutputString(exp.Name + " = " + exp.Value.ToString() + vbCrLf)

        Next

   End Sub

O código de macro acima percorre o quadro atual da pilha e despeja todas as variáveis locais na janela de saída.

Usando nossa Macro DumpLocals customizada

Podemos, então, aproveitar a nossa macro "DumpLocals" customizada utilizando a aplicação de uma simples adição como a seguir:

imagem

Usaremos a tecla F9 para definir um breakpoint na instrução de retorno dentro do nosso método "Add" mostrado acima. Vamos, então, clicar com o botão direito do mouse no breakpoint e selecionar a opção "When Hit..." no menu de contexto:

imagem

Isso abrirá a janela de diálogo a seguir. Ao contrário de antes, onde usamos a opção da caixa de seleção "Print a message" (Imprimir uma mensagem) e manualmente especificamos as variáveis que queríamos na saída, desta vez nós vamos selecionar a opção da caixa de seleção "Run a macro" (Executar uma macro) e apontaremos para a macro customizada UsefulThings.DumpLocals que criamos acima:

imagem

Vamos manter a caixa de seleção "Continue execution" selecionada de modo que o programa continuará rodando, até mesmo quando os nossos TracePoints forem atingidos.

Executando a Aplicação

E agora, quando nós pressionamos a tecla F5 e executamos a aplicação, veremos o seguinte resultado aparecer na janela de saída do Visual Studio quando o nosso método Add for chamado. Observe como a macro está listando automaticamente o nome e o valor de cada variável local quando o TracePoint é atingido:

imagem

Resumo

O depurador de código do Visual Studio é incrivelmente rico. Eu recomendo que você separe algum tempo para realmente aprender todos os seus recursos. As dicas e truques acima são apenas algumas dos muitos recursos que o depurador oferece e que a maioria das pessoas desconhecem.

Eu já escrevi sobre outras Melhorias no Depurador de Código do VS 2010 (em Inglês) (incluindo fixação de DataTip, Importação/Exportação de breakpoints, Preservando Variáveis de Último Valor e muito mais). Eu escreverei mais posts no futuro sobre o novo suporte do VS 2010 para Intellitrace e Depuração de Arquivos de Dump. Estes recursos fornecem muitas novas capacidades quem podem tornar a depuração de aplicações (inclusive aquelas em ambientes de produção) muito mais fácil e mais poderosa.

Também certifique-se de verificar a Série de Dicas e Truques do Visual Studio 2010 (em Inglês) escrita por Scott Cate para aprender mais sobre como tirar um melhor proveito do Visual Studio. Ele tem um conjunto de vídeos e posts gratuitos que são absolutamente impressionantes.

E também verifique a ótima série de posts com Dicas e Truques do Depurador de Código do Visual Studio (em Inglês) escrita por Jim Griesmer. Ele tem um monte de boas dicas e truques que você pode aproveitar.

Espero que ajude,

Scott

PS Além do blog, eu também estou agora utilizando o Twitter para atualizações rápidas e para compartilhar links. Siga-me em: twitter.com/ScottGu

 

Texto traduzido do post original por Leniel Macaferi.

Published Wednesday, August 18, 2010 11:48 PM by Leniel Macaferi

Comments

No Comments