Sou questionado constantemente na Célula JAVA da faculdade Lourenço Filho (da qual fomos os fundadores, eu e o Handerson), sobre o ambiente que uso para desenvolver. Resolvi então criar um post mais direcionado aos novatos para compartilhar essas informações.

Como trabalho exclusivamente com JAVA no meu emprego e tenho seguido minha carreira nessa plataforma, meu ambiente se baseia no Eclipse, a melhor IDE java do mercado.

No trabalho uso o Windows como S.O. e em casa a dobradinha win/lin dual boot, a maioria dos softwares aqui mencionados funcionam nos dois.

IDE

Como mencionado, eu uso como base o Eclipse. Essa IDE tem centenas de plugins bons mas também tem bastante porcarias, já experimentei vários, fiquei com o seguinte ambiente:

Java 6. Sempre instalo a última versão, já conheço as novidades e faço "rêlouordis" para ficar antenado, essa de ficar com java 1.4 instalado não é interessante, afinal a plataforma sempre mantém compatibilidade com as versões passadas de forma extremamente estável (diferente de outro ambiente ali que as coisas da versão 2 não rodam as da versão 1, vai entender o que eles entendem por compatibilidade).

Eclipse como IDE base.

MyEclipse como suíte de plugins para desenvolvimento web e JEE, é o único que não é open source no meu ambiente de trabalho, mas vale cada centavo. O preço é escandalosamente barato para uma ferramenta tão boa.

Aptana, JSEclipse como plugins para html, css e javscript, sendo o último exclusivamente para javascript. o MyEclipse tem editores para esses artefatos, mas não são tão bons quanto o Aptana, eu ainda prefiro o JsEclipse da Adobe no caso do javascript, mas é questão meramente pessoal, em termos de features eles são praticamente a mesma coisa. Ultimamente testei o Spket apenas por curiosidade, por ele já trazer uma integração com o Ext, mas ele não tem diferencial comparado ao Aptana ou mesmo ao JSEclipse.

Container JEE

Tomcat 6 como container web JEE. Por questões de política do meu trabalho tenho que usar o Oracle AS10g como servidor de aplicações, preferiria o JBoss por inúmeros fatores (indiferente de questões filosóficas), mas uso o tomcat para testar todas as aplicações. Obviamente temos que nos policiar quanto às últimas novidades porque a Oracle sempre está alguns passos atrás (medidos em versões) dos outros servidores. Não temos nenhuma aplicação (pelo menos sob minha orientação) que use EJB, como não temos nenhum sistema distribuído e dificilmente teríamos (pelo contexto do nosso trabalho), nunca tivemos tal necessidade.

Banco de dados

Oracle 10g. Diferente do servidor de aplicações, o banco da Oracle na minha concepção é o melhor que existe (alguns dizem que é o IBM DB2, mas eu acho o Oracle). Mas mantenho o brinquedo MySQL instalado para testar as coisas devido a facilidade de instalação e manipulação.

Uso o programa DbVisualizer (que é feito em java) para trabalhar diretamente com os bancos de dados. Ele tem recursos menores se comparado às ferramentas nativas que são disponibilizadas pelas Players dos próprios bancos, mas como acessa todos os bancos que acesso diretamente: SQL Server (legado), MySQL (testes) e Oracle (produção e desenvolvimento), tenho preferência por ele.

Integração Contínua

Não temos um ambiente que enfatize a integração contínua e metodologias ágeis, nossa metodologia tem como base ainda se espelhar no IBM RUP (apesar de não ser o RUP).

Usamos o DotProject (provisoriamente) como gerenciador dos projetos. Não é a melhor ferramenta, aliás é muito fraca de ser considerada uma boa ferramenta, mas por enquanto o custo/benefício dela está falando mais alto, mas já existem movimentos de substituí-la. Esse é um exemplo de que a filosofia não deve falar mais alto que os aspectos técnicos, tínhamos uma base no uso do MSProject, que é muito superior ao DotProject, mas foi relegado em nome do Software Livre pela desculpa dos custos. Esse é um ponto onde o SL sempre perde pontos. Talvês existam softwares livres melhores que o DotProject que poderiam ter sido comparados ao MSProject, mas trocar um software que está funcionando corretamente por questões de custos não é uma boa alternativa, afinal o ROI medido posteriormente desmereça essa troca.

Nosso sistema de controle de versões é o velho e fantástico CVS que já tem suporte nativo excelente no Eclipse, mas vamos mudar para o SVN nesses próximos dias, posteriormente blogarei sobre essa mudança. Existe uma equipe que trabalha com o MSSourceSafe que deverá usar o SVN também, vamos ver o que vai sair dessa mudança, sinceramente eu não tenho opinião final formada sobre isso. Acredito que pode não ser uma boa idéia, já que essa equipe trabalha com DotNet e a integração entre o VisualStudio e o Sourcesafe seja bem melhor (evidente) que com o SVN, vamos ver.

