quinta-feira, 16 de outubro de 2008

Entendendo o padrão de projeto Adapter

Então, faz muito tempo que não posto neste blog, mas agora estou com internet de novo em casa, posso tentar atualizar meu blog com mais freqüência. Vou postar outra coisinha simples, mas que muita gente não conhece, relacionado a padrões de projeto (design patterns), um assunto que eu considero o mais, senão um dos mais importantes para alguém que trabalha com orientação a objetos.

Um padrão de projeto é uma solução comum para um determinado problema, existem 23 padrões "clássicos" para programar orientado a objetos, eles são conhecidos como os 23 padrões GoF (Gang of Four devido as 4 pessoas que criaram eles), além desses 23 padrões clássicos existem ainda padrões J2EE (recomendados pela SUN), padrões GRASP (General Responsibility Assignment Software Patterns) entre outros. Qualquer um pode "criar" um padrão, eles surgem de acordo com a evolução das arquiteturas e do desenvolvimento dos sistemas.

Hoje vou falar de um padrão do GoF que eu costumo usar conhecido como Adapter, esse padrão tem como objetivo converter uma interface de uma classe em outra interface esperada pelos clientes, exemplos da utilização pode ser visto na API padrão do java para tratamento de eventos (MouseAdapter, WindowAdapter), Wrappers (Integer, Double), etc. Existem duas formas de Adapter: Class Adapter que utiliza herança múltipla e Object Adapter que utiliza composição. Class Adapter é usado quando o cliente alvo que eu quero adaptar possui uma interface estatica, Object Adapter é usado quando se deseja menor acoplamento ou quando o cliente alvo que quero implementar não usa interface.

Mas vamos aos códigos. Imagine que estamos utilizando um framework de cinema, que possui uma classe para representar filme, uma interface que define ator, e uma classe que representa o ator principal (só para existir uma implementação de ator). Em um filme eu posso incluir vários atores e então rodar o filme:

public interface Ator {

 void representar();

}

public class Filme {

 private List<Ator> atores = new ArrayList<Ator>();

 public void addAtor(Ator ator) {
  atores.add(ator);
 }

 public List<Ator> getAtores() {
  return Collections.unmodifiableList(atores);
 }

 public void rodaFilme() {
  for (Ator ator : atores) {
   ator.representar();
  }
 }
}

public class AtorPrincipal implements Ator {

 public void representar() {
  System.out.println("Ator principal representando");
 }

}

Essas são classes e interfaces do framework de cinema, eu não posso alterar. Agora imagine que eu tenho meu sistema que possui pessoas, e um comportamento dessas pessoas é andar:

public class Pessoa {

 public void andar() {
  System.out.println("Pessoa andando");
 }

}

Com essa minha classe de pessoa, eu queria incluir figurantes no meu filme, pessoas que não são atores, só para ficar andando lá, fazendo número no filme, porém não posso alterar a interface do filme para receber pessoas, o que eu faço?! Adapto pessoa para ser ator, dessa forma:

public class Figurante1 extends Pessoa implements Ator {

 public void representar() {
  andar();
 }

}

Nesse caso eu usei Class Adapter, pois adaptei a classe pessoa a um ator. Porem esse adaptador não serve para qualquer pessoa, ele é uma nova Pessoa, nova classe, ele não adapta pessoas já existentes a um ator, eu tenho que criar realmente um figurante novo, não adaptar uma pessoa, por isso Class Adapter. Caso você precisasse adaptar qualquer pessoa a um figurante, essa não seria a melhor forma, o ideal é que a classe figurante (adaptadora) fosse dessa forma (usando object adapter):

public class Figurante2 implements Ator {

 private Pessoa pessoa;

 public Figurante(Pessoa pessoa) {
  this.pessoa = pessoa;
 }

 public void representar() {
  pessoa.andar();
 }

}

Ambos são adaptadores, qual usar? Depende do que você quer, em minha opinião, o perfeito é dar as duas opções, eu adaptar uma pessoa já existente ou eu criar uma nova pessoa que já é um figurante, para isso pessoa deveria ter uma interface, e ai meu figurante seria dessa forma:

public class Figurante3 implements Ator, InterfaceDePessoa {

