Categories
Domain-Driven Design

Síndrome de DAO

O assunto Repository X DAO já está bem batido, eu sei, mas é impressionante como isso confunde muita gente até hoje… Muitas pessoas já postaram sobre isso mas eu quero dar meus dois centavos.

Com a popularização do Domain-Driven Design ví muita gente simplesmente renomeando seus XptoDAO para XptoRepository achando que assim estariam aplicando DDD porque “chamar um objeto de Repository é mais semântico que DAO”. Esses dias no Twitter ví uma mensagem assim: “Repositório ou DAO ? Eu gosto do nome repositório porque me parece ser uma abstração mais adequada”. Vamos lá, não se trata somente de nomes diferentes para a mesma coisa.

O padrão DAO têm o objetivo de criar uma abstração da infra-estrutura de armazenamento de dados para a aplicação. Uma camada de persistência é útil porque dá a funcionalidade de armazenamento/persistência de dados sem revelar detalhes específicos da infra-estrutura por trás disso. O armazenamento pode ser feito num banco de dados, em vários bancos de dados, em um webservice, em um arquivo texto, tanto faz, mas do ponto de vista da camada de negócios que obtém esses dados, por exemplo, ela está lidando apenas com busca, alteração e gravação de objetos em algum lugar que nem importa.

Já o padrão Repository tem o objetivo de dar apoio ao domain model fornecendo persistência. Ao contrário do DAO, que é um objeto de infra-estrutura da aplicação e faz parte da camada de persistência, o Repository faz parte do domain model que é parte da camada de negócios.

Domain models (modelos de domínio) fazem sentido quando a aplicação tem regras de negócio muito complexas. Isolar as regras de negócio em um domain model torna mais fácil o trabalho de focar e lidar com essas regras complexas. Porém, para que um software possa funcionar fortemente baseado em domain model (que é a proposta de Domain-Driven Design) é necessário dentre outras coisas que haja algum componente que faça parte desse modelo e permita que se faça persistência de dados – e daí veio o Repository.

No ano passado conversei bastante com o pai do DDD – Eric Evans – sobre isso e para ele o problema é que as pessoas confundem esses dois conceitos porque realmente são bem parecidos. Na maioria dos casos você irá precisar dos dois, porque o domain model fará buscas por objetos em um Repository que por sua vez delegará para o DAO, que é quem entende como é a infra-estrutura de armazenamento de dados. Para ele também não importa se o Repositório é uma classe ou uma interface, o que importa é que os objetos do domain model deverão dempre lidar com busca e persistência de objetos usando a interface do Repository, que tem o compromisso de ser mais semântica do que a do DAO.

Categories
Domain-Driven Design Engenharia de software Eventos

[QCon 2007] Eric Evans: Domanin-Driven Design

Qcon 2007 - Eric Evans - Domain-Driven DesignA apresentação do Eric Evans hoje sobre Domain-Driven Design foi excelente! A abertura do evento não poderia ter sido melhor!

Grande parte do que ele apresentou faz parte do seu livro sobre DDD, incluindo alguns dos exemplos usados no tutorial. Mas isso não fez com que as coisas ficassem menos interessantes. Muito pelo contrário, as discussões foram excelentes.

Falamos inicialmente sobre as características de um bom design de domínio. Na opinião do Eric um bom design é aquele que você consegue explicar para uma pessoa qualquer e ela entende mesmo não sendo especialista no negócio/domínio. Sobre codificação, o Eric falou que se interessa bastante pela clareza trazida por Fluent Interfaces, e DSLs internas e tenta usá-las sempre que possível pois aumenta muito a legibilidade do código. Além disso ele acredita que o uso de Behaviour-Driven Development é interessante no processo exploratório de um domínio e pode te ajudar a identificar e corrigir problemas de design.

