terça-feira, 26 de agosto de 2008

O NetBeans é uma boa opção

É muito comum observar em fóruns a dúvida de iniciantes sobre qual IDE utilizar, Eclipse ou NetBeans. Construí esse post para expressar/explicar a minha opinião sobre o assunto.

Trabalho com o Eclipse há quase 2 anos, mas sou entusiasta do NetBeans desde a versão 4 e tenho acompanhado atentamente evolução dessa IDE. Procurei escolher a minha IDE favorita de uma forma bem racional.

A idéia da IBM com a construção do Eclipse foi criar uma plataforma de desenvolvimento baseada em plug-ins, dessa forma se uma funcionalidade não existir na IDE qualquer desenvolvedor pode criar um plug-in para a mesma. Logo, o Eclipse na verdade é um contêiner de plug-ins.

Hoje, o Eclipse é a IDE mais usada do mercado, mas esse quadro tende a mudar.

A história do NetBeans começou com a IDE Xelfi construída por dois estudantes da Republica Tcheca, A IDE Xelfi pretendia ser como Delphi para a linguagem Java. A Sun gostou da idéia e comprou a empresa. O nome NetBeans veio da idéia de reutilização de componentes. Em Java os componentes são JavaBeans.

Como IDE, o NetBeans prioriza facilitar o desenvolvimento em Java através de facilidades para implementação de padrões. Como por exemplo:

Desenvolvimento Swing – o Matisse, em minha opinião é sem dúvida nenhuma a melhor ferramenta para desenvolvimento de aplicativos desktop/swing em Java;

Desenvolvimento Web – o NetBeans possuí plug-ins nativos para desenvolvimento em Struts, Google Web ToolKit, JMaki e Para JSF sendo que esse último existe a possibilidade de criar as páginas em modo visual. Como se não fosse não fosse bastante o NetBeans tem um fantástico editor CSS e agora tem facilidades de edição de código JavaScript – somente lembrando, todos esses plug-ins são nativos do projeto NetBeans no máximo é necessário baixar o plug-in pelo auto update;

Persistência de dados – do JNDI ao JPA o NetBeans tem suporte a criação de tabelas, views, índices, chaves estrangeiras e a consultas em modo gráfico (ajuda até quem sabe fazer consultas SQL). Lembrando que no JPA o NetBeans é imbatível.

Outra característica que chama atenção no NetBeans é o suporte ao idioma português do Brasil, apesar do inglês não ser um problema para a maioria dos desenvolvedores esse suporte ajuda muito quem está iniciando.

O NetBeans tem muitas facilidades além das listadas nesse post, porém eu não as conheço suficientemente para comenta-las. Para mais informações visite http://www.netbeans.org/ e http://www.eclipse.org/.

Ao que parece o NetBeans é um projeto em plena atividade e o numero de facilidades que a IDE proporciona aumentou bastante nos últimos anos, se esse quadro se mantiver o NetBeans tende a se tornar a IDE mais utilizada para desenvolvimento em Java.

Utilizando a classe Robot

Depois de mais uma das intermináveis discussões sobre o que dá para se fazer em java e o que não dá para fazer em java. Fui obrigado a pesquisar a classe java.awt.Robot.
A classe Robot está presente no Java desde a versão 1.4.2 e segundo a definição no JavaDoc essa classe é utilizada para gerar input no sistema operacional nativo. Como possível uso o JavaDoc indica a automação de tarefas, apresentação de demos de sistemas e geração de testes.
A classe Robot possui um construtor padrão e outro onde é possível determinar qual o dispositivo de saída padrão (geralmente é o vídeo mas pode ser a impressora). Essa classe possui 15 métodos que eu classificaria da seguinte forma:

Eventos de Teclado:

void keyPress(int keycode) – utilizado para simular o pressionamento de uma tecla;
void keyRelease(int keycode) – remove o status de pressionada de uma tecla utilizada pelo método keyRelease;

Eventos de Mouse:

