Domain Model: Uma Forma Mais Eficiente de Construir Aplicações Enterprise

Documentos relacionados
Transaction Scripts: Uma Forma mais Simples de Organizar Lógica de Domínio

Conteúdo. Disciplina: INF Engenharia de Software. Monalessa Perini Barcellos. Centro Tecnológico. Universidade Federal do Espírito Santo

HIBERNATE EM APLICAÇÃO JAVA WEB

Tecnologias Web. Padrões de Projeto - Camada de Apresentação

UFG - Instituto de Informática

ABORDAGEM DE FRAMEWORKS PARA JSF QUE AUXILIAM O DESENVOLVIMENTO DE SOFTWARE

PROGRAMAÇÃO SERVIDOR PADRÕES MVC E DAO EM SISTEMAS WEB. Prof. Dr. Daniel Caetano

Argo Navis J931 - Padrões de Design J2EE. Introdução. Objetivos de aprender padrões J2EE. Conhecer padrões para uso na plataforma J2EE

Especificação do 3º Trabalho

3 Um Framework Orientado a Aspectos para Monitoramento e Análise de Processos de Negócio

2 Diagrama de Caso de Uso

Projeto Demoiselle. Para perguntas e respostas, utilizem a lista de discussões de usuários da comunidade: demoiselle-users@lists.sourceforge.

UFG - Instituto de Informática

Uma Abordagem sobre Mapeamento Objeto Relacional com Hibernate

Modelagemde Software Orientadaa Objetos com UML

Unidade 8: Padrão MVC e DAO Prof. Daniel Caetano

Documento de Projeto de Sistema

Como criar um EJB. Criando um projeto EJB com um cliente WEB no Eclipse

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

DESENVOLVENDO APLICAÇÃO UTILIZANDO JAVA SERVER FACES

Documento de Análise e Projeto VideoSystem

SISTEMA TYR DIAGRAMAS DE CLASSE E SEQUÊNCIA Empresa: Academia Universitária

3 SCS: Sistema de Componentes de Software

5 Framework para coordenação e mediação de Web Services para ambientes de aprendizado à distância

PadrãoIX. Módulo II JAVA. Marcio de Carvalho Victorino. Servlets A,L,F,M

ENTERPRISE JAVABEANS 3. Msc. Daniele Carvalho Oliveira

UNIVERSIDADE FEDERAL DO PARANÁ UFPR Bacharelado em Ciência da Computação

Aplicativo web para definição do modelo lógico no projeto de banco de dados relacional

Programação Orientada a Objetos com PHP & MySQL Cookies e Sessões. Prof. MSc. Hugo Souza

Apesar de existirem diversas implementações de MVC, em linhas gerais, o fluxo funciona geralmente da seguinte forma:

Framework. Marcos Paulo de Souza Brito João Paulo Raittes

MAPEAMENTO OBJETO RELACIONAL: UM ESTUDO DE CASO

Padrão Arquitetura em Camadas

Orientação a Objetos

Sistemas Distribuídos

4 O Workflow e a Máquina de Regras

Prototype, um Design Patterns de Criação

Arquitetura de Aplicações JSP/Web. Padrão Arquitetural MVC

Padrões de projeto 1

5 Mecanismo de seleção de componentes

AULA 4 VISÃO BÁSICA DE CLASSES EM PHP

Java para Desenvolvimento Web

UFG - Instituto de Informática

Implementando uma Classe e Criando Objetos a partir dela

USANDO O IZCODE PARA GERAR SOFTWARE RAPIDAMENTE

SISTEMA DE AGENDAMENTO E GERENCIAMENTO DE CONSULTAS CLÍNICAS

MVC e Camadas - Fragmental Bliki

Padrões de Interação com o Usuário

Como já foi muito bem detalhado no Capítulo IV, o jcompany Developer Suite pode ser

Roteiro. Arquitetura. Tipos de Arquitetura. Questionário. Centralizado Descentralizado Hibrido

4 Um Exemplo de Implementação

Fábrica de Software 29/04/2015

UML Aspectos de projetos em Diagramas de classes

DESENVOLVIMENTO WEB UTILIZANDO FRAMEWORK PRIMEFACES E OUTRAS TECNOLOGIAS ATUAIS

Procedimentos para Reinstalação do Sisloc

PRODUTO 1 (CONSTRUÇÃO DE PORTAL WEB)

Sistema de Controle de Solicitação de Desenvolvimento

Análise e Projeto Orientados por Objetos

Desenvolvimento de aplicação web com framework JavaServer Faces e Hibernate

Curso de Aprendizado Industrial Desenvolvedor WEB

Parte I. Demoiselle Mail

