Artigo sobre padrões de projeto (GoF, Singleton, DDD, Fowler, OO, UML)

Olá amigos,

Estou finalizando meu trabalho de graduação sobre padrões de projetos, qualidade de software orientação a objetos. Estou disponibilizando a primeira versão para vocês, caso tenham sugestões, por favor, não deixem de postar.

O arquivo está disponível no googledocs no seguinte endereço http://bit.ly/cZWlb9

Forte abraço!

Bacana, rapaz! Parabéns! Estou lendo aqui e gostei muito do teu texto.

A propósito: acabei de criar um blog no qual pretendo colocar um exemplo detalhado em Java de cada um dos 23 GoF Patterns em:
http://marconems.blogspot.com/

Se tiver sugestões também, serão bem-vindas. Grande abraço.

Só uma observação:

na regra negocial do teu exemplo, podem existir vários tipos de Alertas, certo?

E o código responsável por criar os objetos Alerta está baseado numa estrutura de decisão do tipo switch-case.

Geralmente, esta não é uma boa decisão em projetos OO. Pode não ser o caso do teu exemplo, mas ao se adicionar um novo tipo de Alerta, precisaríamos alterar o switch-case para criar o novo tipo.

Daí, se em outro ponto do projeto você precisa emitir um relatório, também teríamos que alterar o switch-case.

Em outro ponto, o código envia um e-mail baseado no tipo do alerta >> mais manutenção…

Uma boa opção é deixar a fábrica construir os alertas da seguinte maneira:

Map mapaDeAlertas = new HashMap();
mapa.put(“indevido”, new AlertaParadaIndevida());
mapa.put(“foraDeRota”, new AlertaForaDeRota());

Essas atribuições no mapa poderiam estar definidas num arquivo XML, por exemplo.

Daí a Fábrica faria apenas:

public static Alerta getAlerta(String tipo){
return (Alerta) mapa.get(tipo);
}

Neste caso, se você precisar de um novo tipo de Alerta, precisaria apenas criar a classe AlertaTal implementando a interface Alerta, e incluir o mapeamento:

“alertaTal”, new AlertaTal()

O resto inteiro da aplicação não sofreria absolutamente nenhuma manutenção.

Enfim, espero ter ajudado. Qualquer coisa é só enviar uma mensagem. Em breve vou colocar no meu blog um exemplo detalhado sobre isso, que tem a ver com vários padrões, como Flyweight, Strategy, State, AbstractFactory, etc.

[]'s,
Marcone - http://marconems.blogspot.com

[quote=dohko]
Olá amigos,

Estou finalizando meu trabalho de graduação sobre padrões de projetos, qualidade de software orientação a objetos. Estou disponibilizando a primeira versão para vocês, caso tenham sugestões, por favor, não deixem de postar.

O arquivo está disponível no googledocs no seguinte endereço http://bit.ly/cZWlb9

Forte abraço![/quote]

Se eu fosse o seu orientador eu lhe diria que vc está escrevendo, mas não está entendendo. Vc está apenas colecionando citações. seus exemplos mostram que você não entendeu os conceitos. Escolha melhor os seus exemplos, com muito cuidado, pois eles não batem o que o texto diz.

Por exemplo, o texto diz que singleton é legal para rerpesentar um sistema de arquivos, mas o exemplo usa o exemplo da busca de coneções que todo o mundo já sabe que não é um singleton. Conexões são procuradas num Pool ( padrão Object Pool) através de um registro (padrão Registry) ou de um objecto de localização (Service Locator)

O exemplo do modelo anémico tb não é bom. Se vc olha a pai do JMS verá que é exatamente assim, e ninguem se atreve a dizer que o modelo do jms é anémico. Nem o Fowler. Muito cuidado com isso.

Falar sobre padrões e levantar a sua importância não se trata de enumerar todos eles e mostrar exemplos… muito menos quando esses exemplos não correspondem à realidade.

Mantenha seus exemplos coerentes. Não fique pulando de um modelo para o outro. Por exemplo, vc fala de alertas e logo a seguir tenta usar usuario e computador como exemplos. Não apenas vc mudou de dominio, vc mudou de nivel de abstração. isso não leva a lugar nenhum excepto a fazer seu texto parecer disconexo ( vc pegou um exemplo de um lugar, o outro de outro, e fundiu. Não dá a impressão que vc entendeu…)

