[an error occurred while processing this directive]
Matéria de Capa
Edicao Atual (n. 23)

 

 

A arte do debug

Aprenda a interpretar exceções, utilizar uma ferramenta de debug e encontrar os erros mais estranhos em suas aplicações.

Encontrar erros em uma aplicação é uma habilidade essencial e indispensável para qualquer desenvolvedor. Porém, quando um erro acontece, muitas pessoas não sabem nem por onde começar. O objetivo deste artigo é apresentar técnicas de depuração, como a análise de exceções e o uso de uma ferramenta de debug, além de alguns macetes do dia-a-dia. Com isso, espera-se que o leitor consiga se embrenhar no código de uma aplicação e seguir a trilha deixada por um erro até encontrá-lo.

Encontrar os erros em um software é uma habilidade importante para qualquer programador desde a época do cartão perfurado. Obviamente naquela época os desenvolvedores não contavam com ferramentas tão sofisticadas e nem com uma linguagem com um mecanismo de tratamento de erros tão robusto quando o Java. Ao procurar um erro, muitos se sentem em uma selva fechada buscando uma pessoa perdida e acabam andando em círculos. Porém, assim como esta pessoa perdida, um erro em uma aplicação deixa uma trilha e algumas pistas. O objetivo deste artigo é ensinar a arte de seguir esta trilha e estas pistas para que seja possível encontrar e corrigir os erros de uma aplicação.
O primeiro passo para identificar um erro é saber interpretar o significado de uma exceção. Desta forma, a primeira parte deste artigo irá se dedicar a explicar que informações podem ser extraídas de uma exceção utilizando sua classe, sua mensagem e a pilha de métodos no momento em que ela foi lançada, também conhecida como stack trace. A segunda parte deste artigo irá mostrar como utilizar uma ferramenta de depuração para acompanhar passo-a-passo a execução de um código. A perspectiva de debug do Eclipse será utilizada como exemplo, porém os conceitos apresentados serão aplicáveis a qualquer outra ferramenta com o mesmo propósito. Finalizando o artigo, serão apresentadas situações curiosas que fazem alguns acreditarem que desenvolver software está longe de ser uma ciência exata. Nessa parte final, serão mostradas situações que podem gerar erros difíceis de serem identificados e algumas dicas para contornar estas dificuldades.

Entendendo uma exceção

Usar exceções é uma forma robusta de se trabalhar com tratamento de erros em Java. Elas podem se propagar entre métodos e podem ser tratadas de forma separada do código da aplicação, utilizando um bloco try/catch. Uma exceção é uma classe como outra qualquer, o que significa que ela pertence a uma hierarquia e pode ter informações e métodos. Não está no escopo deste artigo descrever a forma como a linguagem Java lida com exceções e sim como utilizá-las como referência para identificar os erros.
Quando alguém me diz que está ocorrendo um erro que não está conseguindo resolver e precisa da minha ajuda, a primeira pergunta que eu faço é: qual é a exceção que está sendo lançada? O que me surpreende é que muitas vezes a pessoa não sabe me responder. Ao analisar um erro, a primeira coisa que deve ser vista é a exceção, pois ela irá dizer o que ocorre e onde ocorre. Nas seguintes subseções serão discutidas as principais pistas que uma exceção pode deixar. Primeiramente será dito sobre os tipos e as mensagens das exceções e depois será mostrado o que é um stack trace e como utilizá-lo para localizar o erro.


Profile em Aplicações Java

Monitore o consumo de memória e de processamento das suas aplicações Java utilizando ferramentas de Profile

A cada dia, mais aplicações são desenvolvidas e cada vez menos as pessoas se preocupam com o desempenho e consumo de processamento. Hoje, a maioria das aplicações rodam em máquinas compartilhadas e a existência de um monitoramento durante a implementação, dos recursos que a aplicação consome, é essencial. Neste artigo, veremos os conceitos e a utilização do Eclipse Test and Peformace Tools Plataform (TPTP) do projeto Callisto no Eclipse, que irão auxiliar na detecção de problemas relacionados a consumos excessivos de recursos (memória e CPU).

