Delphi - Segredos e Solues

CAPTULO 8

Ferramentas e Tcnicas para Teste e Depurao

Assim que um programa se torna de alguma forma complexo, no importa com
que cuidado voc o esboa ou com que cuidado o planeja, ele
provavelmente no far o que  voc espera - de incio. Essa  uma lio
que os programadores so obrigados a aprender, pelo mtodo doloroso,
repetidas vezes. Parece que por mais que voc tente  fazer seu programa
bem robusto, algum, de alguma forma, encontrar uma maneira de provocar
uma quebra no programa. Uma meta realista no  um programa perfeito,
mas um que  o mais confiveis possvel (ou robusto)  um que, mesmo
quando quebra, tenta salvar o trabalho do usurio antes de encerrar.

Embora os manipuladores de excees (veja o captulo anterior) possam
ajudar bastante, depois que voc escrever um programa, ainda assim ser
obrigado a test-lo  quanto a existncia de "bugs" (defeitos). Assim que
o processo de teste convenc-lo de que h defeitos a espreita, voc
precisa encontr-los e depois erradic-los.  O Delphi integrou muitas
ferramentas no ambiente de desenvolvimento para ajud-lo com essa
tarefa, e este captulo vai lhe mostrar como utiliz-las.
        Evidentemente que, antes de tentar testar e depurar um programa,
voc deve fazer primeiro uma cpia em papel do cdigo-fonte do programa.
Voc tambm pode  querer uma cpia das especificaes dos formulrios no
formato ASCII (veja o Captulo 3) pa e de seus componentes esto
conforme voc espera.
        Finalmente, este captulo fornece tcnicas para melhorar o
