Arquivo de Agosto de 2009

Rodrigo Yoshima

Aspercom no Rails Rumble 2009

No próximo final de semana, mais especificamente das 21:00hs da sexta-feira às 21:00hs do domingo, estarei participando do Rails Rumble. Para quem não conhece, o Rails Rumble é muito simples: É uma competição onde você e mais 3 amigos devem fazer uma aplicação, um website ou produto usando Rails em 48 horas. A melhor aplicação vence! Simples né?

rr09 badge 125 - rr09 badge 125
A equipe conta com Felipe Oliveira Kenobi (nosso sensei SOA), Cauê Guerra (nosso Jedi Rails) e Alexandre Theodoro (nosso expert em Web Design). O projeto é um site para os eventos do tipo Flash Mob estendido ao conceito de redes sociais, onde um usuário poderá criar eventos, notificar seus amigos sobre o mesmo, compartilhar as experiências agregando opiniões de diversos partipantes, registrar seus momentos em diferentes mídias e torná-las acessíveis à partir de um único ponto.

Olhando pela visão tecnológica, o projeto não pretende reiventar a roda. Serão integradas plataformas pré-existentes divididas em: Conteúdo (Digg.com), Mídia (Flickr e Youtube), Calendário (sistemas como Google Calendar e Yahoo UpComing), oAuth para registro do usuário, OpenSocial Platform (Google), Maps e sistemas de microblog (Twitter). Resumindo, muitos mashups em cima de um modelo baseado em WOA.

Link para o projeto: http://r09.railsrumble.com/teams/brazilian-dojo

A participação das equipes brasileiras no Rails Rumble é um patrocínio muito legal da Gonow. Durante o evento, a Gonow estará cedendo o seu espaço e infra-estrutura para as 3 equipes participantes. Além disso, estará também fornecendo hospedagem e alimentação durante o evento. Não só isso, a Gonow também estará filmando tudo (um Big Brother Developer Brasil).

null

Fazer uma aplicação completa num curto espaço de tempo é um desafio técnico e também para a gestão do “projeto”. Como havia relatado aqui anteriormente, no projeto da DDWorks, tínhamos o desafio de entregar um e-commerce em 40 horas (uma semana). Trabalhamos com iterações diárias. Minha experiência nesse tipo de projeto poderá ajudar no Rumble. Basicamente, o que aprendi foi: baby steps são amigos, use histórias bem pequenas, integração contínua insana, coloque os incrementos no ar o mais rápido possível e veja bem o quanto você investe em testes. Espero que isso também ajude as outras equipes!

Neste projeto do Rumble será uma experiencia diferente. A equipe trabalhará tanto no Tech como no Business e vejo que a junção dos skills está favorecendo muito o projeto. Nós decidimos fazer iterações de 3 horas, com 30 minutos de retrospective e planning. Vamos trabalhar em pares, integrando em não mais que 30 minutos. Estamos também separando alguns momentos para descanso dos participantes. Esperamos estar vivos para comemorar no domingo com todo mundo.

É bem provável que estaremos postando muita coisa no Twitter neste fim de semana. Siga: @scaphe, @caueguerra e @rodrigoy.

Rodrigo Yoshima

Repositórios: pra que te quero?

Domain-Driven Desing não é sobre padrões - isso gera muita discussão. Domain-Driven Design (ou simplesmente DDD) é sobre fazer software de maneira mais simples - e sei que muitos não vão concordar com isso, pois “parece” que é mais fácil e muitos se sentem muitos produtivos ligando Table Modules diretamente às telas e abusando de Transaction Scripts.

O objetivo deste artigo não é falar sobre o que a literatura diz sobre repositórios e nem tenho a pretensão de escrever o “post definitivo sobre Repositórios”. O objetivo aqui é demonstrar como tenho aplicado Repositórios nesses 3 anos de experiência em aplicação e ensino de DDD.

O que são Repositórios afinal?

Antes de mais nada, orientamos a aplicação ao domínio. O exemplo que vou montar aqui não é real, mas é bem próximo daquilo que apliquei em alguns projetos. Orientar a aplicação ao domínio significa que seu código será limpo e principalmente sua camada de negócios demonstrará o NEGÓCIO, suas regras, seu estado e suas associações. Se sua aplicação é de vendas, é esperado que o vocabulário do domínio “vendas” seja encontrado nas suas classes. As classes do domínio também não devem ser poluídas com o domínio técnico: o domínio “vendas” não sabe o que são tabelas, filas, sistema de arquivos e nem SMTP. O domínio técnico e do domínio do negócio tentam ao máximo não se misturar numa aplicação Domain-Driven.

Se minhas classes de negócio traduzem a linguagem de vendas, quero que você tente pensar num modelo que resolva os seguintes requisitos:

1. Um pedido de vendas possui cliente e itens
2. O valor total do pedido é a soma do valor dos itens
3. Somente produtos disponíveis podem ser vendidos

Imagine agora, como um ator Vendedor utilizaria o sistema. Ele criaria um pedido, colocaria alguns itens com produtos disponíveis e finalizaria este caso de uso. Quero que você pense bastante em como você resolveria o requisito número 3. No meu código, surgiria algo deste tipo:

ddd diag 1 1 - ddd diag 1 1

A primeira pergunta natural é: Por que o repositório está como uma interface? Muitas vezes o Repositório simplesmente é uma abstração do domínio cuja responsabilidade é representar coleções de entidades, porém, ele ainda é um elemento do domínio. Muitas vezes nós temos um elemento que realiza esta interface para fornecer implementação para essas buscas.

ddd diag 2 1 - ddd diag 2 1

