Compartilhamento de modelo de dominio

28 respostas
spranta

Pessoal, estou participando de um projeto que possui vários sistemas com alguns pontos relacionados.
Explicando melhor, tenho um sistema de emissao de Nota Fiscal e outra de Declaração de Notas. Esses dois sistemas tem quase todo o modelo de dados identico, mas existem algumas diferenças, e algumas funcionalidades de um sistema servem para o outro.
Enfim, a intenção do gestor do projeto é que o modelo de classes destes dois sistema sejam compartilhados, desta forma, nós teriamos um projeto em separado só com as classes de dominio que modelam um contexto unico mas que engloba as situações dos dois sistemas e para tanto, na aplicação web de ambos os sistemas existirá um jar que representa esse conjunto de classes de dominio compartilhados por ambos os sistemas.
Na pratica tudo parece lindo, ou seja, eu teria em um projeto separado por exemplo, a classe NotaFiscal, que teria regras de negocio de ambos os sistemas. No entanto, estou com alguns problemas de definição deste modelo integrado de classes. O principal é o hibernate; uso o hibernate e portanto eu espero que as classes do meu modelo de dominio sejam as mesmas classes utilizadas para mapeamento objeto relacional de cada sistema, acontece que como disse anteriormente, apesar da grande semelhança um sistema tem algumas particularidades de outro, como fazer então para que a mesma classe represente mapeamentos diferentes. Se eu tivesse um modelo de dominio unico compartilhado, mas separado das classes de mapeamento do hibernate em que cada sistema teria o seu, seria mais facil, no entanto, acredito que isso nao é o correto.
Enfim, será que é possivel esse tipo de integração entre sistemas, faze-los compartilhar um modelo de dominio de classes, para reaproveitar pontos em comum?

28 Respostas

sergiotaborda

Algumas ideias:

) Não usar o hibernate
) Não usar modelo compartilhado
) Construir um meta-modelo , ou seja, um modelo que contém tudo o que é comum
e a partir desse contruir os outros dois modelos a partir de herança.
Assim vc tem o que é comum em um só lugar mas tem dois modelos separados para o hibernate entender.

reinaldob

Olá !

Você pode compartilhar o que é comum através de composição, onde nessas entidades onde realmente é comum o mapeamento é o mesmo, e vc cria outras classes com os atributos específicos e mapeamentos específicos.
Só toma cuidado com o cache do hibernate nessas duas aplicações hein, é fácil de dar zica… muito fácil !! :wink:

[]´s

Emerson_Macedo

Provavelmente existe uma confusão sobre o que é de cada sistema. O ideal é que cada um tenha seu Domínio e troquem mensagens via algum protocolo (e.g. REST, RMI (EJB), SOAP, etc.).

Se você puder dar um exemplo concreto de alguma coisa em comum dos 2 sistemas eu posso tentar ajudar.

spranta

Cada vez mais tenho concluido que o melhor é realmente manter dominio separados, acho que tentar fazer algo conjunto se realmente for possível só vai gerar é mais problemas e inclusive vai aumentar consideravelmente o custo de manutenção devido a mudanças que podem refletir em outro sistema, vai ser complicado.
Mas quem sabe, vamos discutir mais um pouco.
Emerson, os dois sistemas tem todo o modelo de endereçamento (Pais,Estado, Cidade, Logradouro) igual, também a a parte de cadastro de Pessoa, Empresa, Contato, Documento em comum, além também da parte de Atividade, Servicos, Aliquotas e bla bla bla, também em comum.
Ou seja, o que difere de ambos é a parte Nota Fiscal, um dos sistema gera a Nota Fiscal enquanto outro serve para declarar as NotasFiscais, neste contexto, meu modelo tem o seguinte, uma super classe DocumentoFiscal (compartilhado) e as sub-classe NotaFiscal (do sistema de geracao de nota fiscal) e DocEmitido e DocRecebido (sistema de declaração de nota fiscal e outros documentos fiscais). Desta forma, o sistema de declaração de nota fiscal poderia inclusive aproveitar do objeto nota fiscal que inicialmente era só do outro sistema para por exemplo buscar as notas fiscais emitidas por certa pessoa, para fazer uma declaração automatizada, ao invés de ter de digitar tudo.
Compreendeste?

Emerson_Macedo

Provavelmente a maioria dos seus objetos pertence ao Domínio do sistema que declara (ou cadastra) as notas fiscais. O sistema que gera as notas irá consumir serviços para obter as informações necessárias.