desempenho de seus programas que realizam o trabalho mas que
dificilmente introduzem novos defeitos  (tentar otimizar em demasia um
cdigo  uma das fontes mais comuns de defeitos em progr programao.

As Ferramentas de Depurao e o Que Elas Fazem

O menu Run contm as ferramentas necessrias para teste e depurao. A
maioria delas tambm pode ser encontrada na SpeedBar. Tipicamente, as
ferramentas de depurao  so utilizadas quando o programa 
temporariamente suspenso (no modo Stopped). A Tabela 8.1 relaciona as
ferramentas de depurao que voc pode utilizar.

DICA: A SpeedMenu do Code Editor permite-lhe ter acesso a muitas das
ferramentas de depurao da Tabela 8.1. D um clique no boto direito do
mouse em uma pgina  de cdigo para exibir sua SpeedMenu.

Tabela 8.1 As Ferramentas de Depurao

        Ferramenta - Equivalente do Teclado - Funo

        Run - ALT+R+R(F9) - Inicia/Reinicia o programa
        Parameters - ALT+R+P - Especifica parmetros da linha de
comando.
        Step Over - ALT+R+S(F8) - Funciona como o procedimento de
exceo da ferramenta Trace Into e as chamadas de funo so tratadas
comoum passo.
        Trace Into - ALT+R+T(F7) - Movimenta-se pelo programa uma
declarao por vez.
        Run to Cursor - ALT+R+C(F4) - Executa o programa at a posio
do cursor.
        Show Execution Point - ALT+R+H - Mostra a linha que ser
processada em seguida.
        Program Pause - ALT+R+G - Interrompe o programa.
        Program Reset - ALT+R+E(CTRL+F2) - Termina o programa.
        Add Watch - ALT+R+W(CTRL+F5) - Exibe a caixa de dilogo Watch
Properties, onde voc pode criar e editar relgios.
        Add Breakpoint - ALT+R+B - Interrompe o programa imediatamente
antes que a linha seja executada
        Evaluate/Modify - ALT+R+V(CTRL+F7) - Exibe a caixa de dilogo
Evaluate/Modify, onde voc pode avaliar ou modificar uma expresso
existente.

 Projetando Programas para Facilitar o Teste

Os programas longos e complexos nunca so fceis de testar, mas escrever
os programas de determinadas formas facilita a tarefa. (Esses mtodos
tambm tornam a programao  mais fcil de uma maneira geral.) Ao
dividir o programa em pedaos administrveis onde cada um realiza uma
nica tarefa, voc pode tornar o seu teste muito mais  fcil. Depois que
terminar cada objeto, procedimento ou funo, voc pode test-lo
rigorosamente para ver se ele consegue tratar todos os parmetros
possveis que  possam ser passados para ele. Utilizando objetos
(reutilizveis) rigorosamente depurados que encapsulam as propriedades e
mtodos que voc precisa (veja o Captulo  6),  possvel economizar
bastante trabalho de sua parte.
        Em seguida, combine todos os procedimentos e objetos que voc
verificou e teste tudo novamente. Em alguns casos, um procedimento ou
funo pode precisar  de resultados de um trecho ainda no escrito para
ser processado. Nesse caso, a melhor tcnic onde necessrio, no lugar de
resultados de procedimento se funes ainda no escritos. (A questo 
ter sempre um programa que faz alguma coisa - mesmo que seja  apenas
para dizer o que  que ele vai fazer.) Defina o procedimento ou funo,
mas preencha-o de constantes em vez de deixar que faa alguma coisa. As
chamadas do  procedimento ainda funcionaro da mesma forma, mas
recebero apenas as constantes dos stubs. Em seguida, voc pode mudar as
constantes para variar os testes.
       Suponha agora que voc tenha eliminado os erros evidentes de
sintaxe e consiga fazer o programa funcionar - segundo um estilo. Mas,
ao testar o programa,  voc percebeu que ele no funciona como deveria;
ele contm defeitos que voc precisa isolar  Voc tem que encontr-los e
determinar seu tipo.
       H essencialmente dois tipos de erros: de processamento e
lgicos. Exemplo de um erro de processamento  tentar abrir um arquivo
que no existe.

DICA: Ao depurar um programa pela primeira vez quanto a erros de
processamento, voc pode querer colocar os manipuladores de excees
entre colchetes (como se fossem  comentrios).

Erros lgicos - so uma famlia ampla que engloba todos os erros
resultantes de um desentendimento a respeito do funcionamento de um
programa. Isso inclui procedimentos  que no se comunicam adequadamente
e erros de lgica internos ao cdigo.

Erros Lgicos

Para se livrar de erros lgicos sutis, voc tem de isol-los - isto ,
encontrar a parte do programa que est provocando o problema. Se voc
seguiu a abordagem modular,  a sua tarefa  bem mais fcil. Os elementos
so mais manejveis, assim, encontrar os erros significa que o palheiro
no  to grande. Do mesmo modo, se voc tenta  encapsular um
comportamento que ocorre normalmente em um objeto configurado, pode
focalizar a sua ateno naquele objeto durante a depurao.
       Se voc testou o programa  medida que o desenvolvia, ento j
deve saber em que objeto, procedimento ou funo se encontra o problema.
Normalmente  mais  fcil determinar com exatido qual  o objeto,
procedimento ou funo problemticos se voc  noo da lgica do
programa. Se o programa no  seu ou voc esperou at o seu "trmino",
poder utilizar as seguintes tcnicas para verificar os elementos um por
vez.
       Presuma que voc escolheu um procedimento de objeto ou funo
defeituosos para testar. H apenas trs possibilidades:
        *O que est entrando est errado - aquilo com o que voc
alimentou o objeto, procedimento ou funo o est confundindo.
        *O que est saindo est errado - o objeto, o procedimento ou a
funo est enviando informao errada a outras partes do programa (por
exemplo, poder estar  causando efeitos colaterais no-previstos).
        *Alguma coisa dentro do objeto, do procedimento ou da funo
est errada (por exemplo, ele est realizando uma operao um nmero
excessivo de vezes, ou  no est limpando a tela no momento certo).

        Nos dois primeiros casos, o erro pode ser rastreado em qualquer
um ou a todos os seguintes itens: os parmetros que voc envia ao
procedimento ou funo  (ou os mtodos do objeto), aquilo que voc
atribuiu aos parmetros ou s propriedades, ou ao  da funo ou do
procedimento.
       Como voc decide com qual situao est tratando? Primeiro, 
difcil imaginar um objeto, um procedimento ou funo curtos escritos
corretamente que voc  no possa analisar em um pedao de papel para
determinar o que deveria acontecer na maioria d ser um computador".
(Isso significa que voc no deve fazer nenhuma suposio alm daquilo
que o computador deveria saber naquele momento; no presuma que as
variveis  tm certos valores a no ser que possa convencer a si mesmo
que elas tm esses valores.) Agora voc precisa verificar se as funes,
os objetos e os procedimentos  esto fazendo o que deveriam fazer.

Acrescentando Informaes de Depurao

Para utilizar o depurador integrado, voc tem de compilar seu programa
para que haja uma maneira do depurador conectar o executvel com seu
cdigo fonte. Isso normalmente   chamado de informao de depurao
simblica. Informao de depurao simblica  uma tabela simblica que
liga o cdigo fonte de seu programa ao cdigo de mquina  gerado pelo
compilador. Por padro, o Delphi gera informao de depurao. Voc pode
ativar/desativar a informao de depurao verificando as opes de
depurao  na pgina Options|Project Compiler.
       Se voc quer utilizar o Turbo Debugger para Windows, ter que
incluir uma informao de depurao simblica em seu arquivo .EXE final.
Verifique a caixa de  escolha de informao de depurao Include TDW na
pgina Options|Project Linker. Entretanto o tamanho de seu arquivo
executvel e far o aplicativo ser processado mais devagar, de maneira
que voc deve se lembrar de fazer sua compilao final com a informao
de depurao simblica desligada.

NOTA: O Turbo Debugger para Windows  um produto independente que
acrescenta muitos recursos de depurao especializados s facilidades de
depurao internas do  Delphi (como pontos de parada de hardware). Ele
no  abordado neste livro. Para mais informaes a respeito desse
produto, consulte a ajuda on-line ou a documentao  fornecida para o
Turbo Debugger.

A Caixa de Dilogo Evaluate/Modify

A maioria das linguagens de programao tem uma maneira para testar as
declaraes, as variveis e expresses do programa, e o Delphi no 
nenhuma exceo. O Delphi  utiliza a caixa de dilogo Evaluate/Modify,
mostrada na prxima ilustrao.
        Para trazer a caixa de dilogo Evaluate/Modify at o primeiro
plano, utilize o menu Run. A caixa de dilogo Evaluate/Modify  modal
(voc tem de fechar a  caixa de dilogo para voltar a trabalhar no
ambiente de projeto) e pode ser movida. Se voc  o Delphi responde
rapidamente com um 4. Voc pode utilizar os comandos de edio comuns do
Microsoft Windows para modificar o contedo de uma linha na caixa de
dilogo  Evaluate/Modify. Voc tambm pode cortar e colar entre linhas.
Lembre-se, porm, de que, ao pressionar ENTER, o Delphi tenta processar
a linha.
        Lembre-se tambm de que voc pode sempre reexecutar linhas
anteriores na caixa de dilogo Evaluate/Modify selecionando a linha da
caixa combinada suspensa  Expression e pressionando ENTER.

Mais Sobre Depurao na Caixa de Dilogo Evaluate/Modify

A caixa de dilogo Evaluate/Modify facilita o teste de uma varivel ou
de uma expresso quanto a seus efeitos em certos valores (por exemplo,
para ver se os resultados  conferem com os clculos manuais). Na maioria
das vezes, voc utilizar a caixa de dilogo Evaluate/Modify para
examinar o valor atual das constantes, variveis  ou expresses. Para
ver o valor de uma varivel, basta colocar uma expresso na parte de
edio da caixa combinada suspensa Expression.
       Para mudar o valor de uma varivel depois de dar um clique em
Evaluate, coloque o cursor na caixa combinada suspensa New Value (aquela
embaixo da caixa Result)  e entre com o valor novo. (Ela estar
desativada, conforme mostrado na ilustrao, se v ao modificar valores
para evitar efeitos colaterais indesejveis.

NOTA: Qualquer mudana que voc fizer na caixa de dilogo
Evaluate/Modify no afeta o cdigo-fonte nem o programa compilado.

        Se quiser fazer em seu projeto as alteraes feitas na caixa de
dilogo Evaluate/Modify, volte ao Code Editor e mude o cdigo-fonte de
acordo. Em seguida  compile o projeto novamente.

Trace Into

Com freqncia, quando voc percorreu um programa manualmente, vai
querer que o computador percorra o mesmo exemplo, uma linha de cdigo
por vez. O Delphi permite-lhe  executar uma declarao por vez em seu
programa - um processo chamado de passo a passo - pressionando
repetidamente F7 ou o cone das ferramenta Trace Into na SpeedBar.
(Evidentemente, se o Delphi est esperando que acontea um evento, no
haver nenhuma declarao para executar.) Se o ponto de execuo est
localizado em uma chamada  a uma funo que no foi compilada com
informao de depurao, ento Trace Into trata o bloco de cdigo como
uma declarao e destaca a declarao que segue a chamada   funo.
       Quando o passo a passo  utilizado pela primeira vez, a primeira
declarao executvel do programa  destacada na janela Code Editor.
(Normalmente, a primeira  declarao estar no manipulador OnCreate do
formulrio, se houver um.) Cada acionamento e ilumina a prxima
declarao que ser executada. Como voc pode imaginar, percorrer um
programa passo a passo  ideal para rastrear o fluxo lgico de um
programa  atravs de estruturas e procedimentos de deciso.
       Sempre que um procedimento  chamado durante o passo a passo, o
cdigo preenche a janela Code Editor. Depois que as suas declaraes
tiverem sido destacadas  e executadas (uma por vez), a rotina que o
chamou reaparece na janela Code Editor.
       Alm da tecla F7 e da ferramenta passo a passo da barra de
ferramentas, voc tambm pode utilizar F8 (ou a ferramenta Step Over)
para percorrer o programa  passo a passo. Com essa ferramenta, cada
procedimento  processado como se fosse uma nica d uma funo complexa
que voc j sabe que funciona.

Interrompendo Temporariamente os Programas

Com mais freqncia do que se pensa, porm, voc precisa interromper seu
programa temporariamente para dar uma olhada em um instantneo dos
valores de muitas das  variveis. Por exemplo, suponha que voc queira
saber por que uma varivel parece no ter o valor que voc quer. 
preciso identificar o ponto onde o valor comea  a se comportar de
maneira estranha. Simplesmente imprimir os valores no dilogo
Evaluate/Modify pode no ser suficiente.
        H duas maneiras para interromper temporariamente um programa.
Uma consiste em escolher o item Program Pause do menu Run. A outra
consiste em utilizar pontos  de interrupo (breakpoints): esses so
lugares em que o programa pra  medida que o De F5 ou utilizando o
SpeedMenu do Code Editor. (Voc tambm pode selecionar Add Breakpoint do
menu Run). Em seu cdigo, os pontos de interrupo normalmente aparecem
em vermelho. Voc tem vrias opes ao criar um ponto de interrupo com
a caixa de dilogo Edit Breakpoint. A caixa de edio Condition pode
conter uma expresso para acionar  o ponto de interrupo. Um valor na
caixa de edio Pass Count acionar o ponto de interrupo depois de um
nmero especificado de passos. Quando voc processa o  programa e o
Delphi encontra um ponto de interrupo, o Delphi pra o cdigo
exatamente antes de executar a declarao com o ponto de interrupo e
entra no modo  de parada. Voc pode estabelecer vrios pontos de
interrupo. Para remover um ponto de interrupo, posicione o cursor no
ponto de interrupo e pressione F5. Para  retirar todos os pontos de
interrupo de um programa, escolha a opo Breakpoints no menu View.
Finalmente, voc pode dar um clique no boto direito do mouse na  janela
Breakpoint List e selecionar a opo Disable All Breakpoints.

DICA: Utilize Run ( Run para continuar um programa parado. Utilize FS ou
a ferramenta Step Over na SpeedBar para tratar uma chamada a um
procedimento ou procedimento  de funo como um nico passo. Dessa
forma, voc no precisa passar por todas as linhas em todas as funes e
procedimentos em seu projeto quando sabe que no h  necessidade.
Combine isso com a opo Call Stack no menu View para ver qual o
procedimento que chamou aquele em que voc se encontra ou para olhar
toda a cadeia  de chamadas de procedimentos se necessrio.

Watch

Sempre que voc estiver depurando, o objetivo eventualmente  conseguir
descer serpenteando at um objeto, um procedimento ou uma funo que
simplesmente no funciona.  Agora voc sabe que tem um erro intern a um
objeto, um procedimento, ou funo. Embora a caixa de dilogo
Evaluate/Modify possa ser utilizada para examinar os valores  de
expresses enquanto percorre um programa passo a passo, a utilizao dos
recursos Watch do Delphi  mais eficiente. Voc pode especificar os
itens que deseja  observar antes de iniciar o programa ou enquanto o
programa est sendo processado e voc o interrompeu temporariamente. O
Delphi permite-lhe observar quaisquer variveis,  expresses ou
condies em seu cdigo. Uma maneira para fazer isso  apresentar a
caixa de dilogo Watch Properties. Essa caixa de dilogo aparece quando
voc escolhe  Run|Add Watch.  assim:
        Como voc pode ver, a caixa Expression comea vazia. Voc coloca
a expresso que deseja observar nessa rea. Depois disso, os botes de
opes permitem-lhe  especificar o formato que o Delphi deveria utilizar
para exibir a expresso.

NOTA: Voc pode observar apenas variveis globais ou variveis ligadas
ao modelo ou unidade atual.

        O Delphi, na verdade, exibe os itens que ele est observando na
janela Watch List.  medida que o Delphi executa o programa, os valores
do item Watch sero  atualizados na janela Watch List. Para remover um
item da janela Watch List, pressione CTR

Instant Watch

Um item Add Watch at Cursor na SpeedMenu (CTRL+F5) de Code Editor
permite-lhe olhar o valor da varivel ou da expresso onde o cursor est
atualmente localizado.  Esse recurso, normalmente chamado de Instant
Watch, complementa o recurso no Delphi que lhe permite utilizar a caixa
de dilogo Evaluate/Modify para olhar o valor  de qualquer varivel
dentro de um procedimento quando um programa  interrompido dentro do
procedimento.


        Para utilizar a Instant Watch:

        1. Selecione a varivel ou expresso que voc quer observar
movendo o cursor para o item ou destacando a expresso utilizando a
combinao de teclas SHIFT+seta.
        2. Escolha Add Watch at Cursor da SpeedMenu (ALT+F10+A ou
CTRL+F5).

        Se o valor no est atualmente disponvel, o Delphi vai lhe
informar. Nesse ponto, voc pode fechar a caixa com a tecla ESC ou optar
por adicionar essa varivel  como um item Watch.

Algumas Observaes Finais sobre Depurao

Fornecer a um procedimento ou funo determinados nmeros e utilizar as
tcnicas de depurao descritas aqui no  uma cura para todos os males.
Nenhuma tcnica  pode ajudar, a no ser que voc tenha uma boa
compreenso sobre o que o procedimento ou a funo deveria fazer. Se
voc est utilizando uma declarao if-then, est  testando pela
quantidade certa? Ser que um > = deveria ser um =? Utilize o recurso
Watch para verificar o valor (True ou False) de qualquer relao
Booleana que  parece estar desligada ( perfeitamente legal entrar com x
= 19 como um valor Watch). Verifique quaisquer laos na rotina; os laos
so uma fonte de problemas comum.  Os contadores esto inicializados
corretamente (h um erro de desvio de uma unidade)? Voc est testando
seus laos indeterminados no topo quando deveria estar fazendo  seu
teste na base?

DICA: Quando um lao Repeat ou While parece estar funcionando muito
tempo, adicione um contador temporrio ao lao Repeat. Em seguida,
utilize o contador em um relgio  de algum valor (relativamente) grande.
Quando o programa  interrompido, examine o estado da expresso testada
no lao para ajudar a determinar por que seus laos  esto demorando
para ser processados.


Erros e Problemas Orientados por Eventos

Quando voc depura um programa orientado por eventos, tem de estar
ciente de determinados problemas que nunca apareceriam em linguagens de
programao mais antigas.  Cascatas de eventos so talvez os mais
comuns. Esses so defeitos provocados por uma seqncia infinita de um
procedimento de evento chamando a si prprio ou a um  outro procedimento
de evento sem possibilidades de interromper a cadeia. O momento mais
provvel em que esse tipo de defeito  introduzido  quando voc faz uma
mudana no manipulador de eventos OnChange para um controle. O
procedimento OnChange  chamado novamente, que, por sua vez,  chamado
novamente e assim por diante  - teoricamente para sempre, mas, na
prtica, voc recebe uma mensagem de erro.
        Outros problemas especiais ocorrem quando voc pra um programa
durante um manipulador de eventos OnMouseDown ou OnICeyDown. Nas duas
situaes, durante  o processo de depurao, voc naturalmente solta o
boto do mouse ou levanta a tecla que invo ele presume que o boto do
mouse ou a tecla ainda est pressionada, e assim os manipuladores
OnMouseUp e OnkeyUp relevantes nunca sero chamados.

Estilo de Programao

Embora voc possa lembrar por um certo tempo a lgica de um programa
complicado, no consegue lembrar-se dela para sempre. A boa documentao
 a chave que pode  abrir o cadeado. Algumas pessoas incluem o
pseudocdigo ou esboo do programa como vrias declaraes de
comentrios. Juntamente com nomes de variveis significativos,  essa ,
sem dvida, a melhor forma de documentao. Estabelea convenes para
variveis globais, formulrios ou variveis locais e fique com elas.
Tente evitar  um cdigo complicado; se voc precisa fazer alguma coisa
engenhosa, assegure-se de que est exaustivamente documentado. (Na maior
parte do tempo, voc descobrir  que o trecho de cdigo engenhoso
realmente no era necessrio.) Nada  mais difcil de mudar depois de
seis meses do que um cdigo "incrementado".
        A questo  que quando voc tenta pensar a respeito de truques
para acelerar seus programas, voc pode, com excessiva facilidade,
perder de vista a questo  fundamental: assegurar que seu programa seja
processado corretamente em primeiro lugar. De do programa, e no de
pequenos "belisces". Falando de modo grosseiro, um algoritmo  o mtodo
utilizado para resolver um problema.
       Isso no significa dizer que depois que um programa  processado
corretamente, voc no possa considerar maneiras de fazer com que seja
processado mais rapidamente.  Assegurar-se de que certas variveis so
inteiros sempre que possvel  uma mudan a no ser que voc precise de
suas propriedades especiais.
        Tente as seguintes tcnicas adicionais para aumentar a
velocidade de seu programa se necessrio (evidentemente que ajuda ter a
maior quantidade de RAM e  um disco rgido o mais rpido possvel):
        *Carregue antecipadamente DLLs quando possvel.
        *Descarregue formulrios quando no so mais necessrios.
        *Apague um cdigo que no  mais utilizado em seu projeto. Em
particular, faa a compilao final sem informao de depurao
simblica.
        *Utilize variveis locais sempre que possvel.
        *Utilize parmetros constantes sempre que possvel.

        De qualquer forma,  extremamente difcil modificar ou depurar
um programa (mesmo um que voc prprio, h muito tempo, escreveu) que
tem pouca ou nenhuma  declarao de comentrios, pouca documentao de
acompanhamento, e nomes de variveis que n

o) deveria se encontrar em um programa sobre James Bond (e talvez nem
mesmo ali), e no em um programa sobre funes trigonomtricas.
Adicionalmente, uma vez que  o Delphi permite nomes de variveis longos,
no transforme seu programa em um atoleiro de variveis denominadas X,
X13, X17, X39, e assim por diante. Se voc se  empenhar em ter clareza
nos programas em vez de se preocupar com a eficincia em primeiro lugar,
voc se sair muito melhor.

        Finalmente, se um procedimento ou uma funo funcionar bem,
lembre-se de salv-lo para ser utilizado novamente em outros programas.
Um dos pontos principais  de uma unidade Pascal  permitir-lhe utilizar
novamente a caixa de ferramentas que voc c e funes. Esses
procedimentos e funes com freqncia podem ter aparecido antes em um
contexto ligeiramente diferente. Isso significa que depois de projetar a
interface, algumas vezes tudo o que voc tem a fazer  modificar e
conectar partes de uma biblioteca de procedimentos e funes
rigorosamente testada nos procedimentos  de evento da interface. (Esse 
um motivo por que os kits de ferramentas comerciais para o Delphi podem
ser to teis. O tempo economizado vale o baixo custo.)