Usar repositórios como interfaces é bom para a saúde da testabilidade da sua aplicação e ainda posso me beneficiar de injeção de dependência. Isso facilita o uso de Mocks e Stubs para testes unitários ou de integração, além de deixar seus objetos desacoplados.

Teve algumas situações peculiares onde a interface TodosProdutos era um elemento do domínio e a implementação TodosProdutosImpl era puramente infra-estrutura. Neste caso, TodosProdutos (a interface) estava empacotada no domínio (geralmente uso o nome domain) e a TodosProdutosImpl estava empacotado como infra-estrutura.

De qualquer forma, para a discussão aqui, simplesmente destaco que o repositório TodosProdutos é algo puramente do vocabulário de negócios. “Todos os Produtos” é algo que o meu usuário sabe o que significa. E TodosProdutos.getDisponiveis - a minha operação - faz mais sentido ainda para os usuários, pois eles também sabem o que são produtos disponíveis para venda (se isso para eles é uma interface ou uma classe isso é completamente irrelevante).

Repositórios como Coleções Parciais

Teve uma certa aplicação que desenvolvi que nas conversas com os especialistas de negócio um determinado termo era muito recorrente. Eles se referiam a um determinado conjunto de entidades com um nome especial: pedidos faturados. E nesse sistema, os “pedidos faturados” tinham uma força tão grande na Ubiquitous Language da DDD que passou a ser um contexto separado.

ddd diag 3 - ddd diag 3

Várias vezes mostrei esse diagrama a arquitetos e programadores e muitos não entenderam isso facilmente. É bastante comum as pessoas associarem um repositório por entidade, enxergando-os como 1 para 1 com DAOs. Muitos desses programadores que não entendem DDD questionaram: - Por que separar isso? Minha resposta: - Não fui eu que separei isto… no domínio do negócio isso é separado. Não é uma opção arquitetural, somente estou transparecendo o domínio.

A maioria das respostas sobre a camada de negócios numa aplicação Domain-Driven é dada pelos usuários e especialistas do domínio e não pelos arquitetos e programadores.

O nome não deve ser XptoRepository?

Durante algum tempo, seguindo a linha do Hibernate, minhas classes de busca eram [NomeDaEntidade]DAO. Depois de um tempo meus DAOs eram repositórios, mas continuava chamando-os de DAOs, pois odeio o nome Repository dentro do meu código. Acho pior ainda o nome “Repositório” - que é uma tradução livre corrente. O nome Repositório é bem pouco expressivo em português (que raios é repositório?) - o termo em inglês é mais claro.

Ao fim de tudo isso, vejo que é bem pouco proveitoso chamar uma classe de domínio de PedidoRepository ou PedidoRepositorio. Teve uma aplicação que chamei meus repositorio de “Pedidos”, mas últimamente tenho usado mesmo “TodosPedidos”, “TodosClientes”, “PedidosFaturados”, “ClientesInadimplentes” e etc… Uso esses termos pois são mais próximos do domínio e não vejo a mínima razão para ter o nome do padrão no nome ou empacotamento das classes.

Pedido é uma entidade, nem por isso o chamamos de PedidoEntity, o mesmo vale para Value Objects, Services e Repositórios. O BufferedInputStream do Java é um Decorator, nem por isso chamamos ele de BufferedInpuStreamDecorator.

Repositórios mais Complexos

Associar repositórios com buscas nem sempre é verdadeiro. Repositórios respondem por conjuntos de entidades, não importando a dificuldade de se obter esse conjunto. Há repositórios que podem ter código de negócio complexo em sua execução onde determinadas operações podem à primeira vista aparentar simplesmente uma busca. Você deve levar em consideração se há inteligência de domínio envolvida, caso afirmativo seu repositório deverá ter essa inteligência embutida. Vamos colocar mais requisitos:

4. Se o pedido é para entrega imediata, os produtos disponíveis são aqueles que eu tenho em estoque no momento da venda
5. Se o pedido é para entrega futura, os produtos disponíveis são aqueles que estarão em estoque na data de entrega

ddd diag 4 - ddd diag 4

Neste “TodosProdutos” refatorado, para obter os produtos disponíveis na data da entrega é necessário pegar o saldo atual do estoque, subtrair os pedidos de venda já comprometidos (saídas) e somar os pedidos de compra (entradas) até a data desejada. Tudo isso é inteligência de domínio que não deve ser delegado para o banco de dados. É um repositório que tem regras e pode até orquestrar junto a outros repositórios e services para cumprir o seu propósito.

Um ponto importante a destacar é que muitas outras variações de implementações de repositórios existem. O objetivo do artigo é somente destacar algumas implementações interessantes que implementei em alguns projetos.

É lícito acessar o EntityManager diretamente?

Discussões sobre Domain-Driven e implementações de respositórios são muito recorrentes em listas de discussões, principalmente no GUJ e na DotNetArchitects (sou novo nessa lista).

Uma das perguntas comuns é: “É licito eu acessar diretamente o EntityManager ou Sessão do Hibernate?”. Particularmente eu sou da opinião que se você está fazendo buscas que não são importantes para o negócio não há problemas acessar diretamente seu framework de persistência. Logicamente que isso não deve ser levado a ferro e a fogo, testabilidade e complexidade são pontos a considerar.

Um exemplo seria: imagine que para emitir o pedido eu tenha que preencher um combo com o tipo de venda (um dado simplesmente informativo). Se é uma busca de uma entidade fraca, que significa muito pouco para o domínio, para reduzir a complexidade, o repositório pode ser descartado sem muito prejuízo para a testabilidade.