 private InterfaceDePessoa pessoa;

 public Figurante(InterfaceDePessoa pessoa) {
  this.pessoa = pessoa;
 }

 public Figurante() {
  this.pessoa = new Pessoa();
 }

 public void representar() {
  pessoa.andar();
 }

 public void andar() {
  pessoa.andar();
 }

}

Isso me permite adaptar qualquer pessoa a um figurante, bem como criar um novo figurante do "zero", ou seja, é uma junção dos dois figurantes apresentados anteriormente. Mas, meu sistema não tem uma interface de Pessoa e eu não quis criar, então vou usar meus dois primeiros figurantes:

public class Main {

 public static void main(String[] args) {
  Ator a1 = new AtorPrincipal();  //um ator de verdade
  Figurante f1 = new Figurante1();  //uma nova pessoa que ja nasceu Figurante
  Pessoa p1 = new Pessoa();  //uma pessoa normal
  Figurante f2 = new Figurante2(p1);  //a pessoa normal adaptada a figurante

  Filme filme = new Filme();
  filme.addAtor(a1);
  filme.addAtor(f1);
  filme.addAtor(f2);

  filme.rodaFilme();
 }

}

Agora vamos evoluir, achei um framework que gerencia tarefas, e eu quero incluir tarefas que ao serem executadas fazem com que todos os atores do filme representem. Esse framework tem uma classe abstrata que representa uma tarefa e um gerente de tarefas:

public abstract class Tarefa {

 public abstract void executar();

}

public class GerenteTarefa {

 public void executar(List<Tarefa> tarefas) {
  for (Tarefa tarefa : tarefas) {
   tarefa.executar();
  }
 }

}

Mas repare que não tenho uma interface de tarefa, então como vou adaptar atores (qualquer ator, até mesmo o figurante) a tarefas?! Solução: Object adapter, ou seja, vou criar meu adaptador a partir de objetos com composição (mesma idéia do figurante2, pois eu quero adaptar qualquer ator a tarefas):

public class AdaptadorDeAtor extends Tarefa {

 private Ator ator;

 public AdaptadorDeAtor(Ator ator) {
  this.ator = ator;
 }

 public void executar() {
  ator.representar();
 }

}

Repare que eu não adaptei a classe, meu adaptador não é um novo ator, ele é uma tarefa que delega seu método “executar” para um objeto de ator, ele adapta qualquer ator a tarefa, executando isso:

public class Main {

 public static void main(String[] args) {
  Ator a1 = new AtorPrincipal();  //um ator de verdade
  Figurante f1 = new Figurante1();  //uma nova pessoa que ja nasceu Figurante
  Pessoa p1 = new Pessoa();  //uma pessoa normal
  Figurante f2 = new Figurante2(p1);  //a pessoa normal adaptada a figurante

  Filme filme = new Filme();
  filme.addAtor(a1);
  filme.addAtor(f1);
  filme.addAtor(f2);

  filme.rodaFilme();

  List<Tarefa> tarefas = new ArrayList<Tarefa>();
  for (Ator ator : filme.getAtores()) {
   tarefas.add(new AdaptadorDeAtor(ator));
  }

  GerenteTarefa gt = new GerenteTarefa();
  gt.executar(tarefas);
 }

}

Ou seja, consegui adaptar minha classe Pessoa para um ator e depois adaptei um ator para tarefa, usando Class e Object Adapter. Entendendo isso, você consegue adaptar qualquer classe para praticamente qualquer interface, talvez muita gente já fez isso, mas não sabia que tinha nome. Para quem nunca usou, pense bem, pode ser muito útil na reutilização de código, integrar sistemas e pode ajudar bastante a melhorar o desenvolvimento.

segunda-feira, 26 de maio de 2008

Scrum, meu novo interesse

Semana passada eu fiz um curso de scrum na caelum, eu não tenho tempo nem conheço tanto para explicar como funciona scrum em geral, mas as impressões que fiquei foram muito, mas muito boas mesmo.