O CONCEITO DE TDD NO DESENVOLVIMENTO DE SOFTWARE

Enterprise Java Beans

Feature-Driven Development

TOTVS Série 1 Varejo (Simples) - Módulo e-commerce

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

Desenvolvendo uma Arquitetura de Componentes Orientada a Serviço SCA

SISTEMA GERENCIADOR DE BANCO DE DADOS

Documento de Arquitetura

Etc & Tal. Volume 2 - Número 1 - Abril 2009 SBC HORIZONTES 44

JPA Passo a Passo. Henrique Eduardo M. Oliveira henrique@voffice.com.br. Globalcode Open4Education

ISO/IEC 12207: Gerência de Configuração

Processo de Controle das Reposições da loja

Aplicativo da Manifestação do Destinatário. Manual

Engenharia de Software III

Figura 1 - Arquitetura multi-camadas do SIE

Eduardo Bezerra. Editora Campus/Elsevier

Projeto SIGA-EPT. Manual do usuário Módulo Requisição de Almoxarifado SISTEMA INTEGRADO DE GESTÃO ACADÊMICA

LINGUAGEM DE BANCO DE DADOS

Disciplina de Banco de Dados Introdução

Metodologia e Gerenciamento do Projeto na Fábrica de Software v.2

SISTEMA DE WORKFLOW PARA MODELAGEM E EXECUÇÃO DE PROCESSOS DE SOFTWARE. Aluno: Roberto Reinert Orientador: Everaldo A. Grahl

2 Engenharia de Software

Padrões de Projeto WEB e o MVC

Guia de utilização da notação BPMN

2 a Lista de Exercícios

Hoje é inegável que a sobrevivência das organizações depende de dados precisos e atualizados.

Prof. Raul Sidnei Wazlawick UFSC-CTC-INE. Fonte: Análise e Projeto de Sistemas de Informação Orientados a Objetos, 2ª Edição, Elsevier, 2010.

Manual dos Serviços de Interoperabilidade

Módulo e-rede VirtueMart v1.0. Manual de. Instalação do Módulo. estamos todos ligados

ANEXO 11. Framework é um conjunto de classes que colaboram para realizar uma responsabilidade para um domínio de um subsistema da aplicação.

Persistência e Banco de Dados em Jogos Digitais

Padrões de Projeto. Singleton

PROGRAMAÇÃO AVANÇADA -CONCEITOS DE ORIENTAÇÃO A OBJETOS. Prof. Angelo Augusto Frozza, M.Sc. frozza@ifc-camboriu.edu.br

Padrões. Projeto (Design) de Software

Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Sistema Gerenciador de Banco de Dados

ALTO DESEMPENHO UTILIZANDO FRAMEWORK HIBERNATE E PADRÃO JAVA PERSISTENCE API

Especificação do Trabalho

Transcrição:

Roberto Perillo (jrcperillo@yahoo.com.br) é bacharel em Ciência da Computação e está atualmente cursando mestrado no ITA, onde já concluiu o curso de especialização em Engenharia de Software. Trabalha com Java há mais de 5 anos, possui as certificações SCJP, SCWCD, SCJD e SCBCD, e é moderador no JavaRanch, onde participa ativamente dos fóruns. Já trabalhou com JEE em grandes empresas, como Avaya e IBM, onde, nesta última, foi co-fundador do time de inovação de ibm.com GWPS LA. Atualmente, trabalha na BoldCron Technologies (uma empresa do grupo UOL) como Senior Java Developer. Domain Model: Uma Forma Mais Eficiente de Construir Aplicações Enterprise Construir aplicações envolve, além de experiência com uma determinada linguagem e arquitetura de software, criatividade e bom senso. Esses talvez sejam os aspectos mais importantes para se criar um modelo de domínio que reflita adequadamente as necessidades a serem contempladas pelo software. A implementação deste modelo requer um estilo de arquitetura diferente, que pode ser alcançado com o padrão arquitetural Domain Model. Este padrão propõe criar uma estrutura de objetos que utiliza plenamente todas as forças da orientação a objetos, o que torna a arquitetura da aplicação mais flexível e fácil de manter e evoluir com o passar do tempo. Este artigo mostra e exemplifica como o padrão Domain Model pode ser implementado, ilustrando os benefícios que podem ser obtidos com sua utilização. tualmente, a comunidade de desenvolvimento aceita que, ao se desenvolver software, a verdadeira complexidade está, na maioria das vezes, no domínio com o qual a aplicação deve lidar. A abordagem conhecida como Domain-Driven Design provê uma série de práticas que ajudam a desenvolver softwares para domínios complexos. O principal produto dessa abordagem é o modelo de domínio, que representa uma abstração do problema a ser representado e solucionado pelo software. Em termos de código, a manifestação desse modelo se dá na camada de domínio da aplicação. Para a implementação desse modelo, o padrão Domain Model pode ser usado. Ele sugere uma estrutura de objetos que permite que o modelo seja implementado e refletido no código, o que permite tirar proveito de todos os benefícios da orientação a objetos, tornando assim a arquitetura da aplicação mais flexível e fácil de manter e evoluir com o passar do tempo. Essa abordagem também oferece mais reúso, pois os componentes não são semanticamente acoplados a nenhum framework, já que são POJOs. No entanto, pode ser necessário utilizar anotações de frameworks para que algum objetivo seja alcançado. Nesse caso, as anotações de domínio podem ser utilizadas para manter a implementação livre de frameworks externos. O objetivo deste artigo é introduzir o padrão Domain Model como uma forma mais efetiva de se construir aplicações enterprise, e está organizado da seguinte 9

