[Prévia] [Próxima] [Prévia por assunto] [Próxima por assunto]
[Índice cronológico] [Índice de assunto]

Re: [reverbel-sod] [EP1] Manipular estado do Customer



On Fri, 2006-04-14 at 01:36 -0300, Rafael de F. Ferreira wrote: 
> Não discordo que esta solução resolve o problema, e sem maiores
> consequências no nosso caso. Mas antes eu disse que não gostava muito
> dela porque, do ponto de vista de orientação à objetos, acho que não é
> o melhor procedimento. O que poderia ser uma interação direta entre
> dois objetos do domínio acaba sendo intermediada por um repositório de
> dados externo e isso torna difícil implementar e manter regras de
> negócio mais complicadas que as do EP. 

Não estou entendendo sua objeção. A maioria das aplicações com objetos
persistentes usa um repositório de dados externo (geralmente um BD
relacional) para armazenar o estado dos objetos. O repositório externo é
uma realidade em boa parte dos cenários. Não adianta nada negar essa
realidade, pois há muitos motivos para se guardar o estado dos objetos
num BD. Também não é muito produtivo se opor ao BD relacional em nome da
orientação a objetos... O desejável é ter um modelo de domínio OO e um
modelo de dados relacional que convivam bem um com o outro. 

> Um exemplo é se existisse um
> requerimento para impedir que os Customers alugassem filmes se tiverem
> algum empréstimo atrasado. Esse tipo de lógica se encaixaria
> naturalmente no objeto customer, mas como ele não fica sabendo da
> transação de aluguel, teríamos que encontrar algum outro lugar mais
> artificial para implementar esse código.

Você está questionando o fato da operação que estabelece uma associação
entre um Customer e uma MovieCopy estar na MovieCopy e não no Customer?
Repare que há também o requisito de só alugar os exemplares de filme que
se encontram na loja (ou seja, nunca alugar um MovieCopy que está com
algum Customer). Para fazer isso é preciso que o MovieCopy fique sabendo
da operação de aluguel, ou que seja pelo menos consultado antes do
aluguel acontecer...

Por outro lado, o Customer precisaria ser consultado para implementar o
requisito que você especificou. Mas isso não significa que a operação de
aluguel (rentTo) deva ser movida do MovieCopy para o Customer. Basta
ter, no Customer, uma operação de consulta à condição "temFitaEmAtraso".
A operação rentTo poderia checar essa condição antes de efetuar o
aluguel.

> Essa questão se relaciona com o problema todo de Entidades vs.
> Serviços. Se uma chamada remota (como à rentTo) desencadear uma
> cascata de outras chamadas remotas síncronas então a performace é
> bastante prejudicada. Além disso, percebemos a dificuldade envolvida
> em alterar uma interface remota publicada para interoperação entre
> grupos diversos. O Ted Neward falou sobre isso numa entrevista
> recente: "Once you publish an interface like that, you can never
> change it because getting all of those players to agree on a change is
> just flat out impossible. You lose health, sanity and hair when you do
> this." (http://tinyurl.com/kpxgv). Uma service façade bem definida
> (talvez com pontos de extensão) na frente de um modelo de domíno
> não-remoto deixa o modelo mais flexível para evolução e evita a queda
> de performance com da cascata de invocações remotas.

Sim, essa é a razão de ser do padrão serviço/sessão de fachada.

Reverbel

> My 2 cents.
> Rafael de F. Ferreira.
> 
> On 4/13/06, Francisco Reverbel <reverbel@xxxxxxxxxx> wrote:
> > On Sun, 2006-04-09 at 22:46 -0300, Rafael de F. Ferreira wrote:
> > > Estou com uma dúvida a respeito de como registrar o alguel de um
> > > exemplar para as entidades Customer.
> > >
> > > Na IDL do Customer não consta nenhuma operação para manipular a
> > > MovieCopyList dos exemplares alugados. Como a operação rentTo(...) da
> > > interface MovieCopy recebe uma referência remota para um Customer,
> > > também não posso fazer um downcast para o tipo do servant do customer.
> > > Sem contar que não é boa prática ficar fazendo casts o tempo todo.
> > >
> > > Eu pensei em dois workarounds, mas nenhum parece muito legal. Uma
> > > alternativa seria fazer o servant do Customer buscar em algum lugar
> > > conhecido a lista de MovieCopy's alugadas para ele no momento em que
> > > precisasse.
> >
> > Essa solução não é ruim. Faça o servente da MovieCopy ter um campo com o
> > id do Customer para o qual a MovieCopy foi alugada. (Pense em como se
> > implementa um relacionamento 1 para N num BD relacional: colocando na
> > tabela correspondente à entidade que aparece com cardinalidade N uma
> > coluna com a chave estrangeira da tabela correspondente à entidade que
> > aparece com cardinalidade 1 no relacionamento.)
> >
> > Para construir a lista de MovieCopies alugados para um Customer,
> > percorra a coleção de serventes de MovieCopy e olhe o campo "id do
> > Customer" de cada servente. (No caso de entidades armazenadas num BD
> > relacional, você faria isso com um comando SQL: "SELECT ID FROM
> > MOVIE_COPY MC WHERE MC.CUSTOMER_ID = CUSTOMER_ID".) Note que a coleção
> > de serventes de MovieCopy servirá também para implementar a interface
> > MovieCopyHome.
> >
> > Repare que basta obter o id (chave) de cada MovieCopy. Tendo esses ids,
> > você pode convertê-los em referências CORBA para objetos MovieCopy
> > chamando poa.id_to_reference() (caso você use um POA com a política
> > RETAIN e deixe todos os objetos MovieCopy ativos o tempo todo) ou
> > poa.create_reference_with_id() (se os objetos MovieCopy não ficarem
> > ativos o tempo todo -- este vai ser o caso no EP2).
> >
> > Você também pode fazer conversão de id em referência CORBA para
> > implementar o método getTaker() no servente da MovieCopy. Tendo o campo
> > "id do Customer" nesse servente, basta converter o id em referência
> > CORBA para um Customer.
> >
> > Em vez de ter, no servente da MovieCopy, um campo com o id desse
> > Customer que alugou a MovieCopy, uma outra alternativa é ter, nesse
> > servente, um campo com uma referência CORBA para o Customer que alugou a
> > MovieCopy.
> >
> > > Outra maneira seria implementar o método
> > > MovieCopy.rentTo(...) de modo a buscar uma referência local para o
> > > servant concreto do Customer no servidor através do ID dele e chamar
> > > uma operação como CustomerImpl.rent(MovieCopy).
> >
> > Só agora entendi que você está querendo estabelecer links na outra
> > direção (de Customer para uma coleção de MovieCopies). Isso é
> > desnecessário, basta o link de MovieCopy para Customer.
> >
> > Reverbel
> >
> > > Alguém tem alguma sugestão?
> > >
> > > Obrigado;
> > > --
> > > Rafael de F. Ferreira.
> > >
> >
> >
> 
> 
> --
> Rafael de F. Ferreira.
>