Precisa estudar mais. (E codificar mais tb)

Sérgio, nao entendi bem sua posição. Na verdade não estou explicando a implementação do Java, como ele trata as conexões, e sim, uma forma de codificar para seu projeto e diminuir problemas de rede. Etendo que as conexão são buscadas em um pool e se você verificar na página 11.

Sérgio, se você verificar a citação da página 8, verá que:

[quote]Para Weisfeld (2004), a diferença chave entre a programação orientada a objetos e a
programação procedural, é que atributos e comportamentos são contidos em um único objeto,
porém no paradigma procedural os atributos e comportamentos são normalmente separados.
[/quote]

assim como fowler diz em

[quote]Fowler (2003), afirma que o
sintoma básico do modelo de domínio anêmico é que a primeira impressão é que isto parece uma coisa real. Eles são objetos, muitos nomeados como substantivos no domínio e estes objetos são interligados com relacionamentos ricos e estruturas que modelos de domínio reais têm. A verdade vem quando você olha para o comportamento, e você percebe que dificilmente existe comportamento para estes objetos, fazendo deles um pouco mais que objetos com getters e setters.[/quote]

Na verdade os padrões não estão enumerados, foi apenas apresentado no artigo, alguns exemplos de aplicação de padrões de projeto.

Oi Sérgio isto é verdade… porém uma forma que achei de fazer uma analogia para um problema simples, pois alerta se trata de um exemplo de projeto real que participei. Os textos são 100% originais, não tendo copiado sequer uma linha, e onde foi feito, foi citado referência.

Precisa estudar mais. (E codificar mais tb) sem dúvidas.

[quote=dohko][quote=sergiotaborda]
Por exemplo, o texto diz que singleton é legal para rerpesentar um sistema de arquivos, mas o exemplo usa o exemplo da busca de coneções que todo o mundo já sabe que não é um singleton. Conexões são procuradas num Pool ( padrão Object Pool) através de um registro (padrão Registry) ou de um objecto de localização (Service Locator)
[/quote]

Sérgio, nao entendi bem sua posição. Na verdade não estou explicando a implementação do Java, como ele trata as conexões, e sim, uma forma de codificar para seu projeto e diminuir problemas de rede. Etendo que as conexão são buscadas em um pool e se você verificar na página 11.
[/quote]

A minha objeção é simples: vc está usando o exemplo errado ( ainda para mais vc mesmo fala isso…). Singleton não passa nem perto de se aplicar a qualquer coisa relativo a conections.
Use o exemplo do sistema operacional ou use as proprias classes singleton que o java tem, para exemplificar.

[/quote]

Isso não significa nada. é texto vazio. OO = dados e comportamento, procedural não. Ok. Isso não tem nada a haver com anémico.

Cuidado. Só porque ele diz que a primeira impressão parece real, não significa que qualquer coisa que pareça real é anémico.
Os objetos mensagem no JMS não são anémicos, mas não tem nada além de get/set.

A anemia advém do contexto e não da implementação. A incorreta atribuição de responsabiliadades é que é o problema.
O exemplo clássico : Conta.getSaldo parece muito bom. Nada anémico. Mas na realidade é uma violação da atribução de responsabilidade.
Porquê ? Porque getSaldo advém dos lançamentos e os lançamentos não estão na conta.

O contra exemplo é o DataUtils.calculaIdade … a idade deve ser calculada por quem a tem…

simplementes colocar as referencias não significa nada…

[quote]

Oi Sérgio isto é verdade… porém uma forma que achei de fazer uma analogia para um problema simples, pois alerta se trata de um exemplo de projeto real que participei.[/quote]

Em sempre use exemplos do mesmo sistema. Ou melhor, pense primeiro nos exemplos que precisa, e escolha um dominio onde eles aparecem.
Se tiver que usar dois dominio , que seja, mas faça isso como ultimo recurso, não como primeiro.

[quote]A minha objeção é simples: vc está usando o exemplo errado ( ainda para mais vc mesmo fala isso…). Singleton não passa nem perto de se aplicar a qualquer coisa relativo a conections.

Use o exemplo do sistema operacional ou use as proprias classes singleton que o java tem, para exemplificar. [/quote]