: : www.mundoj.com.br : : forma: primeiramente, é apresentada uma breve discussão sobre design orientado a objetos versus design procedural. Em seguida, é dada uma visão geral sobre modelagem de domínio, cujo resultado é o modelo de domínio a ser implementado. Logo após, o padrão Domain Model é apresentado. Após isso, é mostrado um modelo simplificado do domínio de comércio eletrônico e como ele pode ser implementado. E, finalmente, são apresentadas as considerações finais, finalizando o presente artigo. Este artigo é inspirado nas práticas apresentadas no excelente livro POJOs In Action, escrito por Chris Richardson. Para uma leitura completa e com mais detalhes sobre o padrão Domain Model, recomenda-se a leitura desta obra. Para Saber Mais Uma anotação de domínio é uma anotação criada especificamente para um domínio e substitui as anotações de frameworks que são externos ao domínio. Isso permite manter a camada de domínio da aplicação isolada, o que facilita a evolução do software e aumenta o reúso dos componentes de negócio. Naturalmente, esse tipo de anotação requer tratamento especial, que pode ser aplicado com uma ferramenta como o Daileon, por exemplo. Consulte o artigo Domain Annotations: Anotações Mais Próximas ao Domínio da Sua Aplicação, publicado na edição 41 da revista MundoJ, para saber mais sobre anotações de domínio e a ferramenta Daileon. Design Orientado a Objetos versus Design Procedural Nas últimas duas décadas, a comunidade de desenvolvimento evoluiu a tal ponto que as pessoas passaram a entender que a verdadeira complexidade, ao se desenvolver software, está na verdade no domínio no qual o programa será aplicado. Embora possam existir outras dificuldades, relacionadas com a infraestrutura de desenvolvimento, por exemplo, o foco principal dos esforços de desenvolvimento deve se centrar no domínio e em sua lógica. Com a introdução de tecnologias como EJB 2, que promoviam projetos em estilo procedural, muitas das vantagens que a orientação a objetos oferece se perderam. Além disso, a complexidade introduzida no ciclo de desenvolvimento tornou a confecção do código mais complexa do que o próprio entendimento do domínio em si. Diante deste cenário, muitos foram os esforços que buscaram simplificar o processo de desenvolvimento, concentrando a maior parte dos esforços no entendimento do domínio no qual a aplicação é aplicada. Um exemplo disto é a abordagem conhecida como Domain-Driven Design, que é um conjunto de técnicas e práticas que ajudam a desenvolver aplicações para domínios complexos, essencialmente conectando implementação a um modelo que evolui constantemente. Uma das práticas promovidas por essa abordagem é a técnica chamada de modelagem de domínio, que promove uma abstração do domínio através de um modelo que contempla os aspectos relevantes ao desenvolvimento da aplicação, separando assim domínio de outros interesses, como infraestrutura, por exemplo. O modelo não é um diagrama, e pode assim ser representado por praticamente qualquer coisa, desde um desenho a um diagrama UML. Em termos de código, a manifestação desse modelo se dá na camada de domínio, que constitui o coração do software. Para que se alcance mais reúso, menos acoplamento e mais coesão, a camada de domínio deve ficar o mais isolada possível das outras camadas sugeridas pelo DDD (como apresentação, aplicação e infraestrutura) e deve ficar o mais livre possível de implementações específicas, como um determinado banco de dados sendo acessado por uma API específica, por exemplo. O principal motivo para se isolar a camada de domínio das outras camadas é a evolução do software. Dessa forma, torna-se mais fácil manter e evoluir o software com o passar do tempo. De acordo com a arquitetura Java EE, os componentes que lidam com a lógica de negócios em uma aplicação enterprise são os EJBs, o que implica na utilização de um Application Server (os chamados heavyweight containers, como o JBoss ou o IBM Websphere, por exemplo). O grande benefício da utilização de EJBs é que containers Java EE permitem que muitos requisitos não-funcionais presentes na maioria das aplicações enterprise sejam atendidos de forma fácil. Por exemplo, a partir da versão 3 da especificação EJB, tornou-se consideravelmente fácil tornar um método transacional e seguro através das anotações @TransactionAttribute e @RolesAllowed. Ironicamente, os EJBs (mesmo na versão 3) promovem um estilo de programação mais procedural, pois ao invés de se criar um modelo de objetos no qual as classes possuem tanto estado quanto comportamento e colaboram umas com as outras para organizar a lógica de negócios, criam-se classes de granularidade grossa que normalmente não possuem estado e se utilizam de DTOs (objetos burros que não possuem nenhuma inteligência e espelham a estrutura das tabelas da base de dados) para transportar dados entre as camadas. Cada método dessas classes de negócio existe normalmente para tratar uma requisição da camada de apresentação, o que caracteriza o padrão Transaction Script, que é uma abordagem mais procedural. Como consequência, construir, testar, manter e evoluir a aplicação pode se tornar cada vez mais complexo com o passar do tempo. Em contrapartida, o padrão Domain Model propõe organizar a lógica de negócios em um modelo de objetos que se utiliza de todos os benefícios da orientação a objetos, em que as classes nada mais são do que POJOs, isto é, classes simples que não estendem nenhuma classe de uma API específica. Assim, o código reflete efetivamente o modelo de domínio construído e, dessa forma, torna-se fácil manter e evoluir a aplicação com o passar do tempo. No entanto, POJOs por si só não são suficientes em uma aplicação enterprise, pois é necessário implementar requisitos não-funcionais na maioria dos casos, como transacionalidade ou segurança, por exemplo. Para isso, pode-se utilizar o framework Spring, no qual se consegue suprir essas necessidades facilmente através das funcionalidades de injeção de dependência e AOP, fornecidas pelo próprio Spring. Graças às funcionalidades oferecidas pelo Spring, torna-se fácil utilizar o padrão Domain Model com POJOs. No entanto, a utilização do padrão não depende especificamente do Spring. De fato, é possível utilizar o padrão em uma aplicação instalada em um container Java EE. É possível, inclusive, utilizar Stateless Session Beans, em que estes podem desempenhar o papel de facades, servicos e repositórios, abordados mais a frente neste artigo. Entretanto, além de algumas limitações, a aplicação nesse caso fica dependente de um container Java EE e o mais natural seria utilizar uma abordagem mais procedural, na qual os Session Beans são os componentes de negócio. 10

