Sempre que vamos usar uma ferramenta, é importante saber como ela funciona para que seja utilizada da melhor maneira possível.
O processo de depuração no TDS não é uma exceção, portanto esse documento visa "detalhar" seu funcionamento para que você tenha a melhor experiência possível e saiba identificar melhor possíveis situações.
Portanto, leia com atenção toda essa documentação pois ela poderá ser de grande ajuda.
A primeira coisa a ser observada é que o TDS é uma ferramenta do tipo cliente/servidor, ou seja, ela sempre requisitará informações ao servidor e apenas apresentará os resultados para o usuário.
Com isso em mente já podemos para observar que quem realmente faz a depuração é o servidor, o TDS apenas exibirá as informações retornadas pelo servidor.
A segunda coisa, é que o TDS é construído em cima da plataforma Eclipse e utiliza o framework de depuração dela para que as informações sejam apresentadas na tela.
Vamos conhecer o fluxo de execução de uma depuração com o TDS.
(Em relação aos processos do servidor, podemos apenas deduzir o que ocorre, portanto as informações aqui referentes a ele são apenas superficiais):
1 - O usuário conecta-se a um servidor (O qual pode ser local ou remoto)
2 - O usuário cria um executor, informando qual o SmartClient que será utilizado, a aplicação de entrada (SIGAADV, ou um fonte específico por exemplo), e parâmetros extras, como -M para múltiplas sessões e etc.
3 - O executor é lançado diretamente pelo botão OK após a criação do executor, ou mais tarde pelo ícone
4 - Após lançado, o TDS executa o SmartClient com os parâmetros informados e fica aguardando o servidor inicializar uma conexão específica para depuração.
5 - Quando a conexão é iniciada, o servido retorna para o TDS um ID de depuração e o TDS pode seguir com o processo de inicialização.
6 - O próximo passo é, antes de mais nada, informar para o servidor os pontos de parada adicionados pelo usuário.
7 - Agora o TDS inicia algumas "flags" internas, informa a plataforma Eclipse que a depuração foi iniciada e fica aguardando a próxima instrução do servidor.
8 - Nesse momento, o servidor está executando a aplicação em modo de depuração, e para isso ele também terá uma série de informações extras que serão processadas.
8.1 - Enquanto o servidor está executando e nenhum ponto de parada foi alcançado, ele envia periodicamente para o TDS uma notificação para que os dois se mantenham conectados e cientes um do outro, e também para que o TDS possa avisar o servidor caso algum ponto de parada foi adicionado, removido ou alterado.
9 - Quando o primeiro ponto de parada é encontrado pelo servidor, ele para a execução e envia a informação para o TDS com o nome e a linha do fonte onde a parada ocorreu.
9.1 - Obs.: Quando o servidor envia para o TDS essa última informação, ele para a execução e fica aguardando instruções do TDS.
10 - O TDS ao receber a notificação de parada, irá requisitar para o servidor todas as informações pertinentes à linha informada, e cada requisição do TDS é uma comunicação com o servidor. Elas são (nessa ordem):
10.1 - Verifica se houve alguma alteração nos pontos de parada (Adição e/ou remoção) e em caso positivo informa o servidor. Note que isso é feito em toda oportunidade que o TDS tiver para que o usuário tenha resposta dos pontos de parada modificados o mais rápido possível.
10.2 - Requisita toda a pilha de execução, montando internamente a estrutura para a plataforma Eclipse.
10.3 - Apenas para pilha corrente, o TDS requisita a lista com todas as variáveis e seus respectivos valores, montando a estrutura internamente para que a plataforma Eclipse possa apresentá-las
10.4 - Procura, nos projetos informados na aba "Source Lookup/Origem" do executor lançado, e que possuam natureza Totvs, o fonte informado pelo servidor. (Atenção, isso é feito pela plataforma Eclipse utilizando as informações da pilha de execução sincronizadas anteriormente)
10.4.1 - Para agilizar essa busca em futuras requisições (Como por exemplo, um fonte onde já houve uma parada anteriormente), o TDS guarda um registro interno com os fontes já procurados e se foram encontrados ou não, evitando assim que a busca seja feita novamente em todos os projetos, agilizando essa etapa.
10.4.2 - Na definição do executor, há opção para localizar fontes duplicados. Se habilitado, todos os projetos informados na aba "Origem" serão processados para localizar o(s) fonte(s). No caso de haver mais de um, será solicitado ao usuário que indique qual o fonte desejado.
10.5 - Caso o fonte não seja encontrado e o usuário marcou a opção para ignorar fontes não encontrados, o TDS já retorna nesse momento para o servidor a informação de que ele deve continuar a execução e o TDS volta a esperar uma nova notificação.
10.6 - Caso o fonte não seja encontrado e o usuário não marcou a opção para ignorar fontes não encontrados, OU o fonte FOI encontrado, o TDS segue processando.
10.7 - O TDS irá agora tentar realizar a parada da plataforma, e para isso precisa verificar algumas situações:
10.7.1 - Caso a parada seja por uma requisição do usuário (Step Over, Step Into, Run to Line, etc..) já notifica a plataforma Eclipse para que a interface seja atualizada, abrindo os fontes, pintando a linha informada (Caso o fonte tenha sido encontrado), montando a visão de pilha de execução, variáveis, atualiza os textos e etc...
10.7.2 - Caso a parada tenha sido por ponto de parada, o TDS confirma que esse ponto de parada existe no registro interno. Em caso positivo, irá notificar a plataforma Eclipse como no item 10.7.1. Caso não seja encontrado, significa que, provavelmente, o usuário removeu o ponto de parada no momento em que o TDS estava processando as informações, portanto ele será marcado para sincronizar com o servidor no momento oportuno.
10.8 - Com a parada identificada e enquanto a plataforma Eclipse atualiza a interface de usuário, o TDS irá sincronizar as informações das tabelas (Caso a opção esteja ligada na visão, senão essa etapa é ignorada). Portanto, caso existam tabelas a serem apresentadas, após o servidor retornar a lista delas, a estrutura interna será montada e novamente a plataforma Eclipse será notificada. Obs.: Esse processo é feito nesse ponto, para que o usuário tenha uma sensação maior de agilidade, pois ele possui um volume de informação muito alto. Note como ele é feito em paralelo com a atualização da interface.
10.9 - Agora com as informações apresentadas, o TDS fica aguardando o usuário informar qual o próximo passo. Eles podem ser:
10.9.1 - Step Over: Essa opção fará com que o servidor execute a linha corrente, parando na próxima do mesmo fonte. Ou seja, a linha possua a execução de uma função qualquer, todo código dessa função será executado e apenas quando ela retornar o servidor fará a parada.
10.9.2 - Step Into: Ao contrário da opção anterior, caso a linha seja uma chamada de uma função, o servidor irá entrar na mesma e informar a parada na primeira linha dessa função.
10.9.3 - Step Return: Retorna de uma função que foi entrada via Step Into.
10.9.4 - Run To Line: Essa opção possui a mesma funcionalidade de um ponto de parada, porém sem a necessidade de criá-lo. O usuário coloca o cursor na linha onde espera que a próxima parada aconteça e aciona essa opção. Na prática, o TDS informa para o servidor que foi criado um ponto de parada naquela linha e manda executar. Quando o servidor retornar para o TDS, este faz todo o processo da parada e remove o ponto de parada da linha.
19.9.5 - Resume: Faz com que a execução continue até que outro ponto de parada seja encontrado ou o programa finalize.
10.10 - Assim que o TDS recebe do usuário a próxima ação, ele a informa para o servidor. Neste momento o TDS entra em modo de espera e o servidor continua seu processamento. Caso uma nova parada seja informada, todo o processo do item 10 se repete.
O texto acima mostrou como funciona um fluxo básico de uma execução de depuração. Note que ali não entrou outros processamentos envolvidos, como quando o usuário pede para avaliar variáveis, a forma que alguns tipos de variáveis, como por exemplo Arrays, são recuperados, a visão de Commands e etc. Mesmo porque essas operações serão feitas no momento em que o servidor e o TDS estão aguardando ações do usuário.
Observando apenas o fluxo de execuções, já é possível deduzir algumas boas práticas para que uma depuração seja realizada. Ao longo do tempo, a equipe de desenvolvimento da ferramenta identificou também alguns comportamentos dos usuários que não ajudam o processo como um todo.
A seguir vamos falar um pouco sobre recomendações, boas práticas, o que fazer e o que não fazer, e o que devemos esperar de algumas situações.
1 - Ambiente de depuração:
1.1 - Recomendamos fortemente que a depuração seja feita em ambiente local
Importante:
(1) Quando o TDS estiver aguardando interação com o usuário, o servidor congela a execução da "thread" que esta sendo depurada. Caso a opção de depuração "multi-thread", definida no lançador de depuração, estiver habilitada, todas as "threads" (a corrente, "jobs", "web jobs", conexões de outros SmartCLients e outras) também serão congeladas, independente do ambiente que está usando;
(2) NÃO faça depuração em ambientes de produção ou compartilhando o servidor com outros desenvolvedores;
(3) Em cenários de "balance", faça a conexão em um "slave" qualquer. Caso o faça no "master", poderá obter erros de comunicação ou processamento inesperado.
1.2 - Observe pelo fluxo de eventos, que durante a depuração o servidor ficará parado em alguns momentos. Apesar disso acontecer em uma "thread" própria, evite fazer depuração em ambiente que esteja sendo usado por outros usuários pois nesse caso, existe uma grande probabilidade de ocorrem inconsistências, tanto para a própria depuração quanto para outros usuários do sistema.
1.3 - IMPORTANTE: Não utilize o Google Chrome. Esse browser é conhecido por usar toda a memória do sistema, e como ele também roda em Java (assim como o TDS), ele pode não deixar recursos suficientes para a execução da depuração (ou mesmo do TDS em si). Caso ele já esteja aberto, feche-o e garanta que todos os processos sejam encerrados (Verifique no Gerenciador de tarefas do seu sistema operacional).
1.4 - Garanta que a máquina que está rodando o TDS tenha memória disponível e o processador não esteja em uso pesado. Faça o mesmo para a máquina onde está localizado o servidor (Caso seja um servidor remoto).
2 - Parâmetro -A:
No executor do TDS, existe um campo onde é possível informar parâmetros para o programa a ser executado (-A).
Até o momento, esse parâmetro é conhecido por causar problema com a função "pergunte" em modo de depuração. Fazendo com que o SmartClient gere um erro de execução. A equipe responsável pela função já foi alertada.
Portanto, não informe absolutamente nada nesse campo, ao menos que seja estritamente necessário e em nenhum momento a função pergunte seja invocada.
Como pode notar, é um problema na função e não existe nada que o TDS possa fazer para contornar.
3 - Procura de fontes:
Como você observou no fluxo, quando o servidor informa ao TDS uma parada, este irá buscar os fontes apenas nos projetos informados na aba "Source Lookup/Origem" do executor.
Algumas coisas muito importantes devem ser observadas em relação a isso:
2.1 - Obviamente, o projeto onde o fonte se encontra deve estar listado ali. Caso não esteja, use o botão "Adicionar". Caso a depuração mostre que uma parada ocorreu mas o fonte não foi aberto, esse é o ponto que deve ser investigado primeiro, pois em 90% dos casos que a equipe investigou, o "problema" estava relacionado a isso.
2.2 - No TDS 11.3, além do projeto ser listado nessa aba, note também que ele deve possuir a natureza Totvs, caso contrário, mesmo estando listado, o projeto não será considerado na busca. Aqui estão os outros 9.9% dos casos relacionados a fontes não abrindo durante a depuração. Ela pode ser adicionada no projeto acionando o botão menu de contexto do projeto com o botão direito do mouse, na opção: Configurar → Adicionar Natureza TOTVS.
2.3 - Ao longo do tempo, observamos que muitos usuários mantém uma área de trabalho, ou com um número muito grande de projetos, ou com um projeto com um número gigantesco de fontes (com dezenas de milhares de fontes). Porém, apesar disso, os usuários trabalham em apenas uma fração desses fontes, ou seja, são mantidos fontes que nunca são usados.
2.3.1 - Esse tipo de situação onera não apenas a depuração, mas o TDS como um todo, então a primeira recomendação é para adicionar na área de trabalho apenas fontes que serão efetivamente trabalhados.
2.3.2 - A segunda recomendação é, mesmo que você adicione todos os fontes do repositório (TFS, SVN, GIT, etc...) na área de trabalho, o TDS permite que você "feche" (Botão direito no projeto, opção fechar projeto) os projetos não usados. Portanto mantenha abertos apenas os projetos realmente utilizados.
2.3.3 - A terceira recomendação é para que seja criado um projeto a parte, copie/mova APENAS os fontes que você deseja trabalhar/depurar para ele e certifique-se que apenas esse novo projeto seja adicionado na aba "Source Lookup/Origem", ou que apenas esse fique aberto na área de trabalho. Porém, atenção nesse procedimento, recomendamos que você sempre verifique essa aba antes de cada depuração.
Note que as ações do item 2.3 possuem um grande impacto na performance da depuração.
4 - Ações de execução:
As ações podem ser: Step Into/Avançar para, Step Over/Ultrapassar, Step Return/Retroceder, Run/Continuar, Termiante/Encerrar.
Falaremos sobre cada uma delas, não deixe de ler pois algumas possuem pontos de atenção na depuração de programas Totvs.
Abaixo usarei os nomes em inglês por ser mais fácil encontrar informações na internet sobre esses termos.
3.1 - Step Into (F5): Essa opção fará com que a depuração entre em qualquer função que exista na linha corrente. Atenção com essa opção, pois ao ser informada para o servidor, cada linha de cada função executada pelo servidor será informada para o TDS até que seja encontrado um fonte ou a função retorne, parando na linha seguinte do mesmo fonte. Perceba que caso seja uma função de um fonte que você não tenha acesso, porém que eventualmente acesse o fonte que você deseja a parada, como informado, cada linha será executada e enviada para o TDS até que seu fonte seja atingido e encontrado.
Por exemplo, suponha a seguinte situação hipotética:
- Na linha corrente exista a função: calculeFatura() e nessa função possua um ponto de entrada onde você deve fazer a soma dos itens e retornar para o processo.
- Porém, antes do ponto em que seu fonte é chamado, essa função seleciona uma série de tabelas e executa 2500 linhas.
- O servidor irá fazer um Step Into em cada uma das 2500 linhas executadas (Mandando informação para o TDS em cada uma delas, onde o TDS fará o processo de parada até que o fonte não seja encontrado), e se em uma delas existir outras funções, essas também serão acessadas antes de chegar no seu fonte.
Percebeu o problema de usar o Step Into nesse caso? Apesar do TDS retornar para o servidor o mais rápido possível em cada linha, ainda sim o processo como um todo será demorado até que seu fonte seja acessado.
Esse é o comportamento padrão de uma execução do tipo Step Into, independente da linguagem, servidor ou plataforma de desenvolvimento.
Esse seria um bom caso para usar a opção Run To Line, ou mesmo adicionar um ponto de parada ao invés de usar o Step Into.
3.2 - Step Over (F6): Use essa opção para que a depuração vá para a próxima linha do fonte corrente. Caso a linha possua uma chamada de função, essa será executada "como se fosse" um processo de "Run (F8)".
3.2.1 - Nessa opção, a performance da depuração irá depender basicamente da função que está sendo executada e do processamento do servidor. Caso a função seja muito complexa, possua instruções pesadas, como abertura de tabelas e etc, a expectativa é que o servidor demore para retornar a parada da próxima linha para o TDS.
3.3 - Step Return (F7): Use essa opção para retornar ao ponto onde a função foi chamada. Use essa opção com cuidado, pois dependendo da função que você estiver depurando, o servidor pode tentar retornar para funções internas do sistema, executando linha a linha até que um fonte na sua área de trabalho seja encontrado ou o programa termine. Também possui um grande potencial para demora do retorno do servidor até que uma das situações anteriores aconteça.
3.4 - Run To Line (Ctrl + R): Posicione o cursor na linha do fonte onde deseja que a depuração pare e acione as teclas Ctrl + R. Essa opção funciona como se tivesse adicionado um ponto de parada na linha do cursor, ou seja, a depuração será executada em modo "Run" até que a linha posicionada seja atingida. Quando isso acontecer o servidor informará o TDS da parada normalmente. Atenção, certifique-se que a linha onde está posicionada o cursor seja atingida pela execução do programa, caso contrário a depuração continuará até que um ponto de parada aconteça ou o programa termine sua execução.
3.5 - Run (F8): Use essa opção para que o programa execute normalmente, interrompendo apenas se encontrar um ponto de parada em alguma linha executada (Processo executado pelo servidor. o TDS fica em modo de espera).
3.6 - Terminate (Ctrl + F2): Essa opção encerra a depuração, fechando inclusive o SmartClient. Atenção nesse processo pois ele pode não ser imediato, pois ainda sim algumas ações de encerramento precisam ser realizadas, como encerramento da conexão de depuração e etc.
Perceba que existem alguns pontos que precisam de cuidado durante uma depuração, o TDS não bloqueia ações que tem um grande potencial de perda de performance pois essa é uma decisão do usuário, pois isso pode ser necessário para alguns. Antes de mais nada, caso você tenha sido direcionado a essa documentação pelo Fluig, favor responda o post com o texto: lido e entendido. Caso você tenha sido direcionado por e-mail, favor respondê-lo ao analista do TDS com o mesmo texto. Continuando, porém é importante entender o que está acontecendo para que se tenha uma expectativa realista em cada situação.
Atenciosamente,
Equipe do TDS.