Desde os primórdios da área de desenvolvimento de software, persistem os mesmos problemas, talvez com menor ou maior influência, dependendo da época, linguagem ou arquitetura desenvolvida. Quando se desenvolve para alguns tipos de microcontroladores a preocupação com o consumo de memória é primordial. Muitas vezes, um alto consumo de memória ou um processamento excessivo podem levar à lentidão, chegando até mesmo ao travamento de um servidor! Do outro lado da rede os clientes poderiam estar incomodados com a baixa performance, ou mesmo recebendo um time-out do sistema. Cenários como esstes podem prejudicar a imagem de uma aplicação. Muitos pontos devem ser observados no que diz respeito a um desempenho inadequado, dentre eles destacam-se:

• Chamadas excessivas ao um mesmo método com um alto tempo de execução;
• Vazamento de memória apesar de todo o controle feito pela Virtual Machine através do Garbage Collector, em Java ainda é possível que isto aconteça;.
• Deadlocks de Threads;
• Aberturas de conexões excessivas no banco de dados ou não- liberação das mesmas após o uso.

Todas as aplicações, mesmo que pequenas, devem passar por testes de performance, principalmente quando este tipo de solicitação for feita por clientes como um requisito não- funcional da aplicação. A melhor forma de se fazer estes testes é utilizar ferramentas de Profiling. Estas ferramentas auxiliam na localização dos gargalos de falta de desempenho, consumo de memória e DeadLocks de Threads. O importante é ter uma metodologia para seguir e evitar a localização dos gargalos por intuição. Existem ferramentas, integradas às IDEs ou que trabalham de forma isolada, que fazem o monitorando das chamadas quando as aplicações são executadas, permitindo a obtenção de informações em relação ao seu tempo de execução e consumo de memória. Uma boa ferramenta é o TPTP (Test and Performace Tool Plataform) que faz parte do projeto Callisto (projeto que integra várias plataformas ao Eclipse). Essa ferramenta será utilizada durante os exemplos deste artigo. Além do TPTP podemos destacar também o hprof que está incluso na própria instalação do SDK.

Test and Performace Tool Plataform

Projeto Callisto
A partir da versão 3.2 do Eclipse, foi incorporado ao Eclipse.org o projeto Callisto. Callisto é um importante projeto do Eclipse.org, destinado ao aumento da produtividade de desenvolvimento sobre a plataforma Eclipse. ÉÉ formado por 10 subprojetos e dentre eles podemos destacar o BIRT (Business Intelligence and Reporting Tools) , CDT (C/C++ Ide), DTP (Data Tools Plataform), EMF (Eclipse Modeling Framework), GEF (Graphical Editing Framework), GMF (Graphical Modeling Framework), Eclipse Project, TPTP (Eclipse Test and Peformace Tools Plataform), WTP (Eclipse Web Tools Project) e VE (Visual Editor). O Callisto tem releases simultâaneos aos releases do Eclipse. Com a instalação de plugins via Callisto, pode-se reduzir o tempo de criação do ambiente de desenvolvimento.

O TPTP faz parte do projeto Callisto e está incubado dentro do Eclipse.org. Para realizar a instalação do mesmo, precisamos utilizar o Eclipse 3.2. Utilizaremos a versão 1.5 do JDK e o Eclipse 3.2 com todas as funções do projeto Callisto instaladas. Porém, para se executar os exemplos, basta instalar o plugin TPTP. A instalação é simples e pode ser feita através do update do Eclipse.
Não será explicado em detalhes a instalação de plugins do Callisto através da funcionalidade de updates do Eclipse. Porém será apresentada uma breve referêencia para que se possa ter uma visão geral da instalação do projeto Callisto:

• Para iniciar a instalação do TPTP, deve-se instalar previamente o Eclipse e inicia-ló;.
• selecione a Workspace que será trabalhada;.
• Para iniciar a instalação, basta clicar em Help -> Software Updates -> Find and Install;.
• Selecione Search for new features to install para que o Eclipse busque novas funcionalidades dentro do projeto Eclipse;.
• Selecione Callisto Discovery Site. Este é o repositório do projeto Callisto, através dele podemos baixar qualquer um dos 10 projetos ligados ao Callisto. ;
• dDevemos agora selecionar o Mirror para o repositório;
• Após selecionar Next, o Eclipse irá realizar uma comunicação com o repositório e baixar as possíveis instalações que poderemos ter;.
• Selecione os pacotes que deseja instalar, obviamente não esqueça do TPTP (Test and Performace Tool Plataform). E aguarde o final da instalação. Após a instalação, o Eclipse deverá ser reiniciado.

Com o TPTP pode-se realizar análise de consumo de memória, consumo de CPU, deadlock de Threads. É interessante notar que a ferramenta possibilita uma visão bem detalhada do consumo de recursos, incluindo a visão de consumo dos métodos isoladamente. Neste artigo, iremos verificarverificaremos o consumo de CPU e o consumo de memória através do TPTP.


Sobrecarregando sua aplicação com JMeter

Descubra qual nível de carga sua aplicação pode suportar

A necessidade de desenvolver uma aplicação segundo metodologias e padrões de testes muito bem definidos, hoje em dia já se tornou um senso comum. Porém, tão importante quanto testar, e onde não se tem desprendido a atenção necessária, é a necessidade de realizar testes sobre todo o universo que esta além do desenvolvimento e que compreende toda a estrutura que suportará a aplicação desenvolvida. Neste artigo, veremos o que, como e quando realizar tais testes assegurando-nos de que tanto a aplicação quanto a estrutura que a suportará estão aptos para atender às necessidades do projeto.

Muito tem se falado a respeito de testes nos dias de hoje. E com o advento das metodologias ágeis, um grande enfoque é dado aos testes na fase de desenvolvimento e codificação do projeto, ou mesmo fala-se em metodologia de desenvolvimento orientado a testes (TDD – Test Driven Development). Todavia, tão importante quanto a execução de testes durante a fase de desenvolvimento, é necessário que sejam efetuados em conjunto, testes que validem a estabilidade e robustez da arquitetura projetada, bem como a infra-estrutura que suportará a aplicação e seus requisitos não-funcionais.
Você saberia responder quantos usuários simultâneos sua aplicação suporta? Quantas requisições por segundo sua aplicação suporta tratar? Em quanto tempo sua aplicação responde quando há cem usuários utilizando-a? E quando há mil?
O intento deste artigo é mostrar e ensinar na prática como realizar testes de carga, performance e stress utilizando o Apache JMeter, de maneira que as perguntas acima possam ser respondidas, ou seja, tais respostas que lhe darão segurança a respeito do comportamento da sua aplicação dentro de um determinado cenário.

Teste de carga, performance ou stress?

Antes de embrenharmos-nos nas peculiaridades técnicas, primeiro precisamos definir conceitualmente os tipos de teste para sabermos quando e o que usar de nossas ferramentas.
Muitas vezes se ouve as definições: teste de carga, teste de stress, teste de performance, ditos como se fossem o mesmo tipo de teste. Porém há algumas diferenças que caracterizam cada um destes tipos de teste. Vamos definir de uma forma concisa e breve tais tipos.


Testes unitários para camadas de negócios no mundo real

Aprenda, na prática, a tornar suas aplicações mais robustas e confiáveis utilizando testes unitários.