Modelagem de domínio Atualmente, a comunidade de desenvolvimento de software aceita que a real complexidade, na maioria dos projetos de software, está no domínio no qual o software é aplicado. A modelagem de domínio, que é uma das práticas incentivadas pelo Domain-Driven Design, ajuda a lidar com essa complexidade. Em termos práticos, modelo pode ser definido como um sistema de abstrações que descreve aspectos selecionados de um domínio e podem ser utilizados para resolver problemas relacionados a esse domínio. Domínio pode ser definido como uma esfera de conhecimento, influência ou atividade. A área onde o usuário aplica o programa é o domínio do software. Por exemplo, para uma aplicação bancária, o domínio é a esfera de conhecimento bancário. Assim, modelo de domínio pode ser definido como uma abstração rigorosa e selecionada do conhecimento que os especialistas no domínio possuem, e embora seja somente uma abstração, é comumente representado através do diagrama de classes da UML. O modelo de domínio é o maior produto do Domain-Driven Design, que nada mais é do que um conjunto de técnicas e práticas que auxiliam no desenvolvimento de software para domínios complexos. É também uma forma de pensar e organizar prioridades, buscando acelerar projetos de software que lidam com domínios complexos. O resultado da modelagem de domínio é uma abstração cujos limites são os aspectos relevantes à resolução do problema através da construção do novo software. A evolução ou refinamento desse modelo se dá incluindo elementos que sejam importantes para a resolução do problema ou excluindo elementos que não sejam relevantes. Em termos de código, a manifestação desse modelo se dá na camada de domínio da aplicação. No entanto, como a lógica de negócios é na maior parte concentrada nas entidades de domínio, a implementação desse modelo requer um estilo de arquitetura diferente. Para essa implementação, o padrão Domain Model pode ser utilizado. Ele sugere uma estrutura de objetos que permite organizar o modelo de domínio e oferecer as funcionalidades implementadas de uma forma totalmente orientada a objetos, incluindo extensibilidade e fácil manutenção. O Padrão Domain Model O padrão Domain Model sugere uma estrutura que implementa um modelo de domínio através de um modelo de objetos onde é possível se utilizar de todos os benefícios da orientação a objetos. De acordo com o Domain-Driven Design, a camada de domínio deve ficar o mais isolada possível do resto da aplicação. Através do padrão Domain Model, pode-se criar uma estrutura de objetos de forma a isolar consideravelmente a camada de domínio. No entanto, existem algumas situações nas quais a camada de domínio acaba inevitavelmente sofrendo efeitos externos para que um determinado objetivo seja alcançado. Caso se trate de anotações externas ao domínio, o conceito de anotações de domínio, abordado na edição passada da revista, pode ser aplicado. As classes de domínio são invocadas direta ou indiretamente pela camada de apresentação e o tratamento de cada requisição resulta na chamada de uma ou mais entidades, que validam os dados fornecidos pelo usuário, realizam computações, lidam com a lógica de negócios e acessam o banco de dados através de repositórios. A seguir, com a estrutura sugerida por esse padrão torna-se fácil desenvolver e manter a aplicação, pois as responsabilidades são distribuídas em classes mais coesas e de menor granularidade. Como as classes que implementam o modelo de domínio são POJOs, pode-se utilizar de todos os benefícios da orientação a objetos e utilizar sem nenhuma restrição qualquer padrão GoF. Ao utilizar essa abordagem, é possível testar a aplicação mais facilmente, pois não é necessário instalá-la em um Application Server. Um modelo de domínio deve refletir a abstração do domínio no qual o software é aplicado da forma mais adequada possível. Pode-se categorizar as classes que implementam esse modelo de acordo com o papel que cada classe desempenha. Cada papel implica em certas responsabilidades e relacionamentos com outras classes que desempenham outros papéis. Dessa forma, definir o papel de cada classe facilita o projeto da implementação do modelo de domínio. Os chamados building blocks, ou classes que implementam o modelo de domínio, podem ser categorizados em: rencia dos demais objetos. Por exemplo, uma classe Pessoa poderia ter um atributo representando seu CPF. As entidades representam conceitos do domínio e concentram a maior parte da lógica implementada pela aplicação. seus atributos e frequentemente são imutáveis, o que significa que uma vez criados não podem ser alterados. Na prática, existem somente para compor entidades e podem ser o resultado do agrupamento de atributos duplicados em mais de uma entidade ou que fazem mais sentido ficarem separados das entidades para deixá-las com uma granularidade menor. Além disso, a literatura antiga de J2EE se referia a DTOs (padrão do catálogo Core J2EE Patterns) como value objects, cujo objetivo é somente transportar dados entre as camadas (normalmente, da camada de negócios para a camada de apresentação). No entanto, a diferença entre esses objetos é que um DTO é um objeto burro que possui somente campos e métodos de acesso e os value objects são objetos que fazem sentido em um domínio. tros objetos. Dessa forma, o mecanismo de criação de objetos fica encapsulado, promovendo assim mais flexibilidade. As fábricas também são bastante úteis quando o grafo do objeto a ser instanciado é complexo. Separar o mecanismo de criação desses objetos permite que o código que implementa as regras de negócio fique mais fácil de se ler e manter. No entanto, o maior benefício da utilização desse tipo de objeto é alcançado ao se utilizar polimorfismo. Dessa forma, o código que utiliza a fábrica pode referenciar uma superclasse ou interface e atribuir a essa referência o objeto retornado pela fábrica, sendo que o tipo retornado pela fábrica pode variar sem precisar alterar o código cliente. Em termos de padrões de projeto, existem dois tipos de fábricas, chamados de Factory Method e Abstract Factory, que podem ser utilizados nessas fábricas nos contextos em que forem adequados. definem métodos para criá-las, alterá-las, excluí-las ou encontrálas. Repositórios encapsulam frameworks de persistência, tornando assim o mecanismo de persistência transparente para o restante da camada de domínio. Um repositório é abstraído em uma interface e pode possuir uma ou mais classes de implementação. A interface define os métodos que o repositório oferecerá a seus clientes, enquanto as classes de implementação utilizam diretamente os frameworks de persistência. O que difere um repositório de um DAO (padrão do catálogo Core J2EE Patterns) é uma linha tênue, mais relacionada com o objetivo de cada um: um repositório gerencia coleções de entidades em um modelo de domínio e oferece métodos que têm relação direta com o domínio, enquanto um DAO visa apenas a encapsular o acesso a dados. - 11