De qualquer forma, eu não entendi o motivo de ter 2 sistemas. Existe algum requisito que te impeça de gerar a nota no mesmo sistema que faz o cadastro da mesma?

spranta

Emerson Macedo:

De qualquer forma, eu não entendi o motivo de ter 2 sistemas. Existe algum requisito que te impeça de gerar a nota no mesmo sistema que faz o cadastro da mesma?

Sim, o sistema que gera é web, enquanto que o sistema que declara ela é desktop

reinaldob

Nesse cenário, onde só muda o frontend, será que não compensa vc ter somente módulos separados ?

O que eu quero dizer ?
Criar um módulo onde está todo o seu domínio (entidades da declaração e emissão da nota), e dois outros módulos que seriam sua GUI, um para Web e outro para Desktop.
Você não cria uma complexidade particionando seu domínio, e ainda por tabela consegue separar bem sua interface, deixando livre para no futuro implementar telas que estão em Web para Desktop e vice-versa, sem grandes traumas, afinal seu domínio está em outro módulo.

[]´s

Emerson_Macedo

spranta:
Emerson Macedo:

De qualquer forma, eu não entendi o motivo de ter 2 sistemas. Existe algum requisito que te impeça de gerar a nota no mesmo sistema que faz o cadastro da mesma?

Sim, o sistema que gera é web, enquanto que o sistema que declara ela é desktop


Nesse caso, você tem a opção de ter apenas um Domínio e ter uma camada de aplicação disponível para as duas UIs. A UI desktop vai estar num TIER diferente. Portanto, você pode usar uma Fachada Remota ou alguma outra técnica. A Web UI você não precisará usar nada disso pois apesar de estar num LAYER diferente, pode ficar no mesmo TIER que está sua camada de aplicação e Dominio.

spranta

Olá Reinaldo,
Até o momento, é justamente isso que estamos fazendo. Temos um projeto chamado model-core que possui todas as ditas classes de dominio compartilhadas, seus DAO’s e algumas classes Services. Enquanto que abaixo temos dois sub-projetos (módulos), o sistema web e o sistema desktop, que dependem (Required Projects do Eclipse) os dois do model-core e fazem uso das classes ali criadas, desta forma é que estamos compartilhando o modelo, e desta forma então durante a distribuicão de cada módulo, cada um leva junto consiguo um model-core.jar
Meu problema é que não é mudado somente o front-end, esta não é a diferença destes módulos, as aplicações tem proposito de negocio diferentes, tem funcionalidades diferentes, mas o apoio delas, principalmente aqueles cadastros auxiliares são quase que iguais. Então minha dúvida seria como conseguir reaproveitar em ambos os modulos, estas classes criadas no model-core levando-se principalmente em consideração o fato de tais classes serem as classes de mapeamento objeto-relacional do hibernate e que além disso cada sub-modulo tem uma ou outra diferença no mapeamento de algumas classes (Endereco por exemplo), e se essa maneira (criando este tal model-core) seria a melhor escolha de se fazer isso mesmo ou é melhor manter tudo cada um com seu dominio proprio e quando ouver necessidade de troca de serviços eu invoco o serviço remotamente via algum protocolo como disse o Emerson?

spranta

Existe um porem. A aplicação desktop será em sua grande parte de execução, uma aplicação off-line, portanto ela nao pode invocar o dominio remotamente, minha intenção nesta historia toda é saber se a melhor opção seria mesmo fazer um modelo integrado de ambos os modulos (mesmo com todos estes problemas que o hibernate pode me causar em função disso) e distribuir isto via um jar colocado em cada sub-sistema ou se eu deveria deixar tudo separado mesmo.

reinaldob

Tem uma opção, que junta boa parte do que todos falaram, seria uma divisão de módulos(sub-sistemas, projetos do eclipse, etc.) algo assim :
[list]
dominio-geral
dominio-especifico-emissão-NF
dominio-especifico-declaração-NF
web-gera-NF
desktop-emite-NF
[/list]
Aí vamos supor um exemplo de Endereço como vc citou, vou criar alguns atributos de mentira ai só pra exemplificar :

Essa aqui tá no “domínio-geral”, e tem seu próprio mapeamento.

public class Endereco {
	private Long id;
	private String logradouro;
	...
	public String getLogradouro(){
		return this.logradouro;
	}
	...
}

Essa aqui tá no “domínio-emissão-nf” e também tem seu próprio mapeamento, e a classe de composição que tá dentro dela não tem um novo mapeamento, ela usa o do outro módulo.

public class EnderecoEmissao {
	private Endereco endereco;
	private String portaoEntrega;
	...
	public String getLogradouro(){
		return this.endereco.getLogradouro();
	}
}