void mouseMove(int x, int y) – move o mouse para o posição x,y;
void mousePress(int buttons) – pressiona um dos botões do mouse;
void mouseRelease(int buttons) – remove a pressão efetuada pelo método mouseRelease(int buttons);
void mouseWheel(int wheelAmt) – Indica o número de vezes que o scroll será utilizado (aceita valores negativos).

Eventos de Vídeo:

BufferedImage createScreenCapture(Rectangle screenRect) – Captura a imagem existente na tela (na verdade no dispositivo padrão de saída);
Color getPixelColor(int x, int y) – captura a cor do pixel na posição x,y;

Métodos Acessórios:

void delay(int ms) – deixa o a instância de Robot parada (sleeping) por int milisegundos;
void setAutoDelay(int ms) – informa o tempo que a instância da classe Robot deve esperar depois de gerar um evento;
int getAutoDelay() – obtém o valor do autodeley da instância de Robot;
void waitForIdle() – Aguarda até que todos os eventos que estão na fila sejam processados;
void setAutoWaitForIdle(boolean isOn) – define se a instância sempre deve aguardar se todos os eventos da fila sejam processados;
boolean isAutoWaitForIdle() – verifica o estado do autoWaitForIdle;
String toString() – esse método dispensa comentários.

Agora vamos a um exemplo de utilização dessa classe – O exemplo de código abaixo abre a calculadora digita 25+12= e copia o resultado abre o bloco de notas e cola o resultado:

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.IOException;


public class Robo {

private Robot robot;

public Robo() throws AWTException {

robot = new Robot();

}

/**
* Executa um comando no SO..
*/
public void execute(String comando) throws IOException {

Runtime.getRuntime().exec(comando);
robot.delay(5000); // Tempo para o programa abrir

}

/**
* Copia os dados para a área de transferência.
*/
public void copiar() {

robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.delay(2000);

}

/**
* Cola os dados que estão na área de transferência.
*/
public void colar() {

robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.delay(2000);

}

/**
* Executa a digitação de uma sequência de caracteres.
*/
public void executeTeclas(int... keys) {

if (keys != null) {

for (int key : keys) {

robot.keyPress(key);
robot.keyRelease(key);

}

}
robot.delay(2000); // tempo para o usuário ver o que foi digitado

}

public static void main(String[] args) throws AWTException, IOException {

Robo robo = new Robo();


// Número 25 seguido do sinal +
int[] primeira = { KeyEvent.VK_2, KeyEvent.VK_5, KeyEvent.VK_ADD };
// Número 12 seguido do sinal =
int[] segunda = { KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_EQUALS };

robo.execute("calc");
robo.executeTeclas(primeira);
robo.executeTeclas(segunda);

robo.copiar();
robo.execute("notepad");
robo.colar();

}

}

Em outro post apresentarei um exemplo utilizando eventos do mouse e da saída padrão.

Aplicações com Agendamento Utilizando Java

Precisando construir um sistema de monitoração fui apresentado a uma nova necessidade: Agendamento de tarefas utilizando o Java. Para implementação de agendamento de tarefas em Java basta o conhecimento de duas classes:

java.util.TimerTask – Classe abstrata que implementa a interface Runnable. Para criar uma Instância dessa classe é necessário sobrescrever o método run().

java.util.Timer – Essa classe permite que uma instância da classe abstrata TimerTask sejam agendadas e executada como uma Thread ou um daemon.

Chega de teoria, vamos à prática:

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class Task extends TimerTask {

int i = 1;

public void run() {
System.out.println(i + " - " + new Date());

if (i++ == 5) {
System.exit(0);

}

}

}

public class Main {

public static void main(String[] args) {
int inicioApos = 20000;
int tempoParaProximaExecucao = 15000;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new Task(), inicioApos, tempoParaProximaExecucao);

}

}

No código anterior, foi implementada uma Task que é iniciada após 20 segundos do inicio do programa e que roda a cada 15 segundos.

Uma opção para obter o mesmo resultado é utilizar:

timer.schedule(new Task(), new Date().getTime() + 20000, 15000);

