Esta foi uma semana espetacularmente intensa. O novo canal do YouTube que oferece o curso está explodindo de inscrições; está entrando na 3ª semana...
O site do curso já está no ar; você pode ver todo o curso lá, embora eu esteja adicionando vídeos o tempo todo e tenha feito aproximadamente 1/3 do trabalho.
Neste momento, tem 3 horas e 17 minutos de conteúdo. Tenho mais uma hora de conteúdo pronta para adicionar e estou trabalhando em várias outras. Tenho certeza de que o curso terá mais de 6 horas quando concluído.
Também estou trabalhando em alguns outros vídeos interessantes, como um sobre como se proteger de ataques de serialização . Vou escrever um post completo no blog cobrindo isso nas próximas semanas.
Se você tiver quaisquer perguntas, pensamentos ou ideias, eu adoraria ouvir de você. Abaixo está o vídeo desta semana e a transcrição.
Bem-vindo de volta à terceira parte da depuração em escala, onde aprendemos a caçar bugs como os profissionais!
Nesta seção, discutiremos expressões de observação que são a base da depuração. Isso é tão importante que revisitarei o assunto novamente mais tarde.
A área de exibição é a área na parte inferior da tela
No IntelliJ, também podemos incorporar expressões de observação ao lado do código. O relógio é um dos recursos mais importantes de um depurador. É assim que podemos ver o que está acontecendo no depurador.
Mas vou muito mais fundo do que isso. Especialmente para marcação de objetos, que é um dos recursos de depuração mais legais de todos os tempos.
Você já voltou de um método apenas para pensar: “o que esse método retornou?”
Isso é muito comum, especialmente quando o valor de retorno não é armazenado em uma variável. Felizmente, o IDE tem a opção de salvar esse valor para que possamos inspecioná-lo imediatamente!
Ao ativar esta opção, podemos ver os valores de retorno de todos os métodos futuros. Se entrarmos no método isPrime
e depois sairmos, você poderá ver o valor de retorno do método aqui embaixo.
Avaliar a expressão é um dos recursos interessantes do depurador que não usamos o suficiente.
Podemos iniciar a caixa de diálogo de expressão de avaliação no menu do botão direito e digitar qualquer expressão Java válida. Esta é uma ferramenta poderosa que pode invocar qualquer método, fazer aritmética e até mesmo alterar o valor das variáveis como resultado.
Se você precisa simular algo difícil de testar no código atual, este é o lugar onde você pode brincar com a plataforma e testar “teorias malucas”.
Isso é muito parecido com o REPL que temos nas versões mais recentes do Java, mas é melhor em muitos aspectos porque podemos executar o código no contexto do nosso aplicativo.
Se eu tiver um método que retorna o valor errado, geralmente copio a chamada em uma caixa de diálogo de avaliação e tento várias combinações da chamada para ver “o que funciona”.
Apenas tentar todas as opções sem reiniciar pode nos poupar muito tempo!
Você pode iniciar esta caixa de diálogo com a combinação de teclas Alt-F8
.
A capacidade de assistir no IntelliJ é absolutamente espetacular.
O IntelliJ nos permite incorporar o relógio diretamente no editor IDE selecionando “Adicionar relógio embutido” no menu de contexto. Esse é um recurso incrível que, até onde eu sei, é exclusivo da JetBrains.
Uma vez selecionado, o relógio aparece à direita ao lado da linha onde adicionamos o relógio inline, o que facilita a avaliação com o código. Isso é muito conveniente ao retornar à mesma linha várias vezes.
Também podemos usar o relógio padrão que adicionará elementos com as outras variáveis. Isso é útil para objetos que queremos rastrear em grandes áreas do código. Tenho muito a dizer sobre a área de observação à medida que avançamos, mas, por enquanto, vamos deixar isso em espera.
O valor definido é um recurso que muitas vezes esqueço de usar durante a depuração.
Isso é uma pena porque é tão poderoso. Podemos definir o valor de qualquer campo clicando com o botão direito do mouse e selecionando definir valor.
Também podemos usar F2
para acelerar isso
Posso alterar o valor para qualquer valor arbitrário. Isso também pode se aplicar a objetos nos quais posso atribuir um valor existente ou invocar um método de criação, uma nova instrução ou qualquer expressão que desejar.
É um recurso extremamente poderoso onde podemos modificar o objeto dinamicamente para reproduzir um estado que queremos testar.
Podemos combinar esse recurso com pular para a linha que discutimos anteriormente e testar um método por meio de muitas permutações diferentes. Mesmo aqueles que podem não ser reproduzíveis normalmente. Um bom exemplo seria o código que tenho que só roda no Windows. Mas eu tenho um Mac.
Eu apenas altero o valor da variável estática que indica o sistema operacional atual e testo esse código.
A marcação de objetos é um dos recursos mais interessantes que discutiremos neste curso e é quase desconhecido.
É um pouco sutil; primeiro, adicionaremos um watch para Thread.currentThread()
que retorna a instância do objeto que representa o thread atual.
Como você pode ver, posso ver o tópico atual no relógio.
Agora, posso executar esse método várias vezes e ver o thread atual; o método é sempre executado a partir do mesmo thread?
Bem, posso ver o ID do tópico e sim. É o mesmo. Então, provavelmente é thread-safe. Mas como posso verificar isso?
Normalmente anoto o ID do objeto ou o ponteiro da variável em um pedaço de papel e verifico se é o mesmo valor. Isso é uma dor e não escala. Com que frequência posso pressionar continuar de novo e de novo?
No menu do botão direito, seleciono Marcar objeto e digito um nome arbitrário. MyThread
neste caso, depois de fazer isso, posso pressionar OK
Isso substitui o valor do thread atual agora pelo novo rótulo. Portanto, podemos assumir incorretamente que este é apenas um nome para uma expressão de observação. Não é. Declaramos uma nova variável e demos a ela o nome MyThread
.
Copiamos o valor atual da expressão de observação para essa variável. Agora podemos tratar essa variável como tratamos a maioria das variáveis no IDE.
Podemos avaliar o valor aqui e conseguir tudo o que quisermos. Observe o sufixo _DebugLabel
adicionado pelo IntelliJ para evitar colisões de nomes, mas fora isso, podemos invocar qualquer operação neste objeto, como obter o nome ou até mesmo acessar o nome do campo privado.
Mas isso fica muito melhor…
Vamos adicionar um ponto de interrupção a este método, um ponto de interrupção completamente padrão, como fizemos antes.
Este será um ponto de interrupção condicional padrão; discutiremos isso em breve em profundidade, mas agora, tudo o que você precisa saber é que posso definir uma condição que determinará se o ponto de interrupção será interrompido ou não.
Vamos ampliar.
Vamos digitar a condição; Posso comparar MyThread
com o valor atual do thread. Observe que essa condição se comportará de acordo, pois o valor de MyThread
é independente da instrução watch original de Thread.currentThread()
.
Portanto, se o thread atual for realmente diferente, o ponto de interrupção será interrompido neste ponto.
Isso é imensamente útil ao lidar com muitos objetos. Nesse caso, posso verificar literalmente se o método será atingido com o mesmo thread. Posso usá-lo para comparar quaisquer objetos em vez de escrever seus ponteiros em um pedaço de papel!
Sim. Eu literalmente sentava com um pedaço de papel e copiava o endereço do ponteiro para ter certeza de que estava certo se o visse novamente. Isso é melhor de muitas maneiras!
Costumo usar isso com APIs como JPA, onde às vezes podemos ter duas instâncias de objeto com a mesma identidade. Isso é realmente difícil de detectar. Basta marcar um objeto e, em seguida, você poderá ver instantaneamente que é uma instância diferente.
Como este caso é obviamente de thread único, o ponto de interrupção nunca será atingido novamente. Mas isso funciona muito bem para casos muito elaborados e é uma ferramenta extremamente útil!
A seguir, vamos nos aprofundar nos pontos de interrupção e nas coisas incríveis que eles podem fazer. Este é um vídeo profundo que você não pode perder.
Se você tiver alguma dúvida, use a seção de comentários. Obrigado!