Sérgio, vc viu que o caso dos sistemas operacionais é uma citação do livro do GoF? na verdade não está relacionado ao meu trabalho e sim apenas uma citação onde ele definia o padrão de projeto. Eu acho que singleton se aplica a conections sim… por exemplo: Faço um simples cliente de ftp… posso usar um singleton para armazenar esta conexão e sempre utilizá-la quando necessária… o pool só se faria necessário quando tivesse mais de uma conexão ou tivesse concorrência (imagine um caso de enviar multiplos arquivos ao mesmo tempo – multithreading).

Sérgio, se você verificar a citação da página 8, verá que:

[quote]Para Weisfeld (2004), a diferença chave entre a programação orientada a objetos e a
programação procedural, é que atributos e comportamentos são contidos em um único objeto,
porém no paradigma procedural os atributos e comportamentos são normalmente separados.
[/quote]
[/quote]

Isso não significa nada. é texto vazio. OO = dados e comportamento, procedural não. Ok. Isso não tem nada a haver com anémico.

Acredito que tenha um significado sim, pois este livro é altamente conceituado… nao sei se ja leu, mas segue o link:
http://books.google.com/books?id=QveDqVtLFIcC&printsec=frontcover&dq=Weisfeld&hl=pt-BR&cd=1#v=onepage&q&f=false

Cuidado. Só porque ele diz que a primeira impressão parece real, não significa que qualquer coisa que pareça real é anémico.
Os objetos mensagem no JMS não são anémicos, mas não tem nada além de get/set.

Até aqui chegamos em uma discussão muito simples… Depende do seu domínio! Na verdade os lançamentos são históricos de operações e não tem nada haver com o saldo… O saldo é um valor e não um campo calculado…

Chegamos a uma discussão complexa… artigo sem referência não tem valor no mundo acadêmico…

Ok, teria alguma sugestão para este caso?

[quote=sergiotaborda] A anemia advém do contexto e não da implementação. A incorreta atribuição de responsabiliadades é que é o problema.
O exemplo clássico : Conta.getSaldo parece muito bom. Nada anémico. Mas na realidade é uma violação da atribução de responsabilidade.
Porquê ? Porque getSaldo advém dos lançamentos e os lançamentos não estão na conta.

O contra exemplo é o DataUtils.calculaIdade … a idade deve ser calculada por quem a tem… [/quote]

Esses exemplos que citou violam a chamada Lei de Demeter e não o Modelo de Domínio Anêmico. Você chegou até a utilizar o termo correto para a situação: responsabilidades. Podem até existir pontos de interseccao das consquencias destes problemas frente aos principios da OO, contudo não devemos misturar as coisas.

[quote=marconems] Só uma observação:

na regra negocial do teu exemplo, podem existir vários tipos de Alertas, certo?

E o código responsável por criar os objetos Alerta está baseado numa estrutura de decisão do tipo switch-case.

[/quote]

Na verdade, aqui trata-se de uma opção minha escolher switch no lugar de IF

Na verdade o caso aqui não é alterar o switch, mas sim centralizar a criação dos alertas em um objeto. Não entendi sua colocação do relatório.

Na verdade o domínio que exemplifiquei não tem tipo de alerta, mas não teria problema algum em adicionar uma enumaration com tipos de alerta.

Isso me parece que você estaria sempre trabalhando com as mesmas instâncias, o que não é ocaso… A fábrica realmente cria o alerta, ou seja, cria uma nova instância para o uso.

[]'s

Então, rapaz, na verdade o uso de IF também não é recomendado, segundo as boas práticas da OO. Tanto que eu me referi à estrutura de decisão, seja ela Swtich ou IF (ou qualquer outra).

Veja bem, não tenho nenhuma intenção de criticar o teu trabalho, aliás, como eu já disse, li e gostei bastante da tua abordagem.

Falando sobre o IF, na verdade, lógicas baseadas em IF têm tudo a ver com a programação estruturada - aliás, são a própria estruturação do código: “SE isso FAÇA aquilo SENÃO faça aquilo outro”. É deixar o código com estruturas fixas. Se um novo caso ocorrer, será preciso dar manutenção na estrutura de IFs já implementada.

Na OO buscamos eliminar os IFs negociais. O Padrão Strategy existe exatamente pra isso. Inclusive, no livro do GoF, página 295, item 3, ele diz explicitamente: “Estratégias eliminam comandos condicionais”, e dá um exemplo justamente para eliminar um Switch.

Estou até preparando um artigo sobre isso, rapaz, vou abordar isso em profundidade, com todos os detalhes, dar exemplos em java, etc. Só pra ter uma idéia, o título vai ser “IF bom é IF morto” (só pra dar uma idéia…rsrsrs). Não deixe de dar uma conferida lá no blog, devo postar semana que vem, acho que pode acrescentar ao teu trabalho aí. No mais, parabéns aí mais uma vez pelo teu trabalho, tenho certeza que será um excelente trabalho e tu vai desenvolver bem o tema.

Abraço,
Marcone - http://marconems.blogspot.com

[quote=FrancoC][quote=sergiotaborda] A anemia advém do contexto e não da implementação. A incorreta atribuição de responsabiliadades é que é o problema.
O exemplo clássico : Conta.getSaldo parece muito bom. Nada anémico. Mas na realidade é uma violação da atribução de responsabilidade.
Porquê ? Porque getSaldo advém dos lançamentos e os lançamentos não estão na conta.

O contra exemplo é o DataUtils.calculaIdade … a idade deve ser calculada por quem a tem… [/quote]

Esses exemplos que citou violam a chamada Lei de Demeter e não o Modelo de Domínio Anêmico. Você chegou até a utilizar o termo correto para a situação: responsabilidades. Podem até existir pontos de interseccao das consquencias destes problemas frente aos principios da OO, contudo não devemos misturar as coisas.
[/quote]

Repare que é a mesma coisa. O modelo é anémico se o Principio de Separação de Responsabilidade (SoC) não está sendo seguido corretamente. Como saber se está sendo seguido ? Respeitando a lei de Demeter.

O getSaldo, como bem disse é uma violação da lei de Demeter, o Pessoa.getIdade, não é. E por isso que o primeiro é anémico e o segundo não.
(Não faz sentido para mim que saldo não seja um campo calculado).

Eu não referi a lei de Demeter no post anterior porque não quiz complicar , mas é exatamente isso que interressa aqui. Esse papo de “modelo anémico” é balela. A verdadeira construção OO se baseia no SoC e na lei de Demeter (que na realidade é um principio e na realidade é uma ferramenta. ela nem sempre pode ser aplicada)

[quote=sergiotaborda]
Repare que é a mesma coisa. O modelo é anémico se o Principio de Separação de Responsabilidade (SoC) não está sendo seguido corretamente. Como saber se está sendo seguido ? Respeitando a lei de Demeter.

O getSaldo, como bem disse é uma violação da lei de Demeter, o Pessoa.getIdade, não é. E por isso que o primeiro é anémico e o segundo não.
(Não faz sentido para mim que saldo não seja um campo calculado).

Eu não referi a lei de Demeter no post anterior porque não quiz complicar , mas é exatamente isso que interressa aqui. Esse papo de “modelo anémico” é balela. A verdadeira construção OO se baseia no SoC e na lei de Demeter (que na realidade é um principio e na realidade é uma ferramenta. ela nem sempre pode ser aplicada)[/quote]

O padrão Business Object viola a Lei de Demeter. Isso é trivial, pois a própria Sun reconhece isso na documentação. A Lei de Demeter e o SoC são conceitos abstratos. O anti-pattern que Fowler descreve é um problema que tem sido recorrente na arquitetura de sistemas corporativos OO, a exemplo o Business Object, apresentado como um viés procedural. A Sun a refere como uma camada orientada a serviços. Não há nada de balela não. Considero um dos artigos mais importantes deste autor.

[quote=dohko]

Isso me parece que você estaria sempre trabalhando com as mesmas instâncias, o que não é ocaso… A fábrica realmente cria o alerta, ou seja, cria uma nova instância para o uso.
[]'s[/quote]

Na verdade não. Se você tem o seguinte mapeamento:

Map mapaDeAlertas = new HashMap();
mapaDeAlertas.put("foraDeRota", new AlertaFora());
mapaDeAlertas.put("indevido", new AlertaIndevido());
//etc

A Fábrica teria o seguinte método:

public static Alerta getInstancia(String chave){
     return (Alerta) mapaDeAlertas.get(chave);
}

Se alguém precisar de Alertas, faria:

Alerta alertaIndevido = Fabrica.getInstancia("indevido");

Ou seja, sempre que alguém invocar o getInstancia da Fabrica, será criada uma nova instância do tipo Alerta - não será a mesma instância, como num Singleton.

Isso foi só um exemplo. Poderíamos melhorar fazendo Map<String, Alerta> mapaDeAlertas = new HashMap<String, Alerta>() para evitar aquele cast no método getInstancia(), etc.

Abraço,
Marcone - http://marconems.blogspot.com

Oi amigo, tudo bom?

Disponibilizei o texto que eu havia te falado:

http://marconems.blogspot.com/2010/06/if-bom-e-if-morto.html

Tem explicações e um exemplo Java completo de como programar sem usar IFs. Espero que seja útil pra você.

Abraço,
Marcone

Olá

A discussão está boa e espero que as ótimas dicas do Sérgio sejam bem aproveitadas.

Tenho uma idéia bem clara na cabeça: quem está começando a programar NÃO deve se preocupar com padrões. Acho que presta um deserviço o professor que ensina padrões antes dos alunos já estarem bem desenvoltos na codificação e principalmente bem habituados na prática de TDD.

Digo e repito até a exaustão. Um programador experiente é capaz de reconhecer e diferenciar padrões pelo cheiro ao longe. Aquele que não muitas horas, dias e meses de código escrito, testado e funcionando, perderá produtividade bloqueado pela tentativa de usar padrões. Principalmente quando se tratam dos padrões de J2EE

Um professor sério só deveria aceitar TCC sobre padrões de alunos que PROVASSEM já ter participado de VÁRIOS sistemas

Primeiro aprendam a programar que em 2010 não pode ser outra coisa senão seguir a sequência básica:

  1. Escrever o teste de aceitação que falha (este passo é recomendado por alguns, me incluo entre eles)
  2. Escrever o teste unitário que não funciona;
  3. Fazer o teste passar;
  4. Refatorar e voltar a (1)
  5. Voltar a (0)

[]s
Luca

Cara, sério mesmo.
Pede para o seu orientador, ou qualquer outra pessoa, analisar metodologicamente o seu trabalho.
Li até a segunda página, e já encontrei: referência inválida (Gang of Four não é referência), referência que não está nas referências bibliográficas (Gang of Four), frase desconexa (“A qualidade da arquitetura em nível de desenvolvimento para que além de um processo de desenvolvimento definido ajude na manutenção…”, sério, li e reli a frase algumas vezes, mas ela continua desconexa. Eu consigo compreender o que ela quer dizer, mas a frase por si só é deconexa), termo meio-traduzido (Gang dos Quatro),
E isso que só li até a segunda página ainda.

Eu falo isso de cadeira, pois ontem mesmo entreguei a 2ª versão da minha proposta de TCC, um documento de 17 páginas, extremamente chato e complicado de se fazer.
E agora vou continuar com o resto da leitura.

edit:
ahhhh, e outra coisa: a ordem das referências deve ser alfabética pelo sobrenome do autor.

[quote=clone_zealot]Cara, sério mesmo.
Pede para o seu orientador, ou qualquer outra pessoa, analisar metodologicamente o seu trabalho.
Li até a segunda página, e já encontrei: referência inválida (Gang of Four não é referência), referência que não está nas referências bibliográficas (Gang of Four), frase desconexa (“A qualidade da arquitetura em nível de desenvolvimento para que além de um processo de desenvolvimento definido ajude na manutenção…”, sério, li e reli a frase algumas vezes, mas ela continua desconexa. Eu consigo compreender o que ela quer dizer, mas a frase por si só é deconexa), termo meio-traduzido (Gang dos Quatro),
E isso que só li até a segunda página ainda.

Eu falo isso de cadeira, pois ontem mesmo entreguei a 2ª versão da minha proposta de TCC, um documento de 17 páginas, extremamente chato e complicado de se fazer.
E agora vou continuar com o resto da leitura.

edit:
ahhhh, e outra coisa: a ordem das referências deve ser alfabética pelo sobrenome do autor.[/quote]

Se vc ver ali verá que coloquei as referências na ordem em que elas aprecem no artigo.

Gang of Four foi um certo “apelido” para definir os integrantes… considerando que eles são mais famosos como gof do que pelo seus nomes…

A qualidade da arquitetura em nível de desenvolvimento <== arquitetura OO (nivel desenvolvimento = desenvolvimento)
processo de desenvolvimento < engenharia de software

[quote=marconems]…
Na OO buscamos eliminar os IFs negociais. O Padrão Strategy existe exatamente pra isso. Inclusive, no livro do GoF, página 295, item 3, ele diz explicitamente: “Estratégias eliminam comandos condicionais”, e dá um exemplo justamente para eliminar um Switch.
…[/quote]@marconems,
Para facilitar o entendimento do aconstantino, q tal (em vez de “jogarmos o Pattern na bucha”)explicarmos os Princípios por trás dos Padrões??!
@aconstantino,
O q o marconems sugere é q vc siga o Princípio “dar preferência a Composição” (Na verdade, o Princípio completo é: ‘Priorizar Composição em relação a Herança’.) Desta forma, ideal seria vc Definir 1 Interface (tb poderia ser 1 Classe Abstrata) para os Seus ‘Alertas’ e Todos os seus Tipos de Alertas implentaria/extenderiam esta Interface/AbstractClass: então, em vez de 1 swich (ou ‘if’) vc poderia ter 1 Collection da Interface/AbstractClass Alerta => desta forma, vc poderia adicionar quantos tipo de Alerta’s quisesse sem alterar uma linha de código deste fonte. Ah, e (hipotéticamente falando, é claro) vc poderia mudar os seus Alerta’s em RunTime (em tempo de execução).
De quebra, vc estaria seguindo outro Princípio de Projeto: ‘Design by Contract’ <=> (comumente traduzido para: ) Programe para Interface e Não para Implementação. Só 1 Observação a respeito deste Princípio: ele não quer dizer necessariamente a Interface do Java; vc pode usar muito bem Classes Abstratas. => explico: a Interface do Java é muito engessada, então se precisar adicionar 1 comportamento (método) a mais, vc vai ter sair fazendo o mesmo em TODAS as Classes q “implementam” esta Interface. Por outro lado, se vc tiver usado Classe Abstrata, esta é muito + flexível.
Espero q agora tenha compreendido o ponto do marconems,

[quote]Para facilitar o entendimento do aconstantino, q tal (em vez de “jogarmos o Pattern na bucha”)explicarmos os Princípios por trás dos Padrões??!
[/quote]

Sim, derlon, você tem toda razão. Inclusive, por isso mesmo, escrevi o artigo a seguir no meu blog, que pretende tratar da forma mais didática possível os 23 Padrões do GoF. Se você puder dar uma olhada e fazer uma crítica, dizer o que você acha, seria importante.

Pelas considerações que você fez no seu post (“Programe para Interface e Não para Implementação”, etc) já deu pra ver que você entende do assunto, logo, sua opinião é importante! Grande abraço e obrigado pelo feedback.

@marcone
Oi Marcone, realmente… vi seu post e acho que o strategy seria legal aplicar aqui… o único problema aqui seria que para adicionar mais um pattern no artigo eu teria que criar um novo tópico no artigo, pois ficaria massante no mesmo tópico dos alertas… por exemplo: Um tópico novo onde seria estudada uma solução melhor para a melhoria daquele código em questão.

@sergio
Pensei também em seguir a mesma linha de exemplos, porém se fizesse estaria dificultado o entendimento, pois estaria utilizando sempre os mesmos exemplos. Li suas idéias sobre o modelo anêmico e acho isso um estudo muito amplo, mas não acho que errei quando citei o livro sobre orientação a objetos. Se você ver ali, na verdade não estou dando exemplo e sim utilizando citações dos livros.

@clone_zealot
Fala André, e ai, vai? Cara… verdade tem uns furos de metodologia ali como nas referências… Já corrigi, embora não concorde com a ordem alfabética e sim com a ordem em que as referências aparecem no texto… Reduzi alguns paragráfos que estavam confusos na versão final. A referencia à GOF eu padronizei todas para Gang of Four como “apelido” para definir os quatro caras.

@marcone

Acho que a minha versão não tinha esse texto… pq era a primeira revisão… coloquei o seguinte texto:

Bom, enfim… embora possa melhorar infinitamente este artigo cheguei ao final dele… fiz algumas revisões e é o que deu pra fazer e espero que tenha sido útil para quem o leu. Coloquei a última revisão no google docs: http://docs.google.com/fileview?id=0B5Ak3Q2yPgp_YTg5MmJiM2ItYmE3YS00MzUxLTgyNmUtMzRlYmYzZjcyMzZi&hl=pt_BR

[]'s