: : www.mundoj.com.br : : veem funcionalidade ao modelo de domínio. Normalmente, um serviço possui uma interface e uma implementação. É invocado pelo código cliente, que pode ser ou a camada de apresentação ou um Façade que envolve a camada de domínio, recupera entidades através de um repositório e delega a execução das tarefas a essas entidades. Como os serviços organizam o fluxo de trabalho da aplicação, eles normalmente possuem as responsabilidades encontradas nos casos de uso. De certa forma, se assemelham aos Application Services (padrão do catálogo Core J2EE Patterns), pois podem também conter lógica que não pode ser atribuída a uma entidade. A combinação dessas classes resulta na implementação do modelo de domínio, e essa implementação corresponde ao M do padrão arquitetural MVC. Por exemplo, consideremos uma aplicação na qual um Front Controller receba todas as requisições, que delega a descoberta do componente que tratará uma requisição específica a um Application Controller. Este Application Controller delega o tratamento da requisição ao modelo e, após o tratamento, redireciona o usuário à tela apropriada. Dessa forma, têm-se os Controllers recebendo a requisição e delegando seu tratamento ao código que reflete o modelo de domínio, e após o tratamento, o Application Controller redirecionando o usuário à tela apropriada. Além das entidades, value objects, fábricas, repositórios e serviços, existe um sexto tipo de objeto que compõe o modelo de domínio e não é citado por Eric Evans no livro de Domain-Driven Design ou por Chris Richardson no livro POJOs In Action. Hoje em dia, Eric Evans reconhece que deveria ter incluído em sua excelente obra os domain events, ou eventos de domínio. Um evento de domínio é um acontecimento que é de interesse dos domain experts. Por exemplo, no modelo abordado por este artigo, o fechamento de um pedido é um evento de domínio. Um modelo de domínio fictício implementado Consideremos a representação simplificada do modelo de domínio apresentada a seguir, referente ao domínio de comércio eletrônico. Em um cenário real, o modelo de domínio deve ser criado com os domain experts. Embora possa parecer fácil, essa é uma tarefa extremamente difícil, pois o responsável por essa modelagem deve buscar extrair o conhecimento do domínio da forma mais adequada possível, para que o modelo contemple os aspectos relevantes à resolução do problema. No modelo apresentado na figura 1, uma categoria pode ter nenhuma ou muitas subcategorias. As categorias são compostas de produtos, que podem ter muitos produtos relacionados. Um item de carrinho de compras tem um produto. Dessa forma, pode-se manter os dados referentes ao carrinho de compras (como quantidade, por exemplo) separados dos produtos em si. Um pedido possui um ou muitos itens de carrinho de compras, pode possuir até um cupom de desconto, um endereço de entrega, dados de pagamento, status referente à condição atual do pedido e sempre pertence a um cliente. O modelo de domínio pode se parecer com o esquema de tabelas do banco de dados e grande parte das classes do modelo de domínio normalmente é persistente. Por essa razão, muitas vezes modelagem de dados também é referenciada como modelagem de domínio. Obviamente, o modelo pode conter elementos que não podem ser representados no banco de dados, como herança, por exemplo. Após a modelagem inicial, é preciso adicionar comportamento ao modelo, ou seja, atribuir as responsabilidades às classes do modelo. Uma responsabilidade é tudo que uma classe conhece ou faz. Para descobrir os métodos e efetuar essa atribuição, pode-se utilizar as seguintes técnicas em conjunto: do-se os requisitos (através de casos de uso ou user stories ) ou projeto de interface do usuário; mínio deve expor para permitir que a camada de apresentação ou facades que envolvem a camada de domínio (que serão discutidas posteriormente) tratem dessas requisições. Assim, pode-se utilizar estas técnicas, considerar como as entidades agem no mundo real e atribuir as responsabilidades a elas. Por exemplo, no modelo ilustrado na figura 1, uma responsabilidade que pode ser atribuída à entidade Pedido é o fechamento do pedido, que insere no banco de dados um novo pedido com o status aguardando pagamento. Para organizar o fluxo da aplicação, é necessário analisar as requisições que a aplicação deverá tratar e definir métodos baseados nessas requisições. Os clientes do modelo de domínio são normalmente facades que o encapsulam ou a camada de apresentação. Os métodos que organizam o fluxo da aplicação são os métodos de serviço. Definindo métodos de serviço Para definir os métodos de serviço, é necessário identificar as requisições que deverão ser tratadas pela aplicação, avaliar os parâmetros que serão recebidos e o que deverá ser retornado para o cliente do modelo de domínio. Uma forma fácil de definir serviços é criar uma interface e uma implementação por caso de uso ou user story. Figura 1. Representação simplificada do modelo de domínio de comércio eletrônico. O modelo ilustrado na figura 2 inclui algumas classes e métodos necessários para organizar o fluxo da aplicação e permitir que o modelo lide com a lógica de negócios e trate as requisições dos usuários. Além disso, o modelo também inclui interfaces de repositórios que lidam com as entidades persistentes. 12