Eu tenho uma estrutura parecida com essa, mas eu uso o maven, então ele me ajuda bastante, pois tem resources que são compartilhados também, ele já explode pra mim dentro as dependências e me adianta um lado, mas vc consegue fazer com as dependencias de projetos do eclipse que vc comentou.

Assim vc reaproveita o código, mas só tem que ver se o seu domínio continua representando a visão idealizada pelo cliente/analista. As vezes não vale a pena tanto aproveitamento se tudo ficar rebuscado.

reinaldob

Hum… agora que eu vi a parte de ser offline…
Eh isso pode mudar um pouco os requisitos, e de repente o compartilhamento do domínio, ou pelo menos o mapeamento podem ser diferentes hein.
Pq offline, geralmente não combina muito com banco de dados pesado ou coisa assim, pode ser que realmente tenha um domínio ou mapeamento separado para o desktop.

Alessandro_Lazarotti

Se o domínio é diferente, então o Domain Model é diferente. Um avião voa feito um pássaro, mas possui comportamento e características diferentes, é uma outra entidade.

Só compartilhe domínio, se vc tem certeza que ele realmente representa o mesmo domínio em todos os sentidos e não apenas em similaridade.

Emerson_Macedo

Tudo bem, vai ser offline, mas como é que a aplicação online que gera as NFs vai acessar as informações geradas pela offline? Não entendi muito bem isso. Em algum momento as informações cadastradas por essa aplicação offline terão que ser disponibilizadas para essa online gerar as NFs. Pode explicar qual é a linha que vocês estão seguindo pra fazer isso acontecer?

spranta

Reinaldo, o caminho tomado até agora tem sido justamente esse ai que voce citou, no entanto, é complicado de ter dois mapeamentos distintos mas referenciando as mesmas classes (que seriam os POJOS utilizados pelo Hibernate).


Tudo bem, vai ser offline, mas como é que a aplicação online que gera as NFs vai acessar as informações geradas pela offline? Não entendi muito bem isso. Em algum momento as informações cadastradas por essa aplicação offline terão que ser disponibilizadas para essa online gerar as NFs. Pode explicar qual é a linha que vocês estão seguindo pra fazer isso acontecer?

Talvez essta tenha sido a confusão até agora e que eu não consegui me expressar bem.
Acontece que a aplicação de declaração da NFS-e não vai precisar (pelo menos até o momento) se comunicar coma aplicação on-line, elas não vão trocar mensagens, não quero ter um dominio compartilhado para esse fim.
Apesar delas terem um ponto bem em comum além de toda a estrutura de dados auxiliar que citei (endereço, atividade, …), é que na aplicação de geração eu tenho a Classe NotaFiscal e na aplicação de Declaração eu tenho a classe DocumentoFiscal (pode ser nota fiscal, pode ser boleto, …) desta forma a aplicação de Declaração poderia utilizar a Classe de NotaFiscal para tratar o Documento Fiscal quando ele for do tipo Nota Fiscal.
Mas sendo mais direto, minha intenção é que como elas (as aplicações) tem quase o mesmo modelo de dados, então o mapeamento objeto-relacional delas naquilo que é comum poderia ser reaproveitado , mas pelo que estou vendo eu estaria reaproveitando somente uma estrutura de dados da classe (a declaração dos atributos), e como o comportamento é distinto, ele não seria reutilizado, já não sei se compensa todo esta complexidade ao invés de isolar cada modelo de dominio.

Eu tenho uma grande parte do dominio de ambos os sistemas que são identicos, não deveria isso ser compartilhado?

Emerson_Macedo

spranta:
Talvez essta tenha sido a confusão até agora e que eu não consegui me expressar bem.
Acontece que a aplicação de declaração da NFS-e não vai precisar (pelo menos até o momento) se comunicar coma aplicação on-line, elas não vão trocar mensagens, não quero ter um dominio compartilhado para esse fim.

Sinceramente eu não entendi. Se eles não se comunicam, como a aplicação online vai gerar as NFs que foram cadastradas pela aplicação offline?

Olha o que você disse em outro post:

Com base nessa afirmação anterior e no que você está me dizendo agora, eu não to é entendendo mais nada…

Pode explicar melhor isso?

spranta