Como eu mencionei, não enfatizamos (infelizmente) os métodos ágeis, mas tento seguir as boas práticas do XP, como não tenho um sistema de geração de builds, tento controlar usando o velho Apache Ant mesmo, tenho um script antigão aqui que coordena o processo inteiro, quem sabe não tenhamos um CruiseControl por aí em breve (que seria um salto extraordinário), quem sabe.

Agora nosso "Calcanhar de Aquiles" é o sistema de Issue Tracking daqui, é uma solução In House H-O-R-R-Í-V-E-L (como ficou gay meigo essa declaração). Já está sendo providenciado outra solução, mas In House também o que é uma pena devido a enorme lista de sistemas excelentes que existem por aí.

Last But Not Least…

O mais importante não é montar um ambiente de desenvolvimento ou simplesmente achar que conseguirá manter o mesmo pelo resto da vida e sim ter consciência de quais são as necessidades e como suplantá-las sempre procurando a melhor ferramenta que se adapte aos seus projetos. Espero que esse post ajude aos novatos como um passo inicial para pesquisar sobre aquilo que melhor o satisfaz na busca por um ambiente produtivo.

Ultimamente estou usando uma abordagem diferente para a persistência. vinha adotando os pattern de ActiveRecord e Repository além do DataMapper popularmente conhecido como DAO. Aperfeiçoei com essa dica do CV no guj.
Apesar da persistência ser arquitetural e teoricamente não fazer parte do dominio dos seus processos de negócios, invariavelmente é a maior preocupação na construção de um software o “como” e “onde” um objeto tem que mudar seu estado persistido. Em outras palavras como isolar a persistência de seu domain model para que a transparência dessa operação diminua o código sem aumentar os pontos de manutenção com alta coesão e fraco acoplamento.

Estados do objeto
Os objetos do ponto de vista do modelo de um processo apresentam estados, como excluído, alterado e criado. Podemos adotar o conceito de Active Record no domain model e fazer com que seus objetos implementem uma interface que sem criatividade no momento chamarei de ActiveRecord:

public interface ActiveRecord {
	public void carregado();
	public void novo();
	public void alterado();
	public void excluido();
}

Podemos então criar uma classe abstrata seguindo o pattern Template Method para criar uma estrutura básica para todos nossos objetos que chamarei de AbstractActiveRecord:

public abstract class AbstractActiveRecord < t extends AbstractActiveRecord >
		implements ActiveRecord {

	public void carregado() {
		Repository.carregar(this);
	}

	public void alterado() {
		Repository.alterar(this);
	}
…
}

Resolvi chamar o Repository dentro do Template do ActiveRecord para deixar isolado os DAOs da aplicação de criar apenas um ponto de manutenção em comum.
O conceito de Repository deixa o sistema isolado da infraestrutura de persistência funcionando como um espécie de banco de dados em memória que os objetos se dirigem ao perguntar por alguém (Alguém esse referente a uma entidade do dominio).
Observe que as classes do meu sistema devem extender a classe AbstractActiveRecord e implentar a interface ActiveRecord, mas isso não é se prender a um framework, porque essas classes fazem parte do dominio apesar de existirem para resolver um problema arquitetural, elas são do meu sistema, e estão independente de infraestrutura porque são relativos do dominio de qualquer forma.
Uma entidade do meu sistema fica assim:

public final class Cliente extends AbstractActiveRecord implements ActiveRecord {
	private int id;
	private String nome;
	private String cpf;
	//gets e sets
}

O Shoes tinha me dado um conselho de usar o Repository junto com o Active Record e DataMapper a um tempo atrás para isolar o modelo da persistência principalmente na lista de entidades, exemplo:
Cliente cliente = RepositorioClientes.carregaListaClientes();
Mas eu resolvi criar um repositório genérico para todas as entidades e dentro dele inserir uma chamada a uma fábrica de DAOs apropriado dependendo do tipo o objeto. Código do meu Repository:

public abstract class Repository {
	public static void carregar(ActiveRecord record) {
		System.out.println("carregou quem? " + record.getClass().getName());
		//faz o trabalho de persistencia... pode fazer injeção etc...
		//pode chamar uma Fabrica para criar o DAO a partir da classe
		// FabricaDAO.criarDAO(record.getClass());
	}
...
}

realizando um teste simples para ver como se comportaria:

public class TransacaoTest extends TestCase {
	public void testTransacao(){
		Cliente christiano = new Cliente();
		christiano.setNome("christiano");
		christiano.setCpf("999.999.999-99");
		christiano.novo();
		assertEquals(1, christiano.getId());
		//acontece mais algumas coisas...
		//e lá pelas tantas...
		christiano.setNome("Christiano Martins");
		christiano.alterado();
		assertEquals("Christiano Martins", christiano.getNome());
	}
}

O resultado foi como esperado, o processo vai modificando o estado dos objetos durante a transação e tornando o código mais legível, evitando chamar DAO dentro do meu modelo ou misturar código de framework como Hibernate ao meu domínio.
Com exemplos simples em transação praticamente CRUD a coisa funciona legal, quando precisamos alterar ou pra Lazy Loading ou Eager Loading dependendo do padrão da aplicação (deixo como padrão lazy), passamos um parâmetro para a estrutura como por exemplo:

normal
Cliente cliente = new Cliente(10); // esse construtor já invoca a estrutura e carrega as informações
com lazy Loading
Cliente cliente = new Cliente(10, ActiveRecord.LAZY_LOADING);
...
Construtor normal:
	public Cliente(int id) {
		super();
		this.id = id;
		this.carregado();
	}
Construtor parametrizavel
	public Cliente(int id, int LOADED_PARAMETER) {
		super();
		this.id = id;
		this.carregado(LOADED_PARAMETER);
	}
...

De qualquer forma podemos criar uma estrutura de modelo do domínio do meu processo isolada da arquitetura tecnológica facilitando a manutenção com padrões de projetos simples, código mais enxuto e transparência nas transações.

Caros, venho por meio desta apresentar mais dois livros.
Recentemente falei que não comprava mais livro traduzido, eis que posso queimar minha língua enorme! O Dalton Camargo do JavaFree participou da tradução do livro Spring in Action , veja o link de como comprar na promoção.

Outro bom material que folhiei recentemente e vou comprá-lo é o livro do Vinícius Manhães Teles, Extreme Programming.

Mas como já falei prefiro material gerado no Brasil, por razões simples, o conhecimento é adaptado à s nossas realidades, desde que esse material seja bom devo ressaltar, e esse livro é bom… bom não, ótimo.

Ultimamente tenho estudado os autores clássicos de desenvolvimento ágil como Kent Beck, Martin Fowler, Robert C. Martin, etc e sofrido bastante. Tendo revisto meus projetos anteriores vi como minha modelagem se baseava no AnemicDomainModel como citado nesse artigo do Fowler.
Todos meus sistemas se pareciam como uma implementação do catálogo de patterns da SUN como se aquilo fosse uma interface.
Recentemente tive oportunidade de ser o responsável por todo o ciclo de desenvolvimento de um projeto pequeno com poucos requisitos funcionais, tinha ao todo uns 10 casos de usos tirando o aspecto CRUD da aplicação.
Pude realizar algumas experiências com conceitos que eu estava estudando a algum tempo e alguns que eu conhecia mas nunca tivera oportunidade de implementar.
Estou planejando um artigo mais elaborado sobre essa experiência, mas por enquanto posso adiantar alguns sentimentos sobre tudo isso.

Test-Driven Development
Essa prática do XP realmente é muito mais produtivo, eu sempre realizei os testes depois que as classes estavam desenhadas e até com métodos implementados, mas nesse sistema eu simplesmente aboli os diagramas de classes da UML, tentei fazer tudo radicalmente, fui separando as classes que eu achava que existiam no dominio da aplicação com cartões CRC, mas depois abandonei os cartões e fui direto para os “Unit Tests”, outro princípio que segui do XP foi fazer os casos de uso importantes primeiro, CRUD eu nem toquei, o banco de dados foi a última coisa que fiz. Fui criando os Unit Tests (UT) e os objetos foram surgindo naturalmente a partir dos requisitos funcionais que respondiam pela cerne do sistema, quando terminei o modelo praticamente tinha o sistema concluido, apesar de não ter nenhum select implementado. Nesse momento eu não sabia como seria a performance ou se teria que refatorar tudo aquilo para se adequar ao banco mas sentia que a aplicação estava terminada, diferente de todas as vezes onde fiz os CRUDs primeiro (que correspodem por cerca de 80% das aplicações ou mais) e praticamente via um túnel sem fim pela frente.

Domain Model
Meu modelo criou classes que a muito tempo não via (acho que desde os sisteminhas de locadora da faculdade). Minhas classes não são apenas tabelas em memória como repositório de dados, elas conhecem suas responsabilidades e seus dados como descrito nesse pattern do Fowler, acredito que as classes criaram até sentimentos (risos!).
Minha forma de pensar era um Bean que mais parecia uma tabela e que viajava da persistencia até o jsp, furando tudo pelo caminho, então dessa forma pude testar todo o sistema praticamente de minhas classes de testes no JUnit usando refactoring a todo momento e criando um modelo estável e que realmente está testado e terminado. Minhas classes sabem fazer o que tem que ser feito, ou seja, elas tem suas responsabilidades, olha só essa frase:

Procedural code gets information then
makes decisions. Object-oriented code tells
objects to do things.
— Alec Sharp

Acho que já to programando OO!

Design by contracts
Pude implementar os conceitos DbC nesse projeto, aliás quando voce desenvolve criando os testes primeiro isso flui quase que naturalmente, basta uma polida nos conceitos e pronto, um bom lugar para isso é esse artigo do Phillip Calçado sobre o tema.

Futuro
Algumas coisas não puderam ser implementadas como Dependency Injection, Aspect Oriented Programming, Pair Programming, Continuos Integration, etc. Esses conceitos vão ficar para os próximos projetos, pretendo adotar Hibernate e Spring na próxima e ver o que essas boas práticas são capazes, vou primeiro tentar convencer minha equipe a adotar o XP como metodologia, aí veremos, qualquer coisa esses conceitos já me foram uteis, aguardem novidades.