Para ilustrar como o modelo de domínio pode tratar requisições dos usuários, consideremos a situação na qual o usuário está navegando pelo site e deseja adicionar um produto ao carrinho de compras. O objeto do carrinho de compras pode ficar na sessão do usuário para que o estado conversacional entre cliente e servidor seja mantido ao longo das requisições. Pode-se definir uma classe de serviços para tratar as requisições referentes às operações do carrinho de compras e lidar com cada requisição. Como o objeto do carrinho de compras fica armazenado na sessão do usuário, ele deve ser fornecido para o modelo pela camada de apresentação. Um Front Controller deve somente receber requisições e pode delegar a descoberta do componente que tratará uma requisição específica a um Application Controller. Dessa forma, a tarefa de instanciar um carrinho de compras caso não exista um na sessão do usuário e fornecê-lo para o modelo não se encaixa em nenhum desses componentes. Uma opção é criar uma classe similar a um Application Service, que seria uma camada entre o modelo e os Controllers cujo objetivo seria impedir que o modelo se acople à camada de apresentação, pois é necessário lidar com os objetos HttpServletRequest e HttpSession, já que o carrinho de compras fica na sessão do usuário. A Listagem 1 apresenta parcialmente uma possível implementação para a interface ServicosCarrinhoCompras, incluída no modelo ilustrado na figura 2. item.setquantidade(quantidade); carrinho.adicionaritem(item); public void alterarquantidade(carrinhocompras carrinho, long iditem, int quantidade) { Produto produto = repositorioprodutos.encontrarproduto(iditem); ItemCarrinhoCompras item = criaritemcarrinhocompras(produto); carrinho.alterarquantidade(item, quantidade); public void removeritem(carrinhocompras carrinho, long iditem) { Produto produto = repositorioprodutos.encontrarproduto(iditem); ItemCarrinhoCompras item = criaritemcarrinhocompras(produto); carrinho.removeritem(item); // Implementação dos outros métodos omitida... Através da implementação parcial da interface ServicosCarrinho- Compras, pode-se perceber que o objetivo de um método de serviço é receber as requisições dos clientes do modelo de domínio, recuperar entidades através de um repositório e delegar a execução das tarefas a essas entidades, organizando assim o fluxo da aplicação. Como a camada de apresentação já possui uma referência ao objeto do carrinho de compras, não é necessário retorná-lo em nenhum dos métodos. Em um caso onde seja necessário retornar valores, pode-se retornar os objetos de domínio ou criar novos objetos contendo os dados requeridos pelo cliente do serviço. No caso do método finalizarpedido(), da interface ServicoCarrinhoCompras, é retornado um objeto Pedido, contendo os dados a serem exibidos na tela de fechamento de pedido. A Listagem 2 apresenta a implementação da classe CarrinhoCompras, utilizada pela classe ServicosCarrinhoComprasDefault. Repositórios Figura 2. Modelo de domínio de comércio eletrônico com elementos do Domain Model. Listagem 1. Implementação parcial da interface ServicosCarrinhoCompras. public class ServicosCarrinhoComprasDefault implements ServicosCarrinhoCompras { private RepositorioProdutos repositorioprodutos; public ServicosCarrinhoComprasDefault( RepositorioProdutos repositorioprodutos) { super(); this.repositorioprodutos = repositorioprodutos; public void adicionaritem(carrinhocompras carrinho, long iditem, int quantidade) { Produto produto = repositorioprodutos.encontrarproduto(iditem); ItemCarrinhoCompras item = criaritemcarrinhocompras(produto); Um repositório abstrai um framework de persistência através de uma interface. Pode-se utilizar JDBC diretamente, entretanto, uma aplicação enterprise envolve muitos comandos SQL, e mantê-los pode consumir muito tempo. Assim, uma abordagem mais prática é a utilização frameworks de persistência que usam mapeamento objetorelacional, como o Hibernate, por exemplo. As classes persistentes devem ser mapeadas para que possam ser persistidas. Pode-se também utilizar a Java Persistence API, que pode ser utilizada dentro ou fora de um container Java EE. Nesse caso, os repositórios utilizariam um EntityManager. A Listagem 3 apresenta a classe RepositorioProdutosHibernate, que é uma possível implementação da interface RepositorioProdutos utilizando o framework Hibernate. Essa implementação estende uma classe utilitária do Spring chamada HibernateDaoSupport, que oferece vários métodos utilitários que facilitam a implementação do repositório, como save, load, find, flush etc. Em uma aplicação enterprise, colaborações envolvendo vários objetos são inerentes. No exemplo mostrado na Listagem 1, um objeto da classe ServicosCarrinhoComprasDefault depende de uma implementação da interface RepositorioProdutos. Um objeto que implementa essa interface poderia ser instanciado dentro da classe ServicosCarrinho- ComprasDefault e então utilizado. No entanto, uma abordagem que proporciona mais flexibilidade é definir o arranjo de objetos utilizando-se de injeção de dependência, fornecida pelo próprio Spring. No 13

: : www.mundoj.com.br : : exemplo em questão, trata-se de injeção de dependência via construtor, que é uma das três formas possíveis de injeção de dependência. Dessa forma, pode-se trocar a implementação utilizada sem alterar o código do modelo de domínio. A Listagem 4 mostra como algumas classes do modelo de domínio abordado neste artigo podem ser arranjadas, utilizando o Spring. Para tanto, deve-se definir um arquivo XML e indicar alguns parâmetros no web.xml da aplicação, para que objetos sejam corretamente instanciados e arranjados pelo Spring quando a aplicação for iniciada. Dessa forma, quando a aplicação for iniciada, os objetos de domínio já estarão prontos para serem utilizados. No entanto, em alguns casos, não é possível tirar proveito da injeção de dependência. Não seria possível, por exemplo, injetar um objeto instanciado pelo Spring em um Servlet porque Servlets são instanciados pelo web container. Nesses casos, pode-se implementar uma fábrica de objetos arranjados pelo Spring, como mostra a Listagem 5, e utilizá-la como mostra a Listagem 6. Listagem 2. Implementação da classe CarrinhoCompras. // imports omitidos public class CarrinhoCompras { private Set<ItemCarrinhoCompras> itens = new HashSet<ItemCarrinhoCompras>(); public void adicionaritem(itemcarrinhocompras item) { itens.add(item); public void removeritem(itemcarrinhocompras item) { itens.remove(item); public Pedido finalizarpedido() { Pedido pedido = new Pedido(); Iterator<ItemCarrinhoCompras> it = itens.iterator(); while (it.hasnext()) { ItemCarrinhoCompras item = it.next(); pedido.adicionaritem(item); Listagem 3. Implementação da interface RepositorioProdutos utilizando Hibernate. // imports omitidos public class RepositorioProdutosHibernate extends HibernateDaoSupport implements RepositorioProdutos { public RepositorioProdutosHibernate(HibernateTemplate template) { super(); sethibernatetemplate(template); public Produto encontrarproduto(int idproduto) { return (Produto) gethibernatetemplate().load(produto.class, new Integer(idProduto)); // Implementacao dos outros metodos omitida... Listagem 4. Arranjo de objetos de domínio com o Spring. <bean id= hibernatetemplate class= org.springframework.orm.hibernate3.hibernatetemplate > <property name= sessionfactory ref= sessionfactory /> <bean id= repositorioprodutos class= br.com.mj.ec.domain.repositorioprodutoshibernate > <constructor-arg ref= hibernatetemplate /> <bean id= servicoscarrinhocompras class= br.com.mj.ec.domain.servicoscarrinhocomprasdefault > <constructor-arg ref= repositorioprodutos /> Listagem 6. Recuperando beans através da fábrica de beans do Spring. pedido.setstatuspedido(statuspedido.pedido_aberto); return pedido; public void alterarquantidade(itemcarrinhocompras item, int quantidade) { Iterator<ItemCarrinhoCompras> it = itens.iterator(); while (it.hasnext()) { ItemCarrinhoCompras itemcarrinho = it.next(); if (itemcarrinho.equals(item)) { itemcarrinho.setquantidade(quantidade); break; // Implementacao dos outros metodos omitida... // Recuperando um bean do Spring utilizando a fabrica // O nome do bean eh o ID definido no XML de definicao de // beans do Spring FactoryBean fabrica = SpringBeansFactory.getInstance(); String beanname = servicoscarrinhocompras ; ServicosCarrinhoCompras servicos = (ServicosCarrinhoCompras) fabrica.getbean(beanname); Como a Listagem 1 mostra, a classe ServicosCarrinhoComprasDefault recebe uma instância da interface RepositorioProdutos no construtor. Isso é possível porque os dois objetos serão instanciados pelo próprio Spring. No entanto, essa abordagem nem sempre funciona para entidades porque entidades são instanciadas pelo framework de persistência. É por essa razão que a entidade Pedido recebe RepositorioPedido no método finalizarpedido. Para testar a classe Pedido, pode-se utilizar um objeto mock, representando a interface Repo- 14