A maior parte dos desenvolvedores sabe que testes unitários são vitais para se ter um software de qualidade. No entanto, em muitos projetos, poucos testes são escritos. Isso se deve, em parte, à falta de uma cultura de testes, bem como à falta de conhecimento de técnicas e ferramentas que podem agilizar essa tarefa. O objetivo deste artigo é dar ao leitor a motivação para escrever testes unitários para a camada de negócios e também apresentar, de maneira prática, as principais técnicas e ferramentas utilizadas para auxiliar nesse processo.

Testar software é um processo que tem por objetivo ajudar a identificar a corretude, completeza, segurança e a qualidade do software produzido. Existem vários níveis de testes a que sistemas de software podem ser submetidos. Os principais são os seguintes:

• testes unitários: testa as unidades mínimas que compõem um software (e.g. métodos, objetos e classes);
• testes de integração: testa a interação entre os componentes integrados do sistema (módulos);
• testes de sistema/funcionais: testa se o sistema implementado atende aos seus requisitos;
• testes de aceitação: teste realizado pelo cliente para verificar se o produto está de acordo com suas necessidades.

Para o desenvolvedor, a categoria de testes mais importante é a dos testes unitários. Quando o código básico, de baixo nível, sobre o qual um sistema é construído, não é confiável, os componentes de mais alto nível provavelmente apresentarão problemas. Testes unitários são escritos e executados para provar que uma parte do código faz o que o desenvolvedor pensa que ela deveria fazer, ao contrário dos testes funcionais e de aceitação, cujo objetivo é validar o sistema contra os requisitos e necessidades do cliente.
O objetivo deste artigo é fornecer uma visão geral de desenvolvimento de testes unitários, focando especificamente à camada de negócios de uma aplicação. Questões relevantes e ferramentas de apoio ao desenvolvedor Java são discutidas. Primeiramente, é apresentada uma visão geral sobre testes unitários. São discutidas questões relacionadas aos benefícios de se ter testes, o que testar e as características que bons testes devem possuir. Em seguida, é trazido um pequeno estudo de caso de uma aplicação para reserva de passagens áreas. Um passo-a-passo é apresentado para a implementação efetiva de testes unitários para a camada de negócios dessa aplicação. Esse exemplo prático ilustra abordagens para endereçar as principais dificuldades com que os desenvolvedores geralmente se deparam na tarefa de escrita de testes para o código que produzem.

Testes unitários – o que são?

Como foi dito na introdução, um teste unitário é apenas um pedaço de código que o desenvolvedor escreve para exercitar um outro pedaço de código e determinar se este outro pedaço de código está se comportando como esperado ou não. Para verificar se o código a ser testado se comporta da maneira adequada, são utilizadas assertivas (assertions). Uma assertiva é simplesmente uma chamada de método que verifica se uma determinada condição é verdadeira. Mais informações sobre o uso de assertivas podem ser encontradas no artigo “JUnit – Testes Unitários”, da MundoJava nº. 17.
É fundamental ter os testes unitários sendo executados automaticamente em cada build do projeto. Algumas ferramentas, como o Ant e o CruiseControl, podem ser usadas com essa finalidade [Wilkinson, 2005]. Está fora do escopo deste artigo discutir a automatização de testes unitários em um projeto de software.
Existem diversos frameworks para facilitar a escrita e execução de testes unitários na plataforma Java. O mais popular deles é o JUnit, que atualmente encontra-se em sua versão 4.x. Detalhes práticos de como o JUnit é utilizado podem ser encontrados neste artigo, na seção referente ao estudo de caso.
Entretanto, na prática, as coisas não são tão simples assim. Em sistemas complexos, que possuem muitas dependências entre seus módulos e que acessam recursos externos, como banco de dados e rede, a tarefa de escrever testes unitários pode se tornar bastante difícil, dado ao nível de acoplamento entre essas entidades. Posteriormente neste artigo, são descritas algumas alternativas para lidar com essas questões.

Leia os artigos completos na revista MUNDOJAVA, já nas bancas!


 




 
© 2003 - MundoJava - Todos os direitos reservados <design: www.id-art.com.br >