É o inverso do que você está pensando.
Primeiro eu tenho um sistema web que gera a NF.
Depois eu tenho um sistema desktop que declara as NF’s geradas por mim e as NF’s tomadass por mim (aquelas que a minha empresa pegou de outros prestadores), lembrando que eu posso nem estar utilizando o sistema web para geração de NF, eu poderia fazer a geração de NF manualmente e portanto somente utilizar o sistema desktop que declara para o governo as minhas notas fiscais emitidas e aquelas recebidas.

Emerson_Macedo

Ah tá. Agora eu entendil. Se você tivesse explicado isso no começo ficaria bem mais fácil. :wink:

Agora o que eu acho é que você tem 2 Domínios completamente diferentes. Por que? Simplemente porque Nota Fiscal para o sistema que gera não tem nada a ver com a Nota Fiscal para o sistema que registra. Portanto, abrigam conceitos diferentes. Portanto, cada sistema terá sua NF para fins diferentes. O que eu quero dizer com isso?

Imagine um objeto Funcionario. Você não iria ter um comportamento irAoBanheiro() por exemplo em um Sistema RH. Mas se esse objeto Funcionario fosse de um software tipo um SecondLife da vida, onde ele precisa andar, correr, etc, talvez esse comportamente faça sentido.

Essa analogia foi meio grotesca mas é pra mostrar que o objeto tem que fazer sentido em um contexto e não necessariamente em mais de um.

No seu caso, e principalmente como os sistemas não se integram de forma alguma, você terá um objeto NotaFiscal que terá estado e responsabilidades relacionadas a geração de Notas Fiscais e outro que pelo que eu entendi do seu sistema nem terá responsabilidades pois parece ser um simples cadastro.

spranta

Isto mesmo Emerson, me desculpe por nao ter sido tão claro no inicio do post, é que as vezes a gente que tá trabalhando no problema já assume os conceitos mais facilmente e nao explicamos tao detalhadamente aos outros.
Mas entao, com relação a entidade NotaFiscal, vejo que realmente eles são distintos entre os dois sistemas, no entanto, e o restante do modelo que ambos os sistemas tem muito em comum, são cerca de umas 40 tabelas que são identicas para ambos os sistemas e que poderiam ser mapeadas pelo hibernate igualmente para ambos. Voces nao acham que isso poderiam ser parte de um dominio compartilhado?

Emerson_Macedo

Sinceramente, se você tem 40 tabelas realmente idênticas eu não entendo o motivo da concepção desses 2 sistemas serem dessa forma, ao invés de pensar numa alternativa naquela linha que mencionei anteriormente.

Em todo caso, pense nos problemas que criar esse JAR compartilhado poderá te causar. Sempre que um dos sistemas precisar mudar uma classe você vai ter que executar testes em ambos pra ter certeza que a mudança não quebrou alguma coisa no outro sistema.

Uma coisa perigosa de acontecer é: você ficar mudando o JAR e só atualiza-lo no sistema demandante da alteração. Depois de muito tempo, quando o outro sistema precisar demandar alguma alteração e for pegar o JAR atualizado, isso pode causar problema. Você pode também descobrir que uma demanda de um sistema é conflitante de alguma forma com alguma outra que foi gerada pelo outro sistema um tempo atrás.

Ferryman

Eai

Estou sem muito tempo para postar, mas dá uma pesquisada em BondedContext, ContextMap e Shared Kernel que são patterns do DDD. A sua situação me parece um shared kernel.

[]s

Emerson_Macedo

Eu pensava que Shared Kernel fosse dentro do mesmo Sistema/Domínio, compartilhando objetos entre módulos. Nunca pensei nisso aplicado a mais de um sistema. Talvez seja uma opção, não sei.

Eu prefiro optar por pensar em 2 sistemas cada um tendo seu Domínio e se comunicarem via serviços.

Especificamente no caso do nosso amigo, está claro que esses 2 sistemas deveriam trocar mensagens, mas por algum motivo que eu ainda não consegui entender, uma aplicação não pode conversar com a outra.

Ferryman

Emerson,

Talvez vc tenha razão… Acho que uma coisa que ajudaria a esclarecer é pensar se realmente são dois sistemas! porque se grande parte do domino é comum, isso nao poderia ser um sistema só, com um shared Kernel e 2 Contextos e duas camadas de visualização?

Emerson_Macedo

Então, se você der uma lida no meu primeiro post, vai ver que eu sugeri 2 UIs. Claro que internamente podemos ter um Shared Kernel, 2 contextos, etc. Mas como ele disse que não pode ter 2 UIs pra mesma coisa e que os sistemas não se comunicam de forma alguma, ficou algo meio como que um beco sem saída porque (1) Um dos sistemas roda na Web online e outro é um Desktop off-line e (2) um sistema não pode se comunicar com o outro sei lá o motivo e (3) pelo visto cada um tem sua base de dados independente.

