Ultimamente vi uma série de posts no meu feed reader coincidentemente encadeados falando sobre padrões de projeto e os considerando genericamente gambiarras.

Tudo comecou no post do Giovane Roslindo Kuhn falando como é legal usar patterns para a comunicação da equipe. O entendimento que se dá no código quando ele é estruturado seguindo convenções estabelecidas em padrões. Claro que esse não é uma das características de se usar um padrão, mas sim um beneficiamento dele (mesmo quando evidentemente não necessitaria haver a presença de um padrão).

Motivado por esse post, o Vítor Ferreira Pamplona escreveu um outro dedicado aos anti-patterns e a prejudicial característica da comunidade java ser reconhecida como a comunidade pattern. Evidenciou a necessidade que programadores empolgados com uma nova linguagem agirem como se essa linguagem fosse uma bala-de-prata e resolvesse todos e quaisquer problemas.

Os próprios padrões de projeto conhecidos podem se tornar um anti-pattern se forem usados para um contexto diferente do que se propõe inicialmente. Quem nunca viu aí uma estrutura cheia de commands para simular MVC em um sistema web levante a mão.

Após o post do Vítor o Thiago Arrais publicou um artigo chamando os padrões de "gambiarra com nomes" que acabou gerando outro artigo do Marcos Tapajós no blog da Improve It na mesma linha.

Concordo com muitos pontos colocados por ambos mas quero fazer uma ressalva, uma gambiarra é uma solução improvisada (deveria também ser temporária) e fora dos procedimentos legais. Um padrão pode ser uma gambiarra mas em essência não é.

Gambiarra "Orientação a Objetos"

Se levarmos ao pé da letra essa consideração podemos então supor que Orientação a objetos seria uma gambiarra, porque os desenvolvedores C já simulavam os conceitos de orientação antes do surgimento do C++, que apenas forneceu ADTs nativos específicos para o desenvolvedor. Linguagens como Smalltalk que foram concebidas tendo em mente a orientação a objetos seria únicas verdadeiras OO mesmo que internamente seu interpretador faça algo parecido com uma linguagem não pura. Mas a única diferença entre as duas é a familiaridade da arquitetura interna da linguagem com o padrão/conceito que se deseja implementar. Uma esconde do desenvolvedor a implementação a outra temos que criar nosso próprio dialeto e não se beneficiar das otimizações e checagens que por ventura a plataforma faça.

Vícios

Temos programadores que acham que podem viver conhecendo apenas uma linguagem e que esta deve servir para tudo, com isso aceitam estruturas estabelecidas mesmo que sejam nocivas.

A Sun criou o conceito de Java Beans para componentes visuais e extendeu esse conceito para sua plataforma Enterprise para designar ADTs que encapsulam suas propriedades.

Hoje a maioria dos desenvolvedores quando codificam suas classes o fazem com um passo-a-passo em mente:

  1. Cria uma classe que representa uma tabela no banco de dados;
  2. Cria as propriedades referentes as colunas nessa tabela;
  3. Atribui private para todas as propriedades;
  4. E por fim cria métodos "set" e "get" para todas as propriedades indiscriminadamente.

Se voce criar uma construção que acesse "objeto.propriedade" é pecado mortal em java, não segue a "convenção".

Em linguagens que implementam o ECMAscript voce tem no BOM (Browser Object Model) o método setProperty(chave, valor) nativo que atribui um valor à propriedade  indicada e não necessita implementar um atribuidor para cada método. Sabiamente não existe um getProperty, voce acessa diretamente.

Em java se uma propriedade é read-only tem coerência voce aplicar um private no qualificador e criar um método getX, outra situação é se voce deseja manipular o valor em tempo de execução, então um método get e ou set tem necessidade. Fora isso  é desnecessário e a propriedade é pública.

Generalidade vs Especificidade

O problema maior com padrões é querer extender uma linguagem além do que ela foi arquiteturada. Como simular Continuations que é nativo da linguagem Scheme, ou Design By Contract do Eiffel. Voce pode fazer ambos em Java, tanto Continuations como DbC podem ser feitas mas com gambiarras, não são inerentes da arquitetura concebida na plataforma Java. Existem até Framework e Container Java que implementam continuations, mas sofridamente.

Inclusive alguns entusiastas do Ruby mais afoitos (A.K.A novatos) fazem bastante algazarra em listas de discussões de como conseguem fazer uma iteração ou outra operação específica com menos linha de código que linguagens como Java ou C++. Claro que é perda de tempo total tentar dialogar e mostrar a necessidade da escolha ideal para o determinado propósito, os programadores de verdade sabem que Ruby também não será o fim dos tempos, conceitos surgirão e retornarão dependendo da situação.

Outra situação depende do ambiente, como simular MVC em uma ambiente web, devido a diferença de contexto do ambiente http em detrimento ao ambiente standalone de um desktop surgiu o famigerado MVC model 2 que deu cria a aberrações como Struts e derivados. Isso hoje pode ser contornado mas ainda é incipiente.

Na mesma forma acontece com padrões, como o contexto de uma linguagem está atrelada a determinado ambiente é vital incorporar conceitos deste contexto na sua semântica e deixar a extensão para o desenvolvedor do que ser genérica e causar improdutividade com tarefas repetitivas, vide sucesso do ruby na construção de aplicações web com o Ruby On Rails.

Em diversas épocas os padrões como Singleton e Factory vão e voltam com desenvoltura, em momento amado e indispensável, outro odiado e suplantado. Mas são padrões universais para resolver um determinado problema, catalogado e disponível para quando forem requisitados.

Padrões são assim, como quase tudo na vida, desnecessários as vezes e se usados com moderação são benéficos. Como dizia minha vó, "tudo demais é veneno".

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.

Uma dificuldade que tenho, e acredito que muitos tem, é de encontrar códigos simples implementados com conceitos de padrões de projeto de desenvolvimento de software, por isso postarei aqui toda semana um exemplo de como implementei algo nesse contexto, de forma que venha ajudar a quem está iniciando no aprendizado e para aqueles que já implementaram podendo contribuir com melhorias no conceito ou sugestões.
Não quero me alongar em histórico de design patterns ou forma técnica de demonstrar um pattern, explicando contexto, problema, solução, etc. Para isso aconselho aos livros clássicos sobre o assunto ou pesquisas em portais que tratam os patterns dessa forma. Vou direto para a dica de implementação com apenas um pequeno descritivo da necessidade de tal padrão.

Necessidade
Para esse artigo inicial vou demonstrar como solucionei uma necessidade de paginação de forma reaproveitavél utilizando os fundamentos da programação orientada a objetos.
O exemplo está utilizando JAVA como linguagem mas pode muito bem ser utilizada em outras linguagens orientadas a objetos.

Padrões
Para solucionar essa necessidade utilizei o Pattern Iterator e o Template Method.

Implementação
Primeiro criei uma Interface onde defini quais métodos seriam implentados para essa necessidade.

Código…

Interface

Classe de Exception auxiliar…

Exception

Então criei uma classe Abstrata que implementa métodos comuns a todas as classes concretas que venham a extendê-la. Um detalhe é que utilizei o conceito de Template Method e deixei alguns métodos a serem implamentados na classe concreta, dessa forma controlo o funcionamento interno de navegação da paginação e deixo aberto para extensão de especificidades da aplicação do programador.

Códigos da classe abstrata…

1
2
3
4
5

Observe que não implementei os métodos:
public String getCmd();
public void setCmd(String cmd);
public Collection getGrid();
deixando a cargo do programador implementá-los.

Não pretendo me ater sobre as funcionalidades de cada método, devo apenas ressaltar que o inteiro cache é relativo ao número de elementos da lista por página.

Utilização
Vejamos como utilizar essa estrutura:

Vamos criar uma classe que seja uma lista de objetos a serem percorridos na paginação.
Essa classe terá que implementar nossa Interface e estender a classe abstrata.

Código da classe…

EquipeListHandler

Vejam que tive que implementar os métodos que a classe abstrata não fez por conta da obrigatoriedade que a Interface causa por implementá-la. Criei um construtor que recebe uma lista de valores e o número de elementos que aparecem em cada página.

Voce instancia em seu controle da seguinte forma:

Business

Esse código é apenas um exemplo de como utilizar a estrutura, existem mais possibilidades.

Na página jsp eu poderia acessá-lo da seguinte forma:

jsp

Utilizo uma variação na criação do Manipulador (Handler), usando uma fábrica para encontrar a classe exata.
Exemplo…

ValueListIterator equipeHandler = ListFactory.getListIterator(”Equipe”);
equipeHandler.setTamanhoCache(10);
equipeHandler.setList(…);

Depois testo se o objeto já está instanciado e se estiver seto o comando especifico.
equipeHandler.setCmd(acao);

Código da Fabrica…

ListFactory

Espero não ter complicado por falta de explicações maiores, mas eu queria somente demonstrar como utilizei determinados Padrões na resolução de uma necessidade específica.

Referências

http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html
http://java.sun.com/blueprints/corej2eepatterns/Patterns/ValueListHandler.html
http://www.corej2eepatterns.com/catalog.htm
http://www.corej2eepatterns.com/Patterns2ndEd/ValueListHandler.htm
http://www.javamagazine.com.br/edicoes/jm21/index.jsp
http://www.javamagazine.com.br/edicoes/jm20/index.jsp

Excelente, de onde retirei grande parte do conceito.
http://www.mundooo.com.br/php/modules.php?name=News&file=article&sid=512

Download do código do artigo
http://www.amigos-list.org/~cmilfont/source/src_pattern_1.zip