Uma das frases que o Eric falou me lembrou a discussão que rolou na semana passada no GUJ sobre testes, TDD e etc: “Estamos no ano do Test-Driven Development e criar designs testáveis é essencial!”. Não quero acender novamente a discussão mas não posso deixar de dar a minha opinião nessa história. Realmente é inaceitável um software nos dias de hoje não ter uma suite de testes decente, não só pelos testes em sí mas por toda a influência positiva que isso traz no design do código, pela segurança que te dá para incluir novas funcionalidades e modificar existentes, segurança para corrigir bugs e tudo mais. Para mim é simplesmente impossível programar sem testes!

Guilherme Chapiewski e Eric EvansInfelizmente não consegui todo o material do curso porque o Eric utiliza esses materiais nos seus treinamentos e por isso não os disponibiliza publicamente. Mas eu consegui o Domain-Driven Design Pattern Summaries, que é um resumo de 39 páginas do livro dele com algumas coisas a mais. Achei bem interessante para se usar como referência. Esse resumo contém informações bem objetivas sobre todos os padrões apresentados no livro de DDD.

Além desse material o InfoQ disponibilizou a palestra Putting The Model To Work que foi uma das que o Eric apresentou para nós. Essa não foi exatamente a apresentação que tivemos mas foi bem parecida.

Para os leitores assíduos de blog, aí vai uma boa notícia: num dos intervalos eu perguntei para o Eric porque que ele não tinha um blog. Ele disse que ultimamente muitas pessoas têm feito essa pergunta e disse que está preparando alguma coisa nesse sentido. Perguntei sobre quando ele planeja lançar isso e ele disse que seria em breve! Com certeza será mais uma ótima fonte para leituras.

E para terminar, a gafe do dia: na hora do intervalo subitamente começamos a ouvir na sala vários barulhos estranhos de mictório e pia de banheiro… O Eric deu bobeira e foi no banheiro com o microfone sem fio ligado! Ao menos constatamos que o microfone era de boa qualidade porque o banheiro era meio longe, haha!

Categories
Domain-Driven Design Refactoring

Tiny Types

Continuando na “luta” para criar sistemas mais fáceis de se entender, me lembrei de dar uma olhada nos Tiny Types apresentados pelo Darren Hobbs.

O CV tinha passado esse link há algum tempo e eu havia olhado superficialmente. Até que nessa história de fazer Fluent Interfaces e Domain-Driven Design acabei me lembrando que isso poderia ser útil.

Os Tiny Types enriquecem o domain model e trazem alguns outros benefícios legais citados pelo Darren em seu texto. Para as próximas features vou experimentar essa estratégia para ver no que vai dar…

Categories
Domain-Driven Design Refactoring

Refatorando para Fluent Interface

Ultimamente tenho passado boa parte do meu tempo trabalhando numa aplicação chamada WebMediaAPI. Trata-se de uma… ahm… API de uso interno que tem como objetivo padronizar, centralizar e facilitar o acesso à mídias e seu consumo em sites da Globo.com.

Por exemplo, quando o pessoal do G1 quiser colocar vídeos no seu site, ao invés de dar vários SELECTs em tabelas que eles não entendem e não conhecem, a idéia é que eles possam usar um JAR na aplicação deles que encapsula várias funcionalidades oferecidas pela nossa infraestrutura de WebMedia, simplificando o trabalho deles (pois não terão que descobrir como inventar a roda) e o nosso (centralizando e organizando o consumo de mídias na empresa).

No início do projeto um dos maiores desafios foi estabelecer como seria a fachada desta API. Nós tentamos alguns formatos e como precisávamos lançar logo a primeira versão acabamos optando por uma interface “tradicional” e simplificada. Para ter uma idéia melhor, veja o código para selecionar os últimos vídeos publicados do programa “Altas Horas”:

int quantidade = 5;
long programaId = 456;
Set midias = new HashSet();
 
WebMediaServices webMediaServices = WebMediaFactory.getServices();
List idsMidias = webMediaServices
	.getIdsUltimasMidiasPublicadasPorPrograma(quantidade, programaId);
 
for (Iterator iter = idsMidias.iterator(); iter.hasNext();) {
   Long midiaId = (Long) iter.next();
   Midia midia = webMediaServices.getMidia(midiaId.longValue());
   midias.add(midia);
}

