| |
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!
|
|