Mas o método schedule, com a assinatura acima permite que uma tarefa seja executada qualquer data, basta passar uma instância de java.util.Date com o dia e hora desejado.

Somente as classe padrões para agendamento de tarefas em Java foram úteis para as min as minhas necessidades, mas, para agendamentos mais drásticos existe o Quartz Enterprise Job scheduler (http://www.opensymphony.com/quartz/).

Programação utilizando Java Assert

A palavra reservada assert (premissa) representa um recurso que permite ao desenvolvedor testar condições que deveriam ser verdadeiras. Esse recurso foi introduzido na versão 1.4 do Java e apesar de bastante interessante ainda é pouco utilizado.

Existem duas sintaxes possíveis sintaxes para o comando assert:

assert expressão1; - Essa é a sintaxe resumida, para a expressão1 é permitido apenas operações que retorne um valor booleano;
assert expressão1: expressão2; - Na sintaxe completa a expressão1 segue o mesmo princípio da sintaxe resumida, mas, a expressão2 deve retornar um valor que será impresso caso a expressão1 seja falsa.

Uso indicados do comando assert:

Para forçar restrições de parâmetros em métodos privados – não existe a indicação do uso de assertions para validação de métodos públicos, já que nesses, podem receber “qualquer valor” de outros objetos.
Checar saídas de métodos – de acordo com a entrada passada a um método um valor de saída é esperado, essa é uma boa situação para a utilização de um assertion.

Abaixo um exemplo da utilização de uma assertion:

private boolean candidato(String nome, int idade) {

assert (idade 45): “Idade inválida.”;
//restante do código do método
return true;

}

Quando esse método private boolean candidato(String nome, int idade) for chamado com o software em produção os parâmetros já estariam validados por outras classes da regra de negócio, portanto, o desenvolvedor supõe que o método candidato nunca teria idade fora do intervalo entre 18 e 45 anos, porém no desenvolvimento é interessante efetuar essa verificação debug.

Sempre que um código com assert é executado e a expressão1 é falsa é lançado um AssertionError que é a indicação de um problema na “premissa” utilizada pelo programador. Um AssertionError nunca deve ser capturado pelo programador.

A checagem de assertions está desabilitada por padrão, as linhas com as instruções de assert são inseridas no código compilado são executadas somente se passado o parâmetro enabledassertions no interpretador Java.

Somente lembrando, Assertions não são mecanismos de tratamento de erros, seu propósito é melhorar a disciplina na fase de desenvolvimento.

Internacionalização com a classe Locale

Segundo o Wikipédia, Internacionalização é um processo de desenvolvimento (ou adaptação) de um software em que se busca criar um software que se adapte mais facilmente a determinadas características regionais, legais, culturais e técnicas.

A classe java.util.Locale é destinada a representar regiões geográficas, políticas e culturais na plataforma Java. A principal representação de um Locale é:

import java.util.Locale;

public class Main {

public static void main(String args[]) {

Locale[] idiomas = {new Locale("pt"),
new Locale("fr"),
new Locale("ja"),
new Locale("en")
};

for (Locale idioma : idiomas) {

System.out.println("Idioma: " +
idioma.getDisplayLanguage());

}

}

}

A saída desse código seria:

Idioma: português
Idioma: francês
Idioma: japonês
Idioma: inglês

O exemplo acima mostrou como criar um objeto Locale utilizando apenas o código do idioma desejado. A definição das siglas de cada idioma encontra-se disponível em: http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt.

Uma outra opção de utilização do construtor da classe Locale é acrescentar à definição de idioma o código que representa o país:

import java.util.Locale;

public class Main {

public static void main(String args[]) {

Locale[] idiomas = {new Locale("pt", "BR"),
new Locale("pt", "PT"),
new Locale("fr", "CA"),
new Locale("fr", "FR"),
new Locale("en", "US"),
new Locale("en", "GB")
};

for (Locale idioma : idiomas) {

System.out.println("Idioma: " +
idioma.getDisplayLanguage() +
" - País: " + idioma.getDisplayCountry());

}

}

}

E a saída desse programa é:

Idioma: português - País: Brasil
Idioma: português - País: Portugal
Idioma: francês - País: Canadá
Idioma: francês - País: França
Idioma: inglês - País: Estados Unidos
Idioma: inglês - País: Reino Unido

O segundo exemplo demonstrou o uso do código do país na criação de um objeto Locale. A definição dos códigos dos países está disponível em: http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html.

A última opção de construtor é o que permite adicionar variantes/dialetos específicos:

import java.util.Locale;

public class Main {

public static void main(String args[]) {

Locale portugues = new Locale("pt", "BR", "WIN");

System.out.println(portugues.getDisplayName());

}

}

Agora um exemplo com uma classe que tem suporte à localização: a classe DateFormat:

import java.text.DateFormat;
import java.util.Calendar;
import java.util.Locale;

public class Main {

public static void main(String args[]) {

Locale[] idiomas = {new Locale("pt", "BR"),
new Locale("fr", "FR"),
new Locale("en", "US"),
new Locale("ja", "JP"),
new Locale("ko", "KP"),
new Locale("de", "DE")
};

Calendar c = Calendar.getInstance();

DateFormat dt = null;
for (Locale idioma : idiomas) {

dt = DateFormat.getDateInstance(DateFormat.FULL,
idioma);
System.out.println(idioma.getDisplayName()
+ " - " + dt.format(c.getTime()));

}

}

}

Como resultado:

português (Brasil) - Sábado, 19 de Abril de 2008
francês (França) - samedi 19 avril 2008
inglês (Estados Unidos) - Saturday, April 19, 2008
japonês (Japão) - 2008?4?19?
coreano (Coréia do Norte) - 2008? 4? 19? ???
alemão (Alemanha) - Samstag, 19. April 2008

É interessante observar que nós idiomas coreano e japonês existem caracteres não disponíveis.

É importante lembrar que a classe Locale não faz o trabalho sozinha, para tirar proveito da localização é necessário utilizar classes com esse suporte. Boa internacionalização.

Referências:

JANDL, Peter Jr. Mais Java, Internacionalização, Cap: 2. São Paulo: Futura, 2003.

SIERRA, Kathy & BATES, Bert. Certificação Sun para Programador JAVA 5 - Guia de Estudo (Exame 310-055). Alta Books, 2ª. Edição, 2006.

JavaDoc, Locale, disponível em http://java.sun.com/j2se/1.4.2/docs/api/java/util/Locale.html no dia 19/04/2008.

Wikipédia, Internacionalização, disponível em http://pt.wikipedia.org/wiki/Internacionalização no dia 19/04/2008.

Consultas preparadas com JDBC

Pode parecer estranho falar em JDBC quando existem os frameworks e as APIs para o mapeamento objeto relacional (ORM), mas sempre é bom lembrar que apesar de ocasionar um maior tempo de desenvolvimento o JDBC, quando usado corretamente, proporciona uma maior velocidade de execução.

Sempre que uma consulta SQL é enviada para um banco de dados sua String passa por um processo de compilação, onde é verificado se existem erros de sintaxe e é gerado um plano de execução que é executado.

O processo de executar uma consulta SQL tem um custo de tempo e processamento, mas quase todos os bancos de dados fornecem um recurso que permite que uma consulta seja enviada para o banco de dados, seu plano de execução seja compilado e esse possa ser executado diversas vezes, sendo necessário apenas passar os parâmetros para a consulta. Esse recurso é chamado de SQL preparada.

O JDBC fornece a interface PreparedStantement que estende Stantement e é a forma de acessar o recurso de consultas preparadas em Java. Vamos observar um exemplo de uso do PreparedStantement:

Situação: é necessário inserir em um banco de dados um arquivo de um sistema legado que possui os dados de 50.000 clientes da empresa.

1. A classe Cliente possui a seguinte implementação:

public class Cliente {

private Integer codigo;
private String nome;
private String telefone;
private String endereco;

// Métodos gets e sets

}

2. A classe que acessa os dados do arquivo é uma implementação da interface Iterator:

import java.io.File;
import java.util.Iterator;

public class Dados<Cliente> implements Iterator<Cliente> {

private File arquivo;

public Dados(File arquivo) {
this.arquivo = arquivo;
}
@Override
public boolean hasNext() {
// Informa se existe outro cliente no arquivo;
}
@Override
public Cliente next() {
// código que retorna um cliente;
}
@Override
public void remove() {
throw new RuntimeException("Não foi implementado.");
}

}

Ob.: foi implementado Iterator pois não aconselharia a construção de um método que retornasse uma lista com 50.000 clientes - afinal tudo ficaria em memória.

3. Finalmente a classe alvo desse post o DAO que insere os dados dos clientes no banco:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class ClienteDao {

private Connection connection;

public ClienteDao(Connection connection) {
this.connection = connection;
}

public int inserirRegistros(Dados<Cliente> dados)
throws SQLException {

PreparedStatement ps = null;
int quantidade = 0;

String consulta = "insert into tbcliente(id, nome, " +
"endereco, telefone) values(?, ?, ? ?)";

ps = connection.prepareStatement(consulta);

while (dados.hasNext()) {

Cliente cliente = dados.next();
ps.setInt(1, cliente.getCodigo());
ps.setString(2, cliente.getNome());
ps.setString(3, cliente.getEndereco());
ps.setString(4, cliente.getTelefone());

quantidade += ps.executeUpdate();
ps.clearParameters();
}

return quantidade;
}

}

Na primeira linha a definição da consulta SQL que desejamos executar:

String consulta = "insert into tbcliente(id, nome, endereco, telefone) values(?, ?, ? ?)";

Em seguida é executado o comando que solicita que a consulta seja compilada:

ps = connection.prepareStatement(consulta);

O while serve para adquirir todos os clientes do arquivo:

while (dados.hasNext()) {
Cliente cliente = dados.next();
...

Os parâmetros são inseridos a cada iteração:

ps.setInt(1, cliente.getCodigo());
ps.setString(2, cliente.getNome());
ps.setString(3, cliente.getEndereco());
ps.setString(4, cliente.getTelefone());

Limpa os parametros depois de inseridos no banco.

ps.clearParameters();

Sempre que possível faça uso das consultas preparadas em seus sistemas afinal os benefícios são grandes.

Referências:

REESE, George. JDBC e Java. Programação para banco de dados. Capítulo 4. JDBC Avançada. Editora Berkeley. 2001.

quinta-feira, 14 de agosto de 2008

Java tem ponteiros!?

Na programação em linguagem C um ponteiro é considerado como uma variável que armazena um endereço de memória.
Na programação Java existe dois tipos de variáveis:

As variáveis do tipo primitivo – nesse grupo estão enquadradas as variáveis:

Inteiras: byte, short, int e long;
Ponto flutuante: float e double;
Booleana: boolean;
Caractere: char;

As variáveis de referência a objetos – esse tipo de variável armazena o endereço de memória onde foi instanciado um objeto, ou seja, é um ponteiro para um objeto.

A dúvida se a linguagem Java utiliza, ou não, ponteiros vêm do fato da mesma não possuir um recurso conhecido da Linguagem C: A Aritmética de Ponteiros. Em C, um programador pode acessar livremente a área de memória que quiser, basta informar ao ponteiro o endereço inteiro que representa uma determinada área, alem disso, em C é possível executar um incremento em um ponteiro:

// Código em C
int h;
int *y; // declaração do ponteiro;
h = 30;
y = &h; // atribui endereço de h para o ponteiro y.
printf("Valor em y: %p, Conteúdo de y: %d\n", y, *y);

Em Java, a forma mais comum de obter uma referência para um objeto é através do comando new:

Integer i = new Integer(25);

A exceção mais comum para desenvolvedores Java iniciantes é a java.lang.NullPointerException que é encontrada quando tenta-se utilizar uma variável de referência que não aponta para um objeto.

public class Teste{
    public Integer i; // não foi atribuído valor
     //o padrão é null


    public static void main(String args[ ]) {
        Teste t = new Teste();
        System.out.println(t.i);
    }

}

Lembre-se: Java tem ponteiros. O recurso que Java não tem é aritmética de ponteiros.

domingo, 10 de agosto de 2008

Formatação de datas usando Java

A classe java.util.Date é a principal para trabalhar com datas em Java, mas como na sua construção não ocorreu uma preocupação com a internacionalização, a maioria dos seus métodos são de uso desaconselhado… Talvez esse seja o motivo pelo qual a as perguntas sobre o correto uso de datas em Java sejam recorrente nos fóruns de iniciantes da linguagem.

Parte do pacote java.text a classe DateFormat é a principal classe para formatação de datas utilizando Java. Essa classe suporta internacionalização, ou seja, é possível representar datas em vários idiomas/locais do mundo.

A classe DateFormat é uma classe abstrata, dessa forma, não possui construtor público, mas disponibiliza vários métodos estáticos, que funcionam com Factories, e permitem obter uma instância da classe:

DateFormat.getDateInstance() – obtém uma instância de DateFormat para representação de datas;
DateFormat.getTimeInstance() – obtém uma instância de DateFormat para representação de horas;
DateFormat.getDateTimeInstance() – obtém uma instância de DateFormat para representação de Data/Hora.

Todos os métodos permitem um parâmetro inteiro que representa o estilo e também a utilização do java.util.Locale. Vamos observar um código de exemplo:

import java.text.DateFormat;
import java.util.Calendar;
import java.util.Locale;

public class Data {

public static void main(String[] args) {

Locale brasil = new Locale(”pt”, “BR”);
Locale canada = new Locale(”fr”, “CA”);
Calendar c = Calendar.getInstance();

Integer[] estilos = { DateFormat.DEFAULT, DateFormat.SHORT,
DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL
};

DateFormat dt = null;
System.out.println(”– Brasil –”);
for (int estilo : estilos) {

dt = DateFormat.getDateInstance(estilo, brasil);
System.out.println(dt.format(c.getTime()));

}

System.out.println(”– Canada –”);
for (int estilo : estilos) {

dt = DateFormat.getDateInstance(estilo, canada);
System.out.println(dt.format(c.getTime()));

}

}

}

E obtivemos a seguinte saída:

– Brasil –
13/04/2008
13/04/08
13/04/2008
13 de Abril de 2008
Domingo, 13 de Abril de 2008

– Canada –
2008-04-13
08-04-13
2008-04-13
13 avril 2008
dimanche 13 avril 2008

Nesse exemplo foi apresentada a impressão de uma mesma data em dois idiomas/paises diferentes (Português/Brasil e Francês/Canadá).

É evidente que existem situações onde apenas os estilos predefinidos não atendem, é para essas situações que existe a classe java.text.SimpleDateFormat.

A classe SimpleDateFormat é uma implementação especializada da classe DateFormat e permite que uma data/hora seja formatada utilizando regras menos restritivas do que o Locale/estilo, com essa classe é possível por exemplo representar uma data com somente os dois dígitos da hora. Vamos logo ao exemplo:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class FormatData {

public static void main(String[] args) {

Calendar c = Calendar.getInstance();

String[] estilos = { “dd/MM/yyyy hh:mm:ss”, “dd/MM-yyyy hh:MM:ss”,
“EEEE dd MM yyyy”, “EEE, dd # MMM # yyyy”, “SSS.ss -> MMMM” };

DateFormat dt = null;
for (String estilo : estilos) {

dt = new SimpleDateFormat(estilo);
System.out.println(dt.format(c.getTime()));

}

}

}

Nesse exemplo tivemos a seguinte saída:

13/04/2008 21:48:49
13/04-2008 09:48:49
Domingo 13 04 2008
Dom, 13 # Abr # 2008
468.49 -> Abril

Pelo que podemos observar através da classe SimpleDateFormat é possível realizar qualquer formatação de datas.

Como podemos obsevar, nesse post, a linguagem Java oferece duas classes onde é possível fazer formatações com datas.

Stand up meeting

A cada dia, as Metodologias de Desenvolvimento Ágil tem uma maior atenção dos desenvolvedores. Algumas das ferramentas das metodologias ágeis são altamente criticadas outras podem ser utilizadas em conjunto com qualquer outra técnica/metodologia de desenvolvimento de softwares. Um exemplo de uma boa ferramenta é a stand up meeting (uma tradução seria reuniões em pé).

Uma stand up meeting é uma reunião rápida, de no máximo 15 minutos, que deve ser realizada no inicio de cada dia. A idéia de manter as pessoas em pé durante em uma stand up meeting é incentivar que a reunião termine rápidamente.

O stand up meeting tem como propósito a atualização de todos os membros da equipe sobre as atividades realizadas no dia anterior e informar a todos quais as atividades que serão realizadas no dia atual.

Além do propósito de informar a atividade que cada membro do projeto realizou no dia anterior, uma stand up meeting serve também para que todos do projeto saibam como foi resolvido os problemas encontrados durante o desenvolvimento, com essa informação, se o problema ocorrer novamente todos já sabem como resolver ou quem poderar ajuda-lo nessa tarefa. Um outro propósito para a stand up meeting é definir o que cada membro da equipe vai realizar no dia que se inicia.

Stand up meeting na prática:

Conheci a ferramenta stand up meeting no meu TCC e agora que trabalho em uma equipe geograficamente distante (a minha parte da equipe trabalha em Salvador-BA e a outra parte em São Paulo-SP) tenho adotado essa ferramenta para facilitar o meu trabalho. Mesmo com a distância, a prática de utilizar a stand up meeting possibilita grandes vantagens no desenvolvimento realizado pela equipe.

Referências:

TELES, Vinícius Manhães. Extreme Programming - aprenda como encantar seus usuários desenvolvendo software com agilidade e alta qualidade. São Paulo: Novatec Editora, 2006.

Wikipédia, Stand up meeting, disponível em http://en.wikipedia.org/wiki/Stand-up_meeting no dia 10/08/2008.

Improveit, Reunião em Pé, disponível em http://www.improveit.com.br/xp/praticas/reuniao_pe no dia 10/08/2008.

quarta-feira, 6 de agosto de 2008

Operação com datas utilizando Java Calendar

A principal classe Java para trabalhar com datas é a java.util.Date, porém, essa não apresenta métodos de fácil uso para operações com datas e horas, por esse motivo, fóruns de programação Java são inundados com perguntas de como fazer operações de data e/ou hora.
Operações usando a classe Date:

//Cria uma instância de Date com a data atual:
Date agora = new Date();
System.out.println(agora);


//Adicionando duas horas (7200000 milisegundos)
agora.setTime(agora.getTime() + 7200000);
System.out.println(agora);

Conforme demonstrado a classe java.util.Date trabalha com milisegundos o que gera a necessidade de realizar muitos cálculos para fazer uma operação simples como diminuir um mês por exemplo. Para evitar esses problemas é aconselhável o uso da classe java.util.Calendar:

//Adquirindo uma instância de Calendar
Calendar cal = Calendar.getInstance();
 
// Inserindo a data e hora atual em Calendar
cal.setTime(new Date());
System.out.println(”Dia e Hora atual: ” + cal.getTime());


//Adicionando duas horas
cal.add(Calendar.HOUR_OF_DAY, 2);
System.out.println(”Mais duas horas: ” + cal.getTime());


//Adicionando três meses
cal.add(Calendar.MONTH, 3);
System.out.println(”Mais três meses: ” + cal.getTime());

Além do método add() a classe Calendar fornece o método roll() que permite adicionar um determinado campo (por exemplo hora) sem alterar todos os outros, dessa forma, se forem acrescidas 30 horas a uma determinada variável do tipo Date o dia não será modificado.
Mesmo com todas as facilidades da classe Calendar existem outras API’s construídas por terceiros como, por exemplo, o Joda Time (http://joda-time.sourceforge.net/). Fique a vontade de usá-la caso seja necessário.