spranta

Os dois sistemas, são independentes, mas possuem similaridades (que é a grande parte do modelo de dados, das tabelas de apoio, mas cada um tem a sua base independente), um é web e outro é desktop (off-line durante a operação toda do usuario, sendo que somente no final do dia ou sei lá quando, é que ele utilizará um web-service ou algum outro protocolo para enviar os dados das declarações nele feitas para um terceiro sistema que recebe tais declarações).
Ou seja, tenho um sistema web que gera, outro desktop que declara. Este dois sistemas são independentes, tem suas proprias bases de dados tem finalidades diferentes apesar de terem regras comuns como calculo de imposto e outras coisas, mas o que eles tem de mais comum é a estrutura da base de dados, quase todas as tabelas de apoio se assemelham, entao minha duvida era se compensava ou não criar um projeto em separado que modelasse o modelo de dominio de ambos ou pelo menos essa parte em comum para que eu tivesse um reaproveitamento.
No entanto, percebo que isto irá me causar mais problemas do que facilidades, o que eu posso fazer é estar componentizando algumas regras de negocio em comum como o calculo de impostos, mas sem utilizar objetos de dominio nisto, visto que cada um teria suas proprias classes, ou seja, o modelo de dominio (tbem de mapeamento objeto - relacional) nao poderá ser compartilhado e sim construido de forma independente.

Emerson_Macedo

Pergunta: Os sistemas tem que ser dessa forma por imposição de alguém ou vocês que escolheram assim?

Pra mim isso ta meio mau pensado …

Se você tem 2 sistemas que tem uma area de interesse um pouco comum e que você tem que duplicar 40 tabelas, isso não te parece estranho?

spranta

O sistema tem de ser assim, um web que atende determinado tipo de usuario e tem uma finalidade propria (geracao de nfse) e outro desktop que atende outro tipo de usuario que nem sempre tem acesso a internet e com outra finalidade (declaração de nfse recebida e gerada)

C

spranta:
Pessoal, estou participando de um projeto que possui vários sistemas com alguns pontos relacionados.
Explicando melhor, tenho um sistema de emissao de Nota Fiscal e outra de Declaração de Notas. Esses dois sistemas tem quase todo o modelo de dados identico, mas existem algumas diferenças, e algumas funcionalidades de um sistema servem para o outro.
Enfim, a intenção do gestor do projeto é que o modelo de classes destes dois sistema sejam compartilhados, desta forma, nós teriamos um projeto em separado só com as classes de dominio que modelam um contexto unico mas que engloba as situações dos dois sistemas e para tanto, na aplicação web de ambos os sistemas existirá um jar que representa esse conjunto de classes de dominio compartilhados por ambos os sistemas.
Na pratica tudo parece lindo, ou seja, eu teria em um projeto separado por exemplo, a classe NotaFiscal, que teria regras de negocio de ambos os sistemas. No entanto, estou com alguns problemas de definição deste modelo integrado de classes. O principal é o hibernate; uso o hibernate e portanto eu espero que as classes do meu modelo de dominio sejam as mesmas classes utilizadas para mapeamento objeto relacional de cada sistema, acontece que como disse anteriormente, apesar da grande semelhança um sistema tem algumas particularidades de outro, como fazer então para que a mesma classe represente mapeamentos diferentes. Se eu tivesse um modelo de dominio unico compartilhado, mas separado das classes de mapeamento do hibernate em que cada sistema teria o seu, seria mais facil, no entanto, acredito que isso nao é o correto.

O modelo de classes dos dois sistemas nao deveriam ser compartilhados, o que deve ser compartilhado é o domínio. Aplicações que manipulam notas fiscais interagem com o dominio onde exista tal conceito. Eu não sei qual a relação sistema <-> domínio vc faz mas em relaçao a dominio <-> database eu penso sempre numa associacao 1 pra 1. E não se deve basear no modelo de dados para definir o que é o dominio, se for pra ser assim esqueca objetos e seja feliz!

Em relação a sua dúvida é difícil pra mim dizer se a diferenca entre os sistemas de emissão e declaracao é de natureza do negócio ou da aplicacao, na dúvida não dividiria o dominio a principio. Da mesma forma poderia sugerir que utilizasse Shared Kernel para compartilhar o dominio mas é possível que a equipe não esteja ciente das implicacoes dessa ato.

Criado 27 de maio de 2008
Ultima resposta 29 de mai. de 2008
Respostas 28
Participantes 7