Não é muito difícil entender o funcionamento deste código… Só que ele poderia ser muito melhor!

Esta interface pode até funcionar mas não é nem um pouco intuitiva. A classe WebMediaServices como pode-se imaginar ficou com dezenas de métodos e virou basicamente um grande saco de funcionalidades. Qualquer método simplesmente ficava nesta classe – o que não é nem um pouco elegante.

Depois de algum tempo tive a idéia de refatorar a API para uma Fluent Interface. A idéia é tentar fazer algo que se assemelha a uma DSL interna, que não é nada mais do que uma API com nomes interessantes. Ao invés de um saco de métodos a WebMediaAPI agora é acessada através de uma interface semânticamente organizada e seu design é pensado para ser legível e… fluente!

Veja como ficou o novo código para selecionar os últimos vídeos publicados do programa “Altas Horas” (exatamente a mesma coisa que o código anterior faz):

Long altasHoras = new Long(456);
Set videos = WebMediaAPI.videos().recentes().doPrograma(altasHoras);

Bem mais elegante!

O lado negativo é que quanto mais fácil a API torna-se para o cliente mais difícil torna-se sua implementação. Construir uma fluent interface muitas vezes me fez perder algumas horas pensando como certas coisas seriam feitas, mas eu gostei do resultado final e acho que para esse tipo de aplicação valeu a pena.

Para mostrar a diversidade e simplicidade da nova API, veja mais alguns exemplos (repare que eu não tenho que dizer nada sobre o que eles fazem para você entendê-los):

// exemplo 1
Set programas = WebMediaAPI.programas().comTitulo("Fantastico");
 
// exemplo 2
Long multishow = new Long(123);
Set videos = WebMediaAPI.videos().favoritos().doCanal(multishow);
 
// exemplo 3
Long destaquePrincipalGloboVideos = new Long(123);
Integer quantidadeMaxima = new Integer(10);
Set videos = WebMediaAPI.videos().relacionados().aoCanal()
	.doVideo(destaquePrincipalGloboVideos, quantidadeMaxima);

Ainda temos um longo caminho pela frente e muita coisa ainda será melhorada, mas já dá para perceber uma difirença significativa entre as duas versões.

Categories
Domain-Driven Design

Em qual língua você programa?

Muitas vezes fico em dúvida sobre qual língua usar nos meus sistemas. Sempre me sentí muito mais confortável programando em inglês do que em português mas nunca achei isso muito certo já que nossa língua nativa é o português. Já houveram casos de eu trabalhar com alguém que só sabia português e apesar de achar que nessa profissão quem não sabe inglês não vai à lugar nenhum não podia simplesmente inviabilizar o trabalho da equipe.

No último projeto que participei nossa equipe usou somente português. Algumas coisas boas aconteceram como o fato de termos incorporado a linguagem do negócio ao sistema. Isso é muito bom porque a grande maioria das entidades do sistema são coisas do mundo real e as discussões são sempre sobre coisas reais e não sobre metáforas (frequentemente mal feitas).

Porém também houveram pontos negativos. Por exemplo, uma determinada classe de serviços, que em inglês seria algo como MediaServices, teve que ser chamada de ServicosDeMidia. No fim das contas acabei optando por tirar a preposição (acho que o “de” é uma preposição, certo?) ficando somente ServicosMidias. Resolví retirá-la porque inúmeras classes ficaram com “De” no nome e ficou meio esquisito. O ruim é que não é exatamente assim que a gente fala naturalmente e fica um pouco estranho…

No fim das contas acho que o ideal é utilizar a língua do negócio, seja ela português ou inglês. Desta forma quando você for conversar com os clientes (product owners) você não terá o overhead de mapear todos os conceitos reais para a linguagem ou metáforas usadas no sistema. Com isso a conversa entre os clientes e os desenvolvedores fica muito mais produtiva já que todos estão falando sobre as mesmas coisas.