Parece uma metodologia que, ao mesma tempo da muita liberdade para o time (desenvolvedores), mas é cruel com pessoas que não rendem, os espertinhos, “enroladores”, pois a cobrança não vem de cima, vem dos lados, dos próprios companheiros de time. A metodologia é baseada muito na confiança da equipe, é uma confiança controlada através de reuniões diárias, mas que faz com que o desenvolvedor se sinta bem desenvolvendo. O scrum me parece realista para a maioria dos problemas de desenvolvimento de sistemas e alguns sociais que podem existir em uma equipe, nele você sabe que o cliente vai mudar os requisitos, você sabe que o programador não vai cumprir exatamente o tanto de horas que ele orçou, trabalha muito com feedback, sinceridade entre a equipe e o mais fantástico, a própria metodologia oferece recursos que ajudam a trabalhar e melhorar isso, como as reuniões diárias e retrospectiva, tudo visando o bem da equipe e não apenas da pessoa. Acho que o sentimento de alguém que trabalha dessa forma é: “eu prefiro ser o goleiro do time vencedor do campeonato, do que um excelente goleiro de um time rebaixado”.

Bom, estamos tentando adotar scrum aqui na empresa (já eheh), o que o Alexandre (nosso instrutor) disse na aula parece que aconteceu, santo de casa não faz milagres, embora agente explique e as pessoas estudem a metodologia, elas duvidam que funcione, por mais que você fala, elas duvidam e querem até mesmo mudar a forma como scrum é, impondo mais responsabilidades de controle da equipe ao scrum master, mudando o planning poker, mudando a reunião de planejamento, enfim, alterando a forma como scrum trabalha, inserindo itens que acabam com toda a vantagem que a metodologia oferece. Mas, eu estou bem confiante, consegui passar a importância de se seguir a metodologia, o porque que é assim, e no fim, acho que vamos seguir o planejado e o certo, espero dar tudo certo e provar que realmente funciona.

Sobre o curso eu aconselho todos que façam porque realmente é bom, scrum é uma metodologia simples, com técnicas bem sociais e realistas, mas que se for pensar bem, é ideal para desenvolvimento de sistemas.

Ai a foto da galera que participou do treinamento (roubada do blog do Alexandre):

sexta-feira, 25 de janeiro de 2008

Criando um Scope ThreadLocal no Guice

Eu comecei a estudar um pouco o Guice, que é um framework da google de injeção de dependência. Estava fazendo uns testes e queria ter uma forma de que o Guice me retornasse sempre a mesma instância quando solicitar um objeto na mesma thread, algo como se feito com esse Factory:

public class ServiceFactory {

 private static ThreadLocal<Service> tl = new ThreadLocal<Service>();

 public static Service get() {
  Service t = tl.get();
  if (t == null) {
   t = new ServiceImpl();
   tl.set(t);
  }
  return t;
 }
}
Porém não achei um scope para isso (na real procurei bem pouco). Resolvi, até para aprendizado criar um novo scope para que seja ThreadLocal, até que deu certo, eis o resultado:
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
...

class LocalThreadScope implements Scope {
 public <T> Provider<T> scope(Key<T> key, final Provider<T> provider) {
  return new Provider<T>() {
   ThreadLocal<T> tl = new ThreadLocal<T>();

   public T get() {
    T t = tl.get();
    if (t == null) {
     t = provider.get();
     tl.set(t);
    }
    return t;
   }
  };
 }

 @Override
 public String toString() {
  return "ThreadLocalScope";
 }
}
Usando-se esse Scope para fazer o bind, o Guice ira criar um novo objeto para cada thread diferente. Exemplo:
public interface Service {
 void go();
}

public class ServiceImpl implements Service {
 public void go() {
  System.out.println(this + " - " + Thread.currentThread());
 }
}

public class MyModule implements Module {
 public void configure(Binder binder) {
  binder.bind(Service.class).to(ServiceImpl.class).in(
    new LocalThreadScope());
 }
}


public class Main {
 public static void main(String[] args) {
  final Injector inj = Guice.createInjector(new MyModule());
  Service s = inj.getInstance(Service.class);
  s.go();
  s = inj.getInstance(Service.class);
  s.go();
  Runnable r1 = new Runnable() {
   public void run() {
    Service s = inj.getInstance(Service.class);
    s.go();
   }
  };
  new Thread(r1).start();
 }
}