Debug do pato de borracha

Figura 1: Debug do pato de borracha

A figura acima ilustra uma das melhores técnicas existentes de debug, e funciona para qualquer linguágem. Ela é conhecida como a técnica de debug do pato de borracha (http://en.wikipedia.org/wiki/Rubber_duck_debugging) .

O método é descrito assim:

  1. Peça, pegue emprestado, compre, faça você mesmo ou de alguma outra forma, obtenha um pato de borracha.
  2. Coloque o pato sobre sua mesa de trabalho e diga a ele que você vai apenas explicar alguns trechos de código para ele.
  3. Explique ao pato o que o código deveria fazer. Explique com o máximo de detalhes, linha a linha.
  4. Em algum ponto da explicação, você vai perceber que algo do que você está dizendo é mentira. O que você diz que o código deveria fazer, não é realmente o que ele faz. O pato continuará sentado, sereno, contente pelo conhecimento avançado que ele tem de programação ter te ajudado a descobrir o problema com o código.

Todas as empresas listadas na FORBES utilizam esse método, acredite, funciona sempre. Se você não tiver um pato de borracha, pode utilizar um amigo ou pedir 5 minutos para a primeira pessoa que passar perto de você.

Esse é o método do pato de borracha. Embora seja muito efetivo, algumas vezes são necessários truques extras para facilitar a vida do querido pato. Então, agora que você já conhece o método principal, vamos aos métodos que vez por outra quebram um galho até você encontrar o pato.

Para exemplificar as técnicas discutidas abaixo, será utilizado um código muito simples. Crie um projeto de uma única view e na implementação desta view utilize o seguinte código:

Listagem 1: Código com erro proposital


- (void)viewDidLoad
{
    [super viewDidLoad];

    [self performSelector:@selector(metodoInexistente:)];
}

O código acima chama o método metodoInexistente em self, que é um UIViewController. Este método não está implementado, então quando a execução do app chegar a este ponto, o app vai travar e o programador verá uma tela mais ou menos como a da Figura 2 abaixo.

Mensagem de debug do travamento do app

Figura 2: Mensagem de debug do travamento do app

O programa de exemplo é simples e é possível com esta mensagem corrigir o problema facilmente. Mas repare que a execução do programa continuou e como a exceção não foi tratada, houve um encerramento forçado do app e terminamos com o ponteiro no return do mais. Se fosse um app mais complexo, fatalmente agora o desenvolvedor estaria perdido sem muitas pistas do que aconteceu.

Dica 0 – Breakpoints

Essa é a dica 0, pois a maioria dos programadores já deve ter utilizado breakpoints. Resumindo, breakpoints são pontos de parada no código, usados para saber se uma parte do código está sendo executada ou para examinar melhor o fluxo de execução de uma determinada parte do código.

Para inserir um breakpoint em uma linha de código, basta clicar na coluna da esquerda ao lado da linha desejada ou usar o atalho : Command+\ .

Para desabilitar o breakpoint, usar o atalho Command+Y ou clicar com o botão esquerdo do mouse sobre o breakpoint.

Para remove-lo, basta repetir o atalho Command+\ ou arrastar o breakpoint para fora da barra.

Uso de breakpoints - linha 19 inativo e linha 21 ativo

Figura 3: Uso de breakpoints - linha 19 inativo e linha 21 ativo

Dica 1 – Breakpoint de Exceção

O uso de breakpoints como da dica 0 é muito básico e eles podem ajudar muito mais do que isso na hora do debug.

Um breakpoint de muita utilitade é o chamado breakpoint de exceção. Esse breakpoint não é associado a uma linha de código específica. Ele será disparado toda vez que houve uma exceção no app.

Para criar esse breakpoint, basta ir na aba de breakpoint, clicar no botão adicionar e selecionar breakpoint de exceção. Para evitar alguns disparos indesejados desse recurso, é interessante setar o tipo de exceção capturada para Objective-C apenas.

A Figura 4 mostra o passo a passo para ir à aba de breakpoints e adicionar o breakpoint de exceção.

A Figura 5 mostra o final do processo, como escolher que o breakpoint seja disparado apenas em exceções da linguagem Objective-C.

Se a opção de capturar apenas excessões do Objective-C não for selecionada, é possível que este breakpoint seja disparado em comportamentos normais de módulos criados em C/C++ e etc. Principalmente no uso de bibliotecas do Core Audio.

Após criado, caso se o app for executado novamente, a mensagem de erro será exibida exatamente na linha que a gerou e será mais fácil identificar os problemas. A Figura 6 ilustra o travamento do app agora com o breakpoint de exceção sendo disparado.

Criando o breakpoint de exceção

Figura 4: Criando o breakpoint de exceção

Criando o breakpoint para exceções em Objective-C

Figura 5: Criando o breakpoint para exceções em Objective-C

Travamento do app com disparo do breakpoint de exceção

Figura 6: Travamento do app com disparo do breakpoint de exceção

Dica 2 – Breakpoins Compartilhados

Quando se trabalha em equipe, algumas vezes é interessante compartilhar breakpoints com o time, de forma que outra pessoa possa debugar o seu código.

Os breakpoins criados no Xcode podem ser compartilhados com outros membros do time (via svn/git) quando setados como breakpoins compartilhados.

Para fazer isso, basta clicar com o botão direito no breakpoint desejado e selecionar “Share Breakpoint”.

Esse procedimento é ilustrado pelo item 1 da Figura 7.

Breakpoints compartilhados e de usuários

Figura 7: Breakpoints compartilhados e de usuários

Dica 3 – Breakpoint de Usuário

Breakpoints de usuário são aqueles breakpoints que uma vez criados, estarão presentes em todos os projetos que forem criados localmente pelo mesmo usuário.

O breakpoint de exceção por exemplo, é um caso interessante de ser transformado em breakpoint de usuário, pois uma vez criado, todo novo projeto já vai trazê-lo por padrão.

Para transformar um breakpoint em breakpoint de usuário, basta clicar no breakpoint desejado com o botão direito, selecionar “Move Breakpoint To“ e “User“. Esse procedimento é exemplificado no item 2 da Figura 7.

Por padrão, todo breakpoint criado pertence ao projeto no qual foi criado. Para transformar um breakpoint de usuário em breakpoint de um projeto específico, basta clicar com o botão direito, selecionar “Move Breakpoint To” e “Projeto XYZ“.

Verificar no item 2 da Figura 7 que existe o User e o AXDebug, que seria o projeto em questão.

Outro uso interessante para breakpoints de usuário são os breakpoints simbólicos, que ficam como sugestão de pesquisa complementar para os leitores.