Probleminha OOAD (DDD Repositórios)

128 respostas
rodrigoy

Amigos,

Motivado pelo post do Paulo sobre repositórios aqui no GUJ, quero fazer uma pergunta para saber a opinião e para vocês refletirem.

Imagine que você está fazendo um sistema de hotel (que é o estudo de caso do nosso curso OOAD com UML2. Se quiser, veja o documento de visão linkado (não é necessário ler o documento todo, mas quem tiver curiosidade em ver a “big picture”)

Num determinado ponto do sistema há o seguinte requisito:

  • Ao efetuar a reserva o sistema deverá exibir uma lista de quartos disponíveis para o período da estadia do hóspede.

Pergunta: Quem responde pela lista de quartos disponíveis para o período?

a. O repositório de Quartos?

b. O repositório de Reservas?

c. Faço uma query na UI usando Scriptlet…

Justifique sua resposta.

128 Respostas

Ferryman

Voto na Opção 1,

Pois julgo ser responsabilidade do quarto saber se ele está ocupado.
Parece mais intuitivo ler o código: TodosQuartos.getDisponiveis do que TodasReservas.getQuartosDisponiveis.

Se você tiver que procurar no sistema aonde está a regra para exibir os quartos disponíveis, minha primeira tentativa seria procurar algo relacionado com quarto, e não com reserva.

[]s

peerless

Um quarto que controla o periodo em que ele ficará reservado ?

:wink:

rodrigoy

Pertinente a sua pergunta. Não o quarto não sabe (ou não precisaria saber) é algo assim:

(realmente o yuml.me é viciante)

tnaires

Tenho uma dúvida: um quarto está indisponível quando está reservado? Ou apenas quando está ocupado?

rodrigoy

Quando está reservado, lógico! Veja que a pergunta é quartos disponíveis no período. Se há uma reserva futura para o quarto ele está reservado para aquele período.

Emerson_Macedo

Eu implementaria de acordo com a opção 1.

Na opção 2, TodasReservas retornar uma lista de quartos não me parece muito intuitivo.

[]s

joellobo

Opção 1. O repositório TodasReservas poderia ter um método como getQuartosReservados(periodo):Quartos mas não getQuartosDisponiveis(periodo):Quartos. Apesar de ter exceções, como no exemplo do seu post (Yoshima), a regra 1 repository para cada aggregate está resolvendo a maioria dos meus problemas.

rodrigoy

Qual a diferença? :?

MarceloAraujo

Não tem essa opção, mas…pq não hotel.getQuartosDisponiveis(periodo):Quartos ?
Parece ser mais coerente com o negócio e também com a OO.

bruno77sa

olá rodrigo,

eu não faria em nenhum repositorio apresentado, porque este requisito não esta em nenhum deles, veja:

1-O repostorio de quartos, representa uma colecao de quartos, pelo requisitos apresentados o que define se esta reservado ou não é a relacao de agregacao entre o mesmo e sua reserva, ou seja aqui não é o lugar, aqui só tenho minha caixa de quartos, não tenho informacão sobre reservas aqui.

2-daria pra fazer no repositorio de reservas, mas a ideia deste objeto no sistema seria representar apenas os quartos com reserva no periodo, e para atender esse requisito o repositorio de reservas deveria saber sobre todos os quartos, o que acredito que não seja o intuito do mesmo.

e agora? como resolver?

Service!!!

public  class ServiceReservas{
      public getQuartosDisponiveis(periodo):Quartos{
           Set  todosQuartos        =  TodosQuartos.getTodosQuartos();   //nome  tosco  eu sei :)
           Set quartosReservados = TodasReservas.getQuartos(periodo); //reserva so vê quartos reservados, ou pelo menos deveria!!
           Set quartosDisponiveis =  todosQuartos.removeAll(quartosReservados); 
           return quartosDisponiveis;
     }

}

outra versão!!

public  class ServiceReservas{
      public getQuartosDisponiveis(periodo):Quartos{
           Set  todosQuartos        =  Quartos.getTodos();   
           Set quartosReservados = Reservas.getQuartosReservados(periodo); 

           Set quartosDisponiveis =  todosQuartos.removeAll(quartosReservados); 
           return quartosDisponiveis;
     }

}

vamos as observacões

obs:1 desconsiderem esse meu codigo java, ha 3 anos que não mexo no bichinho,sei que tem erro ai!!
obs:2 desconsiderem os nomes dos metodos, pensei rapido aqui!!
obs:3 meu teclado disconfigurou aqui linux,por isso engoli os acentos! :slight_smile:

bem essa é minha visão, eu faria desta forma, o que achas? :slight_smile:

FredMP

Eu acho que fica mais coerente TodosQuartos.getDisponiveis, opção 1.

Mas:

Qual a diferença? :?
Nesse caso acho que ele quis dizer que TodasReservas deve conhecer quartos relacionados a elas, as reservas. Portanto, apenas os quartos reservados. Mas, no fundo se vc sabe todos os reservados para um período, a principio, os que sobram são os disponíveis. Embora isso possa não ser de todo verdade, pois podem haver outras formas de se indisponibilizar um quarto além da reserva, como colocá-lo em manutenção ou interditá-lo talvez.

rodrigoy

MarceloAraujo:
Não tem essa opção, mas…pq não hotel.getQuartosDisponiveis(periodo):Quartos ?
Parece ser mais coerente com o negócio e também com a OO.

Marcelo, se você for nessa linha de pensamento um monte de coisas irão ser questionada para o Hotel. E outra: Já parou para pensar que isso é um Singleton? Quem dá a instância de Hotel?

Hotel é o domínio que estou modelando. Neste caso, me é estranho ter um elemento Hotel dentro do domínio Hotel.

rodrigoy

É uma boa justificativa.

A Reserva depende de Quarto independente de Quartos estarem reservados ou não. Porém, quartos não sabem da existência de reservas.

Service é transacional e sua execução tem efeito colateral, o que não acontece com o requisito solicitado. É só uma busca por informações. Você está modelando um novo repositório com nome de service.

rodrigoy

FredMP:

Nesse caso acho que ele quis dizer que TodasReservas deve conhecer quartos relacionados a elas, as reservas. Portanto, apenas os quartos reservados. Mas, no fundo se vc sabe todos os reservados para um período, a principio, os que sobram são os disponíveis.

Seu raciocínio está certo. No último diagrama que postei fica claro que reservas sabem da existência de quartos. A associação deixa a dependência explícita. O contrário é que não é verdade. Quartos não dependem de reserva.

FredMP:

Embora isso possa não ser de todo verdade, pois podem haver outras formas de se indisponibilizar um quarto além da reserva, como colocá-lo em manutenção ou interditá-lo talvez.

Isso não está nos requisitos!

[piadinha](cada dia que passa eu vejo que não é o cliente que aumenta o escopo… são os programadores…) :slight_smile: [/piada]

FredMP

Nem tinha reparado nessa opção! :shock: :smiley:

rodrigoy:

FredMP:

Embora isso possa não ser de todo verdade, pois podem haver outras formas de se indisponibilizar um quarto além da reserva, como colocá-lo em manutenção ou interditá-lo talvez.

Isso não está nos requisitos!

Acredite… esse requisito irá aparecer logo logo! :twisted:

MarceloAraujo

rodrigoy:
MarceloAraujo:
Não tem essa opção, mas…pq não hotel.getQuartosDisponiveis(periodo):Quartos ?
Parece ser mais coerente com o negócio e também com a OO.

Marcelo, se você for nessa linha de pensamento um monte de coisas irão ser questionada para o Hotel. E outra: Já parou para pensar que isso é um Singleton? Quem dá a instância de Hotel?

Hotel é o domínio que estou modelando. Neste caso, me é estranho ter um elemento Hotel dentro do domínio Hotel.

Ok. A minha intenção foi dizer q nenhum dos 2 repositórios parece ser o responsável por responder quais quartos estão disponíveis num período de tempo. Isso partindo do princípio que vão existir os 2 repositórios que você mencionou e que TodosQuartos conhece apenas os Quartos que o hotel tem e TodasReservas conhece apenas Reservas e seus respectivos Quartos reservados.

Faz sentido todasReservas saber algo sobre os quartos q não estão reservados, num determinado período de tempo?
Ou então todosQuartos saber algo sobre período de tempo, que é uma característica de reserva?

Sendo assim você vai precisar de alguém que assuma a responsabilidade de subtrair os "“quartos reservados para o período informado”, da “listagem geral de quartos do hotel” e com isso ter em mãos a lista de quartos disponíveis para o período. Ou seja, alguém que tenha acesso aos 2 repositórios que você criou ou alguém que assuma a responsabilidade de lidar com os dois domínios (Reserva e Quarto) quando eles estão associados e também quando não estão.

Pelo menos é o que me vem a mente agora :slight_smile:

fantomas

Quando alguem quer fazer uma viagem e está enteressado em fazer uma reserva fala com quem no hotel?

Setor / departamento / alguem / etc… que cuida das reservas certo? Me avise se eu estiver enganado.

Portanto a minha primeira intenção seria colocar esta responsabilidade no repositório que controla as reservas.

flws

Link_pg

Olá!

Imaginemos como isso seria feito manualmente: um quadro na parede com vários quadradinhos, cada um representando um quarto existente no hotel. Em cada quadradinho, haveria 3 informações básicas: o número do quarto, o tipo (simplesinho, fodão, mais ou menos) e o preço da diária.


|||||||
|||||||
|||||||

Beleza, agora imagine que quando alguém vai lá e pede pra reservar o quarto, a moça da recepção pegue um post-it e escreva: o nome do cara que reservou e o período da reserva. Após fazer isso, ela vai no quadradinho que representa o quarto que o fulano escolheu e cola o post-it.

Como ela faria pra dizer quais quartos estão disponíveis? Contaria todos os quadradinhos que não houvessem post-it’s colados. Agora, tirando o meu da reta, como traduzir isso pro sistema? aheuheauauhe

Uma pergunta: o quarto terá uma reserva ou uma reserva terá um quarto?

Abraços

fantomas

link_pg:
Olá!

Imaginemos como isso seria feito manualmente: um quadro na parede com vários quadradinhos, cada um representando um quarto existente no hotel. Em cada quadradinho, haveria 3 informações básicas: o número do quarto, o tipo (simplesinho, fodão, mais ou menos) e o preço da diária.


|||||||
|||||||
|||||||

Beleza, agora imagine que quando alguém vai lá e pede pra reservar o quarto, a moça da recepção pegue um post-it e escreva: o nome do cara que reservou e o período da reserva. Após fazer isso, ela vai no quadradinho que representa o quarto que o fulano escolheu e cola o post-it.

Como ela faria pra dizer quais quartos estão disponíveis? Contaria todos os quadradinhos que não houvessem post-it’s colados. Agora, tirando o meu da reta, como traduzir isso pro sistema? aheuheauauhe

Uma pergunta: o quarto terá uma reserva ou uma reserva terá um quarto?

Gostei…primeiro o negócio (o sistema) depois a tecnologia. Seria ótimo se alguem soubesse como a coisa toda funciona na realidade.

Respondendo: Na minha opinião, detesto ter que “achar” alguma coisa em sistemas mas vamos lá senão não tem brincadeira, a reserva é uma entidade constituida pela uma associação do quarto com “quem” é dono da reserva (fora outros detalhes). O quarto “X” tem uma reserva seria uma resposta “construida/deduzida” pelo modelo. Na verdade os quadradinhos (idéia bacana essa) seriam as reservas ao meu ver.

flws

luistiagos

Realmente acho que a opção 1 seria a mais correta…
pois a reserva pode tornar um quarto indisponivel… a reserva conhece o quarto e o quarto não conhece a reserva porem ele pode saber se ele (o quarto) esta ou não disponivel. E vejamos o seguinte… mesmo que não esta no escopo que uma manutenção por exemplo possa indisponibilizar um quarto hoje… nada impede que amanha este requisito apareça… e se deixarmos esta responsabilidade para a reserva se um dia surgir a manutenção tamo tudo fu***… pois a manutenção desta arquitetura nos dara mais dor de cabeça… Não se pode esquecer que um dos requisitos de uma boa app é ela ter a capacidade de extensão e nunca de alteração…

king_of_gods

1º Opção.

Como já falaram o quarto tem que saber responder se ele está ocupado ou não.

rodrigoy

A pergunta é: As reservas (que podem ser abstraídas como uma caixinha com Index Cards que ficam lá na recepção) conhecem todos os quartos?

rodrigoy

Link_pg:

Imaginemos como isso seria feito manualmente: um quadro na parede com vários quadradinhos, cada um representando um quarto existente no hotel…

Link, não vejo que é uma boa opção persarmos em Domain-Driven só imaginando como o usuário faria na mão. Isso vai gerar abstrações pobres na minha opinião.

Mas na sua idéia, quem saberia se o quarto está reservado ou não para um período? A caixinha que representa o quarto ou os post-its?

Imaginem o conjunto de quartos como os quartos fisicos mesmo (aonde estão as camas, o frigobar e etc…). Eles sabem se as reservas existem ou não?

rodrigoy

Não pode não… isso pode gerar uma dependência desnecessária.

luistiagos:

E vejamos o seguinte… mesmo que não esta no escopo que uma manutenção por exemplo possa indisponibilizar um quarto hoje… nada impede que amanha este requisito apareça… e se deixarmos esta responsabilidade para a reserva se um dia surgir a manutenção tamo tudo fu***…

E aquele papo esperto de YAGNI? Simplicidade?

luistiagos:

pois a manutenção desta arquitetura nos dara mais dor de cabeça… Não se pode esquecer que um dos requisitos de uma boa app é ela ter a capacidade de extensão e nunca de alteração…

Introduzir dependência desnecessária é o que ferra a sua arquitetura… O quarto, no mundo real, nunca sabe se ele está em manutenção ou não (o diagrama acima não muda o problema original, só postei aqui como ficaria a solução menos acoplada para a questão “quartos em manutenção” - não vamos complicar ainda mais a discussão).

Saber os quartos disponíveis tem mais a ver com quartos ou com Reservas?

tnaires

Acho que tem mais a ver com reservas. Ao contrário da maioria, não acho adequado um quarto saber se está reservado ou não. Fico com a opção dois.

fantomas

rodrigoy ,

Acho que o luistiagos se referiu a manutenção do sistema e não ao quarto do hotel.

flws

rodrigoy

Não não, fantomas, ele foi claro, certo luistiagos?

(inclusive naquela parte do fu****)

fantomas

Verdade, havia me esquecido desta parte.

Valeu!

ercardoso

Eu ficaria com o Repository de Reservas, considerando em minha opinião que temos Reservas com informações de quais os quartos reservados em determinados periodos.

ercardoso

Ops, desculpe … o objetivo são os quartos disponveis e não indisponíveis. :smiley:

ercardoso

Eu acredito que realmente pelo fato de eu querer os quartos disponíveis por periodo eu teria que saber das reservas os quartos reservados e por consequência trazer do repoistorio dos quartos os que não estão reservados. axo que precisariamos mais que um unico local.

luistiagos

eu me referi a manutensão do quarto… não vejo problema em delegar para o quarto saber se ele esta disponivel ou não… não importando o que lhe torne indisponivel… penso da seguinte forma… se o quarto não sabe se ele esta disponivel ou não… se quem sabe isto e a reserva… se surge um elemento diferente da reserva?

no caso delegando a responsabilidade para a reserva como vc resolveria então se um dia seu cliente coloque um terceiro fator que indisponibiliza o quarto? diferente da reserva? como manutenção, interditação, limpeza ou outro fator que não seja a reserva?

sobre este diagrama:

vendo que ambas as classes tem os periodos em comum… sujeria colocar uma interface Periodo onde qualquer elemento que possa inviabilizar um quarto implemente e esta interface faça sua agregação com o quarto… e não 2 classes identicas como na figura… assim não gera dependencias desnecessarias… apenas tera uma dependencia com uma interface e não se importaremos com quem a implemente…

viniciusv

Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

B

Documento de Visão:
4. A reserva é associar um período de tempo a um quarto, se uma pessoa quiser mais de um quarto são consideradas duas reservas; O sistema deve impedir reservas duplicadas de quartos em um mesmo período;

  1. O hóspede pode prorrogar a sua estadia, mas se existir reservas para o quarto que ele está, deve-se verificar a possibilidade de transferir a reserva para outro quarto de mesma classificação. Se a transferência não for possível, deve-se oferecer um quarto de classificação maior ao hóspede (nesse caso, o hospede seria transferido e uma nova reserva criada). Somente em último caso deve-se negar a prorrogação, porém, as reservas feitas com antecedência devem sempre ser respeitadas;

Reservas já são associações de quartos com períodos, e a reserva é o componente crítico da disponibilidade dos quartos. O repositório Reservas é que responde por essa lista.

Mesmo se escolhêssemos a opção 1, ela ainda teria que consultar as Reservas. Escolheria a opção 2 também para evitar duplicação da responsabilidade, ou delegação desnecessária.

rodrigoy

luistiagos, colocar mais requisitos vai mudar o problema, e com isso a discussão como um todo. Como falei, vamos esquecer essa questão manutenção de quartos e outros. Há outras maneiras de colocar mais requisitos e gerar as mudanças que provem qualquer ponto de vista. Vamos nos ater somente a Quartos e Reservas. OK? (de qualquer forma, não vejo a sua sugestão como melhor opção, podemos discutir depois).

Atentem o seguinte: A disponibilidade do quarto é temporal. A questão não é simplesmente “o quarto saber se ele está ocupado ou não”. A questão é: “na data xx/xx/xxxx o quarto está ocupado?”. Isso tem relação com quartos ou com reservas?

Link_pg

É, até seria plausível o quarto ter um atributo “disponivel”. Agora quem disponibiliza ou não disponibiliza, por quanto tempo, etc. é onde está o porém.

FredMP

Bom, como já disseram, internamente o repositório de quartos poderia usar o repositório de reservas para definir quais os disponíveis, já que todos pertencem ao domínio. No caso poderia ser uma implementação tipo a do bruno77sa, mas sem usar um service e usando o que o viniciusv colocou:

public class TodosQuartos { public Set disponiveisEntre(Date inicio, Date termino) { Set todosQuartos = getTodosQuartos(); Set quartosReservados = new TodasReservas().getQuartos(inicio, termino); Set quartosDisponiveis = todosQuartos.removeAll(quartosReservados); // Um pouco de BDUF: :-P // quartosDisponiveis = quartosDisponiveis.removeAll(new AlgumaOutraCoisaQueTorneOQuartoIndisponivel().get()); return quartosDisponiveis; } }

No caso de ter que lidar com outros tipos de indisponibilidade, bastaria trabalhar este método. Mas mesmo levando em conta apenas os requisitos colocados eu ainda deixaria a responsabilidade com o repositório de quartos. Mas é apenas minha opinião! (por enquanto) :smiley:
Essa discussão tá bem interessante!

rodrigoy

Err… vocês não acham isso um pouco estranho não?

(depois me falam que a UML não serve para nada)

fantomas

Ainda continuo indicando as reservas para tomar conta disto.

flws

luistiagos

rodrigoy:
luistiagos, colocar mais requisitos vai mudar o problema, e com isso a discussão como um todo. Como falei, vamos esquecer essa questão manutenção de quartos e outros. Há outras maneiras de colocar mais requisitos e gerar as mudanças que provem qualquer ponto de vista. Vamos nos ater somente a Quartos e Reservas. OK? (de qualquer forma, não vejo a sua sugestão como melhor opção, podemos discutir depois).

Atentem o seguinte: A disponibilidade do quarto é temporal. A questão não é simplesmente “o quarto saber se ele está ocupado ou não”. A questão é: “na data xx/xx/xxxx o quarto está ocupado?”. Isso tem relação com quartos ou com reservas?

certamente a questão temporal tem a ver com as reservas…
bem qual a melhor solução do problema então?

luistiagos

viniciusv:
Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

Por padrão na nomeclatura da propria sun e aconselhavel usar getters e setters… talvez vc pense que isto e uma tremanda de uma bobagem… porem se for usar reflection para automatizar um pouco as coisas precisara de td em um padrão… dai sim vc vai ver a verdadeira utilidade de padrão para nomeclaturas…

rodrigoy

gomesrod

rodrigoy:
Err… vocês não acham isso um pouco estranho não?
(…)

Acho que temos um impasse aqui:

Existem razões técnicas para achar que o repositório de reservas é o melhor lugar para obter essa informação (pelo fato de as reservas conhecerem os quartos e não o contrário). Porém, por outro lado, colocar isso no repositório de quartos é muito muito muito MUIIIITO mais intuitivo.

FredMP

luistiagos:
viniciusv:
Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

Por padrão na nomeclatura da propria sun e aconselhavel usar getters e setters… talvez vc pense que isto e uma tremanda de uma bobagem… porem se for usar reflection para automatizar um pouco as coisas precisara de td em um padrão… dai sim vc vai ver a verdadeira utilidade de padrão para nomeclaturas…

Concordo em parte com vc. Já trabalhei num código no qual precisei usar reflection e tive que seguir alguns padrões sim. E se vc for chamar esse método em uma expressão EL ou algo parecido será de fato ruim. Mas, pra começar a implementar o domínio acho que a idéia do viniciusv de dar mais expressividade é boa. Se depois aparecem limitações tecnológicas então terá que refatorar.
E rodrigoy: desculpe fugir do tema! :oops:

rodrigoy

gomesrod… para pra pensar: será que é intuitivo ou será que esse é o maior motivo que confundimos Repositórios com DAOs? Se você perguntar para o especialista do dominio do hotel ele vai te dizer que são as reservas que sabem se um quarto está disponível para um período ou não.

A maioria das pessoas relutam em ir para a opção 2 porque “me parece estranho um repositório de Reservas me retornar Quartos… nos DAOS isso nunca acontecia” (mesmo que para o domínio isso faça sentido).

A pergunta é: é intuitivo ou nós estamos acostumados a fazer sempre assim?

viniciusv

luistiagos:
viniciusv:
Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

Por padrão na nomeclatura da propria sun e aconselhavel usar getters e setters… talvez vc pense que isto e uma tremanda de uma bobagem… porem se for usar reflection para automatizar um pouco as coisas precisara de td em um padrão… dai sim vc vai ver a verdadeira utilidade de padrão para nomeclaturas…

Padrões, reflection ou qualquer outro aspecto meramente computacional não pode ser razão pra nomear as coisas na camade de domínio. Tratam-se de complexidade acidental [1], não coisas que, de fato, fazem parte do domínio em questão. Pense no mesmo sistema mas implementado usando Python ou Ruby.

[1] http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/[telefone removido]

rodrigoy

Sobre o nome:

Uma operação na maioria das vezes é uma ação e uma ação sempre requer um verbo. Me é estranho chamar TodasReservas.disponiveis(Date, Date), apesar de ficar bem ubiquo. TodasReservas.obterDisponiveis(Date, Date) pode ser mais indicado para quem não quiser o get.

Além disso, apesar de não ser convenção, operações getXXXX() no Java me remontam a Query Operations da UML (isto é, operações que não tem efeito colateral == não mudam o estado do objeto).

Quem já programa em Ruby sabe que lá não tem get, mas tem os métodos bang! para indicar aquilo que tem efeito colateral.

luistiagos

viniciusv:
luistiagos:
viniciusv:
Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

Por padrão na nomeclatura da propria sun e aconselhavel usar getters e setters… talvez vc pense que isto e uma tremanda de uma bobagem… porem se for usar reflection para automatizar um pouco as coisas precisara de td em um padrão… dai sim vc vai ver a verdadeira utilidade de padrão para nomeclaturas…

Padrões, reflection ou qualquer outro aspecto meramente computacional não pode ser razão pra nomear as coisas na camade de domínio. Tratam-se de complexidade acidental [1], não coisas que, de fato, fazem parte do domínio em questão. Pense no mesmo sistema mas implementado usando Python ou Ruby.

[1] http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/[telefone removido]

Talvez… mas ja parou pra pensar pq a propria sun resolveu criar um padrão? padrões é algo maravilhoso na hora de vc desenvolver algo… se algo e padronizado e tem digamos uma classe com um atributo custa… se vc usa padrões para os nomes em qualquer lugar vc deduzira que para retornar a custa chamara getCusta e não retornarCusta, exibirCusta, pegarCusta ou algo do genero… isto tornara implicito pois utiliza o padrão de nomeclatura… vc não precisa consultar a classe para saber como retornar determinado atributo…
isto se torna muito mais facil… mesmo que na outra maneira seja mais intuitivo… ou seja a padronização não serve so para o reflection saber oq ele esta fazendo e sim tbm para o programador saber o que ele esta fazendo sem precisar consultar o metodo para isto…

zinho

Legal ver discuções interessantes no GUJ novamente =)

http://domaindrivendesign.org/resources/ddd_terms

Não acho que seja apenas uma questão de estarmos acostumados a fazer sempre assim.
Me parece bem óbvio pensar em “retirar reservas” de um repositório de reservas e “retirar quartos” de um repositório de quartos.
Porém, nesse caso eu tenderia para o quesito técnico e colocaria o método no repositório de reservas para evitar a sequinte dependencia cíclica:

TodosQuartos - Quarto
      |          |
TodasReservas - Reserva
B

rodrigoy:
gomesrod:

Existem razões técnicas para achar que o repositório de reservas é o melhor lugar para obter essa informação (pelo fato de as reservas conhecerem os quartos e não o contrário). Porém, por outro lado, colocar isso no repositório de quartos é muito muito muito MUIIIITO mais intuitivo.

gomesrod… para pra pensar: será que é intuitivo ou será que esse é o maior motivo que confundimos Repositórios com DAOs? Se você perguntar para o especialista do dominio do hotel ele vai te dizer que são as reservas que sabem se um quarto está disponível para um período ou não.

A maioria das pessoas relutam em ir para a opção 2 porque “me parece estranho um repositório de Reservas me retornar Quartos… nos DAOS isso nunca acontecia” (mesmo que para o domínio isso faça sentido).

A pergunta é: é intuitivo ou nós estamos acostumados a fazer sempre assim?

Aí você está pressupondo que os DAOs estão errados, ou que eles só saibam responder perguntas onde todas os dados se encontram numa única tabela.

Eu acho intuitivo perguntar aos quartos sobre quartos, mesmo que eles não tenham todos os dados para responder à pergunta, e tenham que perguntar a um conhecido.

Da mesma forma, também acho estranho perguntar às Reservas sobre quartos.

Se formos por intuição, estranheza, aí vai cair no gosto pessoal de cada um.

Hehe, mais e mais acho que desenvolver software é entrar em acordo sobre como fazer. Não há somente uma resposta certa.

viniciusv

rodrigoy:
Sobre o nome:

Uma operação na maioria das vezes é uma ação e uma ação sempre requer um verbo. Me é estranho chamar TodasReservas.disponiveis(Date, Date), apesar de ficar bem ubiquo. TodasReservas.obterDisponiveis(Date, Date) pode ser mais indicado para quem não quiser o get.

Além disso, apesar de não ser convenção, operações getXXXX() no Java me remontam a Query Operations da UML (isto é, operações que não tem efeito colateral == não mudam o estado do objeto).

Quem já programa em Ruby sabe que lá não tem get, mas tem os métodos bang! para indicar aquilo que tem efeito colateral.

Eu concordaria com voce se o seu repositório de reservas tivesse um nome como ‘Repositorio’, ‘Gerenciador’ ou algo nessa linha, que passasse a idéia de ‘algo que armazena reservas’. Neste caso, faria todo o sentido pensar que o ‘Repositório’ obtém/faz/age. Ex: RepositorioReservas.obterDisponiveis(Date, Date) me soa melhor do que TodasReservas.obterDisponiveis(Date, Date).

Quando penso em TodasReservas, isso me passa a idéia de um conjunto, uma coleção. Neste caso, TodasReservas.disponiveisEm(periodo) parece ser mais próximo do que voce provavelmente vai ouvir do cliente quando ele lhe disser:

“Como atendente, preciso ver todas as reservas disponíveis em um periodo para que eu possa reservar um quarto para um hospede.”

boaglio

Eu achei os nomes TodosQuartos e TodasReservas meio confusos para as classes de repositório, parecem nomes de método.

tnaires

Já eu não penso assim porque a definição da entidade quarto não envolve sua disponibilidade para reservas. Podemos olhar a situação sob uma outra ótica e perceber que para verificar se um quarto está disponível, é necessário checar se há alguma reserva efetuada para ele. Para quem devemos fazer essa questão? Para aquele que dá acesso global às reservas, que é o repositório de reservas.

Link_pg

Acredito que vai depender de quem tem o que. (Pensando um pouco em facilitar a implementação)

1º Se o quarto tem uma reserva então deve ficar no repositório de quartos, pois o método perguntaria pra cada quarto se ele tem uma reserva ou não. Se tiver, vê se o período bate com o período passado por parâmetro. Se o período bater, não adiciona o quarto na lista de retorno, se não bater ou não tiver reserva, adiciona.

2º Se a reserva tem um quarto então deve ficar no repositório de reservas, pois o método perguntaria pra cada reserva qual seu período. Se bater com o período passado por parâmetro, passa a diante pra próxima reserva, se não bater, adiciona o quarto relacionado com a reserva numa lista auxiliar. Daí a lista de retorno seria algo como: todosOsQuartos - listaAuxiliar.

B

Já eu não penso assim porque a definição da entidade quarto não envolve sua disponibilidade para reservas. Podemos olhar a situação sob uma outra ótica e perceber que para verificar se um quarto está disponível, é necessário checar se há alguma reserva efetuada para ele. Para quem devemos fazer essa questão? Para aquele que dá acesso global às reservas, que é o repositório de reservas.

Sim, se você já tiver com o quarto em mãos, e quiser saber se ele está disponível ou não, você pergunta somente para a reserva de quartos.

Se você não quiser um quarto em específico, e quer saber sobre qualquer quarto disponível, você pega todos os quartos, pergunta para a reserva de quartos quais estão reservados, e tira estes do conjunto todo.

Não dá para perguntar diretamente para a reserva de quartos por que lá existe o subconjunto de quartos reservados, e não dá para inferir o conjunto inteiro a partir de um subconjunto.

Se qualquer forma terá que trabalhar com Quartos e Reservas. Quem chama quem é a questão aqui.

rodrigoy

Não uso essa nomenclatura ‘Repositorio’.

Como citaram aqui, repositórios possuem assinaturas de Collection. Devem atuar como tal.

luistiagos

Agora a questão de ser intuitivo é tbm importante… vc ja pensou se vc tenque fazer uma alteração na busca de quartos disponiveis e quem criou isto foi não foi vc… e não existe uml e nenhuma documentação do sistema… seu GP manda vc fazer a alteração em 15 min… com uma porrada de classes e dependencias… aonde vc vai procurar primeiro a bagaça? no repositorio de quartos creio eu…

fantomas

rodrigoy

Entendi o seu ponto de vista e tenho pensado bastante sobre o assunto (mas ainda não o suficiente); o que me incomoda um pouco nesta estratégia de criar o nome da classe que vc adotou é que o nome de uma classe segundo as “regras” da OO não deveria ser no plural e sim no singular. Corrija-me se achar que estou enganado. Ou seja, o nome TodasReservas, semanticamente falando, fica muito esquisito para mim; imagine uma coisa como esta aqui: TodasReservas todasResevas = new TodasReservas(); logo mais adiante TodasReservas outrasTodasReservas = new TodasReservas(). Fica muito confuso quando vc olha para o nome a não ser que a classe seja um Singleton mas aí “dá lhe conversa né?”

flws

gomesrod

Esses posts traduzem bem o que tinha em mente quando fiz o comentário:

Não acho que seja apenas uma questão de estarmos acostumados a fazer sempre assim.
Me parece bem óbvio pensar em “retirar reservas” de um repositório de reservas e “retirar quartos” de um repositório de quartos.

Bruno Laturner:
Aí você está pressupondo que os DAOs estão errados, ou que eles só saibam responder perguntas onde todas os dados se encontram numa única tabela.
Eu acho intuitivo perguntar aos quartos sobre quartos, mesmo que eles não tenham todos os dados para responder à pergunta, e tenham que perguntar a um conhecido.
Da mesma forma, também acho estranho perguntar às Reservas sobre quartos.

Posso estar redondamente enganado pois sou leigo em DDD, mas que fica estranho fica!

Indo um pouco além, cheguei a uma conclusão curiosa:
Um método TodasReservas.getQuartosReservados() não soaria tão estranho quanto o TodasReservas.getQuartosDisponiveis(), talvez porque o primeiro use apenas dados que são diretamente conhecidos pelas reservas (o “quarto” de cada uma), enquanto o segundo envolve uma pesquisa completa de quartos.

rodrigoy

fantomas:
rodrigoy

Entendi o seu ponto de vista e tenho pensado bastante sobre o assunto (mas ainda não o suficiente); o que me incomoda um pouco nesta estratégia de criar o nome da classe que vc adotou é que o nome de uma classe segundo as “regras” da OO não deveria ser no plural e sim no singular. Corrija-me se achar que estou enganado.

Te corrijindo, você está enganado:

Este não é o original da ISO. Pelo que me lembro isso entrou no padrão por conta da Literatura do Rumbaught de 1991.

TodasReservas representam uma coleção de Reservas.

:wink:

fantomas

rodrigoy

Obrigado pela correção!

Mas o meu incomodo com isto é em relação ao significado das coisas: por exemplo, seria muito mais simples a sugestão de nomes como People para todas pessoas ou WholeCars para todos os carros ao invés de PersonRepository ou CarRepository (me incomoda também a palavra repository). O que acontece é que quando se diz PersonRepository transmite a idéia, ao menos para mim, de que estou lidando com UM mecanismo agregador (repository) de entidades originadas DA (única) classe Person.

Valeu pela dica, vou pensar mais sobre o assunto.

Ótimo topico.

flws

zinho

O gomesrod levantou um ponto interessante.
Se existisse o método obterQuartosReservados não faria sentido colocá-lo em TodosQuartos pois a Reserva já possui um Quarto.
Apesar de, na minha opinião ficar bem semântico, também não faria sentido colocar o método obterQuartosReservados em TodasReservas e o método obterQuartosDisponíveis em TodosQuartos.
Logo, ainda vejo como melhor opção colocá-lo no repositório de reservas!

rodrigoy

fantomas:
por exemplo, seria muito mais simples a sugestão de nomes como People para todas pessoas ou WholeCars para todos os carros ao invés de PersonRepository ou CarRepository

PersonRepository, PessoaRepository, PessoaRepositorio não faz sentido para as pessoas do domínio. Esse é o meu ponto. WholeCars não faz sentido. Estamos dando exemplos em português.

sergiotaborda

Rodrigo, não me leve a mal e o que vou dizer a seguir é apenas para ajudar.
Vc está exigindo escolher 1 de 3 pre-definidas. Eu não considero nenhuma delas a resposta certa. Não sei se isso é de propósito para estabelecer algum ponto no curso mas, eis como eu resolveria :

Vc tem que mostrar os quartos disponíveis, mas isso não significa que tenha que procurar os quartos disponíveis.
O que vc quer, na realidade é mostrar quais reversas são possíveis para que a pessoa escolha uma. O quarto, como mostrou, é um dos fatores, mas as datas são outro. Se o quarto está disponível apenas por 1 dia e a pessoa vai ficar três, então esse quarto não pode ser reservado e não deve aparecer como opção.

A minha resposta seria então :

d. Faço uma pesquisa em TodasReservas por getReservasPossiveis(Periodo)

Isso irá trazer uma lista de objectos reserva com as datas iguais às do periodo e os quartos iguais aos disponiveis. Se vc quiser mesmo mostrar os quartos vc usar reserva.getQuarto()

É claro que por detrás dos panos vc irá procura apenas os quartos e montar os objettos reserva “on demand” no repositorio porque essas reservas não existem “fisicamente” no banco. Mas existem no dominio. Tanto é que vc está procurando por elas.

sergiotaborda

luistiagos:
viniciusv:
Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

Por padrão na nomeclatura da propria sun e aconselhavel usar getters e setters… talvez vc pense que isto e uma tremanda de uma bobagem…

A sun usa para javabeans e ejb que são tecnologias, não padrões. Outros frameworks usam beans (não javabeans) e get/set representam as propriedades do bean.
A ideia do viniciusv é válida porque disponíveis não é uma propriedade de TodosOsQuartos porque esse objeto não é um bean , nem um javabean , nem um (entity) EJB : ou seja, ele não tem propriedades logo ele não têm get/set .
O prefixo padrão para reposiorios é find e poderiamos colocar encontraDisponiveis. Mas disponiveisEm é ainda melhor. (curiosamente find era o prefixo em ejb 2 para métodos de pesquisa, que são na essencia o que constitui um respositorio)

viniciusv

luistiagos:
viniciusv:
luistiagos:
viniciusv:
Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

Por padrão na nomeclatura da propria sun e aconselhavel usar getters e setters… talvez vc pense que isto e uma tremanda de uma bobagem… porem se for usar reflection para automatizar um pouco as coisas precisara de td em um padrão… dai sim vc vai ver a verdadeira utilidade de padrão para nomeclaturas…

Padrões, reflection ou qualquer outro aspecto meramente computacional não pode ser razão pra nomear as coisas na camade de domínio. Tratam-se de complexidade acidental [1], não coisas que, de fato, fazem parte do domínio em questão. Pense no mesmo sistema mas implementado usando Python ou Ruby.

[1] http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/[telefone removido]

Talvez… mas ja parou pra pensar pq a propria sun resolveu criar um padrão? padrões é algo maravilhoso na hora de vc desenvolver algo… se algo e padronizado e tem digamos uma classe com um atributo custa… se vc usa padrões para os nomes em qualquer lugar vc deduzira que para retornar a custa chamara getCusta e não retornarCusta, exibirCusta, pegarCusta ou algo do genero… isto tornara implicito pois utiliza o padrão de nomeclatura… vc não precisa consultar a classe para saber como retornar determinado atributo…
isto se torna muito mais facil… mesmo que na outra maneira seja mais intuitivo… ou seja a padronização não serve so para o reflection saber oq ele esta fazendo e sim tbm para o programador saber o que ele esta fazendo sem precisar consultar o metodo para isto…

Discordo. Getters/Setters são, na maioria das vezes, algo negativo. Objetos possuem estado e comportamento relacionados. É responsabilidade de um objeto receber mensagens e decidir por sí mesmo se muda de estado ou não. Getters/setters expõe a implementação do estado para fora da classe, fazendo com que este estado possa mudar imprevisivelmente e criando dependencias indesejáveis. Estado e lógica relacionados devem estar juntos [1]!

Além disso, getters/setters baseiam-se em implementação, não em intenção. Digamos que voce queira um método para justificar um parágrafo. Voce poderia fazer isso com um setter:

… que na verdade quer dizer “estou setando o valor CENTERED no attributo justification”. Não seria melhor…

… que diz exatamente o que voce quer, que é centralizar o parágrafo?

Recomendo a leitura desse post do Philip Calçado sobre esse assunto. Bem esclarecedor.

[1] http://www.amazon.com/Implementation-Patterns-Addison-Wesley-Signature-Kent/dp/[telefone removido]

luistiagos

viniciusv:
luistiagos:
viniciusv:
luistiagos:
viniciusv:
Só uma sugestão: que tal trocar TodosQuartos.getDisponiveis(periodo) por TodosQuartos.disponiveisEm(periodo) ?
Nomes são importantes. E se a língua escolhida para nomear as coisas for o português, provavelmete não existirá esse ‘get’ na linguagem do domínio.

Por padrão na nomeclatura da propria sun e aconselhavel usar getters e setters… talvez vc pense que isto e uma tremanda de uma bobagem… porem se for usar reflection para automatizar um pouco as coisas precisara de td em um padrão… dai sim vc vai ver a verdadeira utilidade de padrão para nomeclaturas…

Padrões, reflection ou qualquer outro aspecto meramente computacional não pode ser razão pra nomear as coisas na camade de domínio. Tratam-se de complexidade acidental [1], não coisas que, de fato, fazem parte do domínio em questão. Pense no mesmo sistema mas implementado usando Python ou Ruby.

[1] http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/[telefone removido]

Talvez… mas ja parou pra pensar pq a propria sun resolveu criar um padrão? padrões é algo maravilhoso na hora de vc desenvolver algo… se algo e padronizado e tem digamos uma classe com um atributo custa… se vc usa padrões para os nomes em qualquer lugar vc deduzira que para retornar a custa chamara getCusta e não retornarCusta, exibirCusta, pegarCusta ou algo do genero… isto tornara implicito pois utiliza o padrão de nomeclatura… vc não precisa consultar a classe para saber como retornar determinado atributo…
isto se torna muito mais facil… mesmo que na outra maneira seja mais intuitivo… ou seja a padronização não serve so para o reflection saber oq ele esta fazendo e sim tbm para o programador saber o que ele esta fazendo sem precisar consultar o metodo para isto…

Discordo. Getters/Setters são, na maioria das vezes, algo negativo. Objetos possuem estado e comportamento relacionados. É responsabilidade de um objeto receber mensagens e decidir por sí mesmo se muda de estado ou não. Getters/setters expõe a implementação do estado para fora da classe, fazendo com que este estado possa mudar imprevisivelmente e criando dependencias indesejáveis. Estado e lógica relacionados devem estar juntos [1]!

Além disso, getters/setters baseiam-se em implementação, não em intenção. Digamos que voce queira um método para justificar um parágrafo. Voce poderia fazer isso com um setter:

… que na verdade quer dizer “estou setando o valor CENTERED no attributo justification”. Não seria melhor…

… que diz exatamente o que voce quer, que é centralizar o parágrafo?

Recomendo a leitura desse post do Philip Calçado sobre esse assunto. Bem esclarecedor.

[1] http://www.amazon.com/Implementation-Patterns-Addison-Wesley-Signature-Kent/dp/[telefone removido]

A casos e casos… neste exemplo realmente não faz necessario o uso de um setter… pois o proprio objeto pode muder seu estado… porem qdo necessitamos de uma interação entre objetos, uma representação das entidades? como javabeans por exemplo… dai sim faz sentido…

viniciusv

rodrigoy:
Não uso essa nomenclatura ‘Repositorio’.

Como citaram aqui, repositórios possuem assinaturas de Collection. Devem atuar como tal.

Rodrigoy, o que eu quero dizer, sobre essa sua nomenclatura é o seguinte: TodosQuartos ou TodasReservas não me dá a idéia de uma coleção, de uma lista, de um repositório, enfim, de um objeto… me dá a idéia de vários objetos ao mesmo tempo. Tudo bem em mandar um objeto executar uma ação, mas vários objetos ao mesmo tempo soa meio desconfortável à leitura. Olha só:

ListaDeQuartos.getDisponiveis(periodo) ok, pois leio "hey lista de quartos, me dê os disponíveis no periodo tal."
ColecaoDeQuartos.getDisponiveis(periodo) ok, pois leio "hey coleção de quartos, me dê os disponíveis no periodo tal."
RepositorioDeQuartos.getDisponiveis(periodo) ok, pois leio "hey repositório de quartos, me dê os disponíveis no periodo tal."
TodosQuartos.getDisponiveis(periodo) estranho, pois leio “hey todos os quartos, me dê os disponíveis no periodo tal.”

Por outro lado, TodosQuartos.disponiveisEm(periodo) ok, pois leio “quero todos os quartos disponíveis em tal periodo.”

Não estou encrencando com a sua escolha de nome do repositório, que por sinal é bem melhor do que todas as outras alternativas. Estou dizendo que o nome dos métodos que voce escolheu causam (ao menos a mim) um pouco de desconforto na leitura. Isso sem falar nesse ‘get’, que como já falei, parece um feijão no dente da ubiquitous language.

luistiagos

Pelo jeito o assunto aqui disvirtuou… começou em Repositorios e terminou em nomeclaturas…

boaglio

rodrigoy:

PersonRepository, PessoaRepository, PessoaRepositorio não faz sentido para as pessoas do domínio. Esse é o meu ponto. WholeCars não faz sentido. Estamos dando exemplos em português.

Talvez InformacoesDePessoas, InformacoesDeQuartos, InformacoesDeReservas, não sei, ainda está estranho…

Edufa

boaglio:
rodrigoy:

PersonRepository, PessoaRepository, PessoaRepositorio não faz sentido para as pessoas do domínio. Esse é o meu ponto. WholeCars não faz sentido. Estamos dando exemplos em português.

Talvez InformacoesDePessoas, InformacoesDeQuartos, InformacoesDeReservas, não sei, ainda está estranho…

Eu acho que o nome Reservas, funciona melhor do que TodasReservas, me parece mais intuitivo.

E a consulta de quartos disponiveis deveria estar em Reservas.

Reservas reservas = new ReservasImpl(...); List<Quarto> reservas.getQuartosDisponiveis(Periodo periodo) {...}

Um quarto não sabe se está disponivel ou não, para saber se está disponivel tem de ver se no periodo tem alguma reserva feita, se tiver não está disponivel.

rodrigoy

Sergio, dei as alternativas mais para facilitar a reflexão.

Apesar de ser uma solução plausível, “reservas possíveis” é um termo novo do domínio. Creio que feriria a UL. Mas você concorda então que a responsabilidade é das reservas. Certo?

rodrigoy

Edufa, é uma alternativa. Eu já usei… ficou melhor que ReservaRepositorio, mas por alguma razão, descartei essa nomenclatura. Acho que é por ser muito próximo do nome da entidade e alguns nomes ficam estranhos.

rodrigoy

viniciusv:

Não estou encrencando com a sua escolha de nome do repositório, que por sinal é bem melhor do que todas as outras alternativas. Estou dizendo que o nome dos métodos que voce escolheu causam (ao menos a mim) um pouco de desconforto na leitura. Isso sem falar nesse ‘get’, que como já falei, parece um feijão no dente da ubiquitous language.

Vinicius… meus repositórios são JavaBeans, pois uso muito DDD com JBoss Seam e não tenho preconceito de usá-los (meus repositórios) diretamente na UI. Algo como:

#{todasCategorias.ativas}

TodasCategorias.getAtivas()

Mas fique à vontade de usar de outras maneiras. Não fere muito o conceito que preguei aqui.

(gostei desse termo… um feijão no dente da UL) :wink:

rodrigoy

Meu repositório pode ser um Javabean se eu decidir que sim, certo? (leia meu post anterior)

zinho

sergiotaborda wrote:
A ideia do viniciusv é válida porque disponíveis não é uma propriedade de TodosOsQuartos porque esse objeto não é um bean , nem um javabean , nem um (entity) EJB : ou seja, ele não tem propriedades logo ele não têm get/set .

Meu repositório pode ser um Javabean se eu decidir que sim, certo? (leia meu post anterior)

Mesmo porque, falando em OO, qualquer objeto tem propriedades. Independente de bean, javabean ou seja lá o que for!

sergiotaborda

rodrigoy:
sergiotaborda:

A ideia do viniciusv é válida porque disponíveis não é uma propriedade de TodosOsQuartos porque esse objeto não é um bean , nem um javabean , nem um (entity) EJB : ou seja, ele não tem propriedades logo ele não têm get/set .

Meu repositório pode ser um Javabean se eu decidir que sim, certo? (leia meu post anterior)

Antes de mais é preciso cuidar o fato que JavaBean é um nome especial ( se escreve até com TM).
ELe designa uma tecnologia em que o objeto tem propriedades e além disso ele tem listenerts para alteração dessas propriedades. O SwingBeans, por exemplo, tira partido desta tecnologia.

Um objeto só com get/set mas sem o mecanismo de listeners não é um javabean. (Um entity ejb 3 não é um javabean)
Um objeto com listeners que não sejam para a alteração das propriedades não são javabeans.

O seu repositório têm propriedades ?

  • se sim, então ele pode ter propriedades e listeners e virar um javabean
  • se não, não ha como ser um javabean

Os meus não têm. Se os seus têm, por favor dê um exemplo que fiquei curioso.

Se vc nunca viu isso, então é dificil aceitar que possam ser javabeans.

sergiotaborda

rodrigoy:

Apesar de ser uma solução plausível, “reservas possíveis” é um termo novo do domínio. Creio que feriria a UL. Mas você concorda então que a responsabilidade é das reservas. Certo?

Com certa a responsabilidade é de quem conseguir procurar quartos e datas. Essas coisas são reservas, então não tem como fugir que o respositorio seja o de reservas. Mas, o retorno não pode ser quartos. Esse , acho, que é o ponto mais importante.

Não acho que reservas possiveis seja um novo termo, mas mesmo que seja, ele não é uma nova entidade, logo o dominio não mudou. Por outro lado, sem adicionar esse novo conceito não ha como resolver o problema que vc propos dentro do SoC.

Claro que vc pode sempre usar TodasReservas.getReservas(Periodo) para não incluir o novo termo …

Na prática, eu acho, vc chegaria na conclusão logica que é preciso esse conceito e vc propunha isso para o cliente. E ai , ou ele confirma que é isso mesmo ou ele propoe uma alternativa coerente. Por exemplo, ele pode achar que fica melhor : TodasReservas.getReservasAbertas(Periodo).

Acho que a palavra final para o sufixo é irrelevante. Ele vai vir naturalmente da conversa com o cliente e ser adicionado ao UL. O ponto da analise é descobrir que esse sufixo é necessário (aka essa “categoria” de reservas).

Da sua resposta parece que não ha espaço para adicionar coisas à UL atual. Acho que isso não é a realidade prática já que o processo é inerentemente interativo e iterativo.

rodrigoy

Vc tem razão, meus repositórios não tem listeners e não vejo razões para ter listeners…

(para falar a verdade, isso deveria ser out-of-the-box no Java)

Um repositório poderia ser um Javabean numa aplicação desktop local.

rodrigoy

Você acha que é um pecado imperdoável um repositório de Reservas retornar Quartos, mesmo que isso faça sentido para os especialistas do domínio e os usuários?

[essa pergunta é para todos, não só para o taborda]

B

Você acha que é um pecado imperdoável um repositório de Reservas retornar Quartos, mesmo que isso faça sentido para os especialistas do domínio e os usuários?

[essa pergunta é para todos, não só para o taborda]

O que eu acho ruim é metodologia ou arquitetura tentando me dizer o que eu posso ou não posso fazer, ou pior, seguidores cegos destes falando o mesmo.

Se os usuários, especialistas e você, o desenvolvedor, falam A, não tem gente de fora que diga B ou C. Não quer dizer não vou ouvir nem considerar, mas sem meter o dedo onde não é chamado.

sergiotaborda

Você acha que é um pecado imperdoável um repositório de Reservas retornar Quartos, mesmo que isso faça sentido para os especialistas do domínio e os usuários?

Como qualquer teosofo sabe todos os pecados são perdoáveis :lol:
Nâo acho que seja um pecado. Acho que é uma falha lógica.Sendo uma falha acho que dá para fazer melhor.
Se o especialista de domínio e os usuários disserem que dois hospedes nunca terão o mesmo nome você modela o sistema seguindo essa regra ? Eu não o faria porque sei que isso é uma falha lógica.

Na minha experiência a realidade do mundo vem primeiro que a opinião dos usuários ou dos especialistas pela simples razão que a realidade não tem falhas lógicas. É por isso que estudamos matemática e lógica. Outros programadores que virão depois mexer no código sempre poderão apelar para a lógica para entender o sistema. Eles não terão esse guia se a opinião falhada dos usuários se sobrepuser. Mas isso, acaba sendo um problema entre você e eles : os usuários e especialista por um lado e os seus peers desenvolvedores por outro…

Colocar um repositório de X retornar Y acho que não é lógico. Sendo assim o detalhe tem que ser contornado no design e no modelo para que seja lógico. às vezes temos que ir mais longe. Temos que chegar em algo como Hotel.getQuartosLivresParaReservaEm(Periodo) : Quartos. Isto dá o que você quer, é ainda mais realista que um objeto chamado TodasReservas e é semântico o suficiente para usuarios e programadores.

Mesmo que os pecados sejam perdoáveis a graça é não os cometer em primeiro lugar.

Esquecendo a UL por um pouco, do ponto de vista puramente OO um repositório de X retornar Y é uma violação do objetivo do próprio objeto repositório. Se vc não quer que o repositorio de X retorna sempre X porque vc afirmar que é o repositorio de X se na realidade posso encontrar nele outras coisas ? É como ter um TodasPessoas e ter um TodasPessoas.getAnimaisDeEstimação() : AnimaisEstimação … animais de estimação não são pessoas, que magia é essa que me permite tirar animais de onde só ha pessoas ?

Claro que vc pode optar por dizer que o repositório é agnóstico, que ele não é de X ou Y e que não ha problema algum em TodosX retornarem Y. Ok. Mas por esse mesmo agumento não ha por que ter dois repositórios , um para X e outro para Y. Basta ter um RepositorioGeral que encontra tudo de qualquer tipo.

Não sei se ficou claro. O ponto é: Se você divide responsabilidade de procura para objetos diferentes baseado na associação a uma entidade , isso tem que significar algo. Não pode simplesmente ser ignorado quando é tentando a violar essa divisão que você mesmo criou por algum motivo de simplificação técnica ou porque lhe pediram para ser assim. Ou vc divide em N repos e mantém a coerencia (coesão) dessa divisão sempre, ou vc só tem 1 repositório universal e pronto. Coisas no meio não são lógicas. Para mim não são.

Concordando com o Bruno Laturner eu também acho que seguir as coisas cegamente é ruim. A diferença é que eu considero que boa arquitetura e design dão visão e não tiram como vcs parecem achar. Não é preciso ter poderes mágicos ou ser visionário para criar um bom design. É só seguir a regras. O argumento que as regras podem ser dribladas em condições especiais não é lógica para mim e realmente eu vejo isso como um pecado de corrupção.

Bom design , principios e regras, nunca trazem problemas. Não os seguir é que sim traz.

fantomas

rodrigoy:
Você acha que é um pecado imperdoável um repositório de Reservas retornar Quartos, mesmo que isso faça sentido para os especialistas do domínio e os usuários?

[essa pergunta é para todos, não só para o taborda]

Falar pecado imperdoável acho meio forte pra isso, mas ao meu ver parece fazer sentido, pois se não houver quartos não haverá reservas, logo se vc receber reservas (orientação do repositório) como resposta logo haverá quartos associados fornecendo-lhe respostas a respeito desta entidade. Talvez a questão não seja o fazer sentido e sim se isto é realmente necessário. Acredito que os requisitos ajudem nesta hora.

flws

fantomas

sergiotaborda:
Concordando com o Bruno Laturner eu também acho que seguir as coisas cegamente é ruim. A diferença é que eu considero que boa arquitetura e design dão visão e não tiram como vcs parecem achar. Não é preciso ter poderes mágicos ou ser visionário para criar um bom design. É só seguir a regras. O argumento que as regras podem ser dribladas em condições especiais não é lógica para mim e realmente eu vejo isso como um pecado de corrupção.

Bom design , principios e regras, nunca trazem problemas. Não os seguir é que sim traz.

Gostei bastante desta parte.

[]'s

Marcio_Duran

fantomas:
Você acha que é um pecado imperdoável um repositório de Reservas retornar Quartos, mesmo que isso faça sentido para os especialistas do domínio e os usuários?

essa pergunta é para todos, não só para o taborda]

@fantomas
:arrow: Acredito que no sentido de repositorio o sergio esta corrento sim, o que esta fazendo confusão ai é o que o objeto tem em sua real responsabilidade.

@Sergio Taborda
Bom design , principios e regras, nunca trazem problemas. Não os seguir é que sim traz.

:arrow: O design(requisito) esta ligado a ação do ator(comportamento) indiretamente, abstração é sempre alvo de redesenho na Orientação a Objeto(refatoração)

@Todos

Falar pecado imperdoável acho meio forte pra isso, mas ao meu ver parece fazer sentido, pois se não houver quartos não haverá reservas, logo se vc receber reservas (orientação do repositório) como resposta logo haverá quartos associados fornecendo-lhe respostas a respeito desta entidade. Talvez a questão não seja o fazer sentido e sim se isto é realmente necessário. Acredito que os requisitos ajudem nesta hora.

:arrow: Aqui não concordo, novamente existe outros fatores de circunstanciais a se considerar ou onde podem projetar na navegação da ação ao use case, se não houver quartos não haverá reservas ? ou se não houver quartos “temos outro estabelecimento proximo de sua localização nas mesmas condições desejadas”, ou se não houver quartos temos no hotel temos a estadia de estilo diferenciado, master premium, e assim vai

fantomas

Mas aí é que está a graça da coisa Marcio, sempre haverá um quarto para uma reserva; a força disto é tão grande que vc arrumou quartos até em outras instancias rsrsrsrsr. Arrisco a dizer que deve haver uma regra neste mundinho dizendo que vc não pode concretizar uma reserva sem um quarto (levando em conta data/hora).

flws

Link_pg

Entramos agora numa questão filosófica: “Vale a pena ferir as regras há muito estudadas por especialistas em favor de uma possível ‘facilitação’ no desenvolvimento da arquitetura?”

Acho que podemos criar outro tópico pra isso, o que vocÊs acham?

:smiley:

luistiagos

Poxa agora me veio um pensamento… reservas estão sempre associadas a um quarto… vc so pode fazer uma reserva para um quarto disponivel correto? não poderemos fazer reservas para algo que não seja um quarto… em meio disto vemos uma relação: “reserva x quarto” para existir uma reserva deve existir um quarto disponivel… vendo desta forma um esta ligado com outro… pq então não unimos os 2 e matamos a reserva? pq não utilizamos apenas o repositorio quartos com atributo com o periodo de indisponibilidade?

fantomas

Carinha, essa frase entre aspas ficou parecendo um tipo de elixir revigorante para pogueiro.

Se todos estiverem de acordo blz, mas ainda acho que a assunto ainda é pertinente ao tópico criado pelo rodrigoy; acredito que no fundo éra justamente este o questinamento dele; É de um lado ou é do outro? Se é do outro e esse outro é agregador ele pode expor as entidades agregadas diretamente? e por aí vai…bem interessante isto tudo.

flws

FredMP

Não mate a reserva, por favor! :smiley: Se fizer isso poderá ter muitos problemas futuros! (Eu já fiz isso :cry: )

No primeiro sistema no qual trabalhei, que foi para uma pequena pousada, interpretamos que não haveria necessidade de uma entidade Reserva, pois quando uma pessoa reservava um quarto nós criávamos direto uma conta com as diárias e através das diárias tínhamos como saber se a pessoa já havia efetuado o check-in, ou seja, se já havia ocorrido uma ocupação. Nós ignoramos o fato de que na linguagem do especialista no domínio a palavra reserva aparecia constantemente e tinha um significado essencial para o negócio. Isso se mostrou um erro com o passar do tempo.

Link_pg

“fantomas”:

Link_pg wrote:Entramos agora numa questão filosófica: “Vale a pena ferir as regras há muito estudadas por especialistas em favor de uma possível ‘facilitação’ no desenvolvimento da arquitetura?”

Carinha, essa frase entre aspas ficou parecendo um tipo de elixir revigorante para pogueiro.

ahuehueaheua vou imprimir e colar aqui na minha baia, do lado do Dijkstra is watching e do poster do curintia!!

B

Link_pg:
Entramos agora numa questão filosófica: “Vale a pena ferir as regras há muito estudadas por especialistas em favor de uma possível ‘facilitação’ no desenvolvimento da arquitetura?”

Acho que podemos criar outro tópico pra isso, o que vocÊs acham?

:smiley:

O que acontece quando os especialistas pensam uma coisa, mas o caminho ótimo para alcançar o objetivo é outro? Quando seguir a risca o DDD piora o sistema (em performance)?

Isso me lembra um pouco a questão do “Object-relational impedance mismatch”, o mapeamento é menos que perfeito.

Link_pg

É, isso é verdade. Até porque o foco do DDD não é a performance em si, o que acaba depreciando-a nesse caso, o que não é nada bom pois em software a performance é sim muito importante. Acredito que o melhor dos casos é o bom senso… não há como uma teoria (como o DDD) garantir que todos os aspectos não funcionais (performance, escalabilidade, manutenabilidade, *idade) de uma aplicação sejam otimizados, algumas vezes até prejudicando-os, portanto não seria nada de outro mundo darmos uma adaptada na modelagem para contemplar um requisito não funcional (sem exageiros, claro).

luistiagos

É, isso é verdade. Até porque o foco do DDD não é a performance em si, o que acaba depreciando-a nesse caso, o que não é nada bom pois em software a performance é sim muito importante. Acredito que o melhor dos casos é o bom senso… não há como uma teoria (como o DDD) garantir que todos os aspectos não funcionais (performance, escalabilidade, manutenabilidade, *idade) de uma aplicação sejam otimizados, algumas vezes até prejudicando-os, portanto não seria nada de outro mundo darmos uma adaptada na modelagem para contemplar um requisito não funcional (sem exageiros, claro).

É ai que entra o bom senso e a capacidade do desenvolvedor de escolher a melhor ação a ser tomada…
um bom desenvolvedor não é aquele que resolve o problema pois isto todos fazem… mas sim aquele que escolhe a melhor solução para o problema…

rodrigoy

Não me parece lógico em Domain-Driven eu ter um elemento chamado Hotel sendo que o que eu estou modelando é o funcionando do mesmo. Já tinha respondido aqui que ter esse “Hotel” gera outros problemas também lógicos.

Não exagera!!! :wink: No meu exemplo não estou misturando tanto as coisas. Reserva é algo intimamente relacionado com Quartos. Repositórios simplesmente representam uma coleção, geralmente de entidades. Portanto, mensagens que eu atire para este objeto denotam a responsabilidade dele. Não me parece sem lógica perguntar algo para um repositório sobre uma coisa que só ele sabe. Só as reservas sabem os quartos disponíveis.

Exagerou de novo. O EntityManager é o RepositorioGeral, mas usá-lo deste jeito não é Domain-Driven.

Eu já sou da opinião que design é algo criativo. Padrões existem como um guia não como regra. Só conhecimento em padrões não faz ninguém um bom designer.

Na sua solução (listada abaixo), você está construindo entidades transientes somente para que seu repositório TodasReservas retorne Reserva[0…*]. Para mim isso não é lógico, e qualquer programador que pegar esse código no futuro não vai ter a mínima idéia de porque você montou uma lista transiente de reservas se no fim o que você queria eram quartos.

Isso aqui abaixo é do agrado de todos?

fantomas

Acredito que não importa o lado (quarto ou reserva) os questinomentos serão sempre os mesmos, um depende do outro.

A princípio prefiro (ainda) a solução no repositório das reservas, porque estou considerando quarto uma entidade fraca na relação quarto x reserva, inclusive ela (quarto) é agregada da reserva.

E ao observar seu exemplo, me recorre o questionamento: O resultado desta operação é necessário para satisfazer algum requisito?

[]'s

rodrigoy

Neste caso, não é uma regra que um repositório deva sempre retornar a mesma coisa. Repositórios simplesmente representam coleções.

Não me lembro em nenhuma literatura de padrões falando sobre regras. É mais empírico. Quando o GOF foi escrito eles foram claros em dizer que Padrões eram soluções comuns que apareciam no código para problemas específicos. Um padrão é a repetição de um determinado mecanismo dada uma situação. NÃO É UMA REGRA. Se fosse o nome do livro seria Software Design Rules.

Você deve fazer o mesmo caminho para voltar para casa todos os dias. Isso é um padrão. Se você por alguma razão não fizer o mesmo caminho não estará violando uma regra.

sergiotaborda

Repara na contradição : “Não me parece sem lógica perguntar algo para um repositório sobre uma coisa que só ele sabe” X “Só as reservas sabem os quartos disponíveis”.

As reservas não sabem dos quartos disponiveis já que cada reserva só sabe do seu quarto.
Se o Repositório sabe, então não ha problema. O problema é que ele não sabe. Quem sabe qual é o animal da pessoa é a própria pessoa. Quem sabe do quarto da reserva é do próprio quarto.

O repositorio não sabe. Ele vai encontrar. É a sua função no sistema. Como ele encontra é uma questão modelada na implementação. O quê ele encontra é uma questão modelada no contrato .
Então, seja como for que ele procura ele sempre encontra reservas.

Por outro lado repositórios podem comunicar entre si. Portanto, do ponto de vista OO é sempre válido vc executar dentro do repositorio de reservas codigo referente a qualquer entidade. no caso quartos.
O codigo a seguir é válido dentro de TodasReservas

// usando uma mecanismo de busca qq , vc invoca o seguinte
 Collection&lt;Quarto&gt; quartos = store.execute(
Criteria.search(Quarto.class).where("reserva").isNull()
);

 return OnDemandCollection&lt;Reservas&gt; (quartos, Periodo);

A reserva tem 1 quarto, mas o quarto tem 1,0 reservas. O quarto está reservado quando ha no sistema uma reserva que o possui.

O OnDemandCollection é um objeto especial que tem a interface do contrato (digamos que Collection) mas ele só criar os objetos quando o iterador passa por eles. É claro que vc pode fazer isso num for antes e retornar a coleção já preenchida. O ponto é apenas demonstrar como na realidade, na implementação, não estou manipulando reservas. Contudo, do lado de fora vc veria:

Collection&lt;Reservas&gt; reservas = TodasReservas.reservasDisponiveis(Periodo);

for ( Reserva r : reservas){
  System.out.println(r.getQuarto().getNumero());
}

O seu requisito era : "- Ao efetuar a reserva o sistema deverá exibir uma lista de quartos disponíveis para o período da estadia do hóspede. "

Ele está exibindo essa lista. Isso é 100% o que foi requisitado. Não foi requisitado como essa lista seria obtida. Mas existem regras implícitas de como isso vai ser feito. São as regras de OO, as boas práticas, o SoC , a não gambiarra, etc…
Acho que esta solução não viola nem a UL nem OO e portanto tem prioridade sobre as outras.
Acho que já ficou claro que qualquer uma das outras soluções apresentadas como opção não satisfazem todo o mundo.

Cuidado. EntityManager é o DomainStore. O DomainStore não é um reposiotrio porque ele não contém regras de dominio de como procurar entidades. Eles executa os critérios, mas ele não é responsável por os montar, ou saber quais são. Um RepositorioGeral seria uma classe que consome um EntityManager(DomainStore) e tem métodos para encontrar qq tipo de coisa. VC teria getHospedes e getQuartos e getReservas tudo na mesma classe.
Sendo assim, re-analise o que eu falei. O ponto era: Objeto unico com todos os métodos de pesquisa (RepositorioGeral) vs Repositorio por Entidade e qual é a regra/força que o faz preferir o segundo ao primeiro.
Essa mesma força é a que impede que Repositório de X retorne Y.

Claro que faz. Um processo criativo sem regras não serve para nada porque ninguem o vai entender. Isso é arte abstrata onde não ha bom nem ruim. Fazer software ainda não é uma arte abstrata. É uma arte concreta. As outras pessoas podem qualificá-la simplesmente conhecendo as regras. É por isso que ha bom design e mau design. É por isso que ha padrões e anti-padrões. É por isso que ha refactoring e bad smells. O valor do design (bom/mau) advem das regras e não da opinião ou gosto de ninguem. Assim, bom design é bom para todos e mau é mau para todos. Ainda estamos falando de um oficio baseado em ciência e não apenas em estética ou empirismo.

Fazer o que vc gosta e acha que dá certo é empirismo. Fazer o que as regras dizem é ciencia. A diferença é clara. A primeira vai lhe causar problemas ( como o testemunho do colega que ao não colocar Reservas no sistema se ferrou depois).

Correção. Estou criando objectos transientes. Entidades nunca não são transientes.
Isso é um truque de implementação que posso fazer em OO. Em nada isso define o contrato do objeto repositorio.

Hummm… na realidade ultima, o que eu quero são os identificadores dos quartos, pois sem eles ninguem vai saber de nada. No caso o numero serve como identificador (normalmente até ha uma regra para que o andar esteja contido no numero do quarto e assim ter 2 informações com um unico dado).
Eu quero ver o identificador. Isso não significa que eu procure pelo identificador. Acho que é passivo e aceitável que :

TodosQuartos.disponiveis(): Collection&lt;Integer&gt;

É um mau uso de OO e um modelo muito capenga.
O fato de querer obter e manipular X não significa que tenho que procurar X. Isso é uma falácia.
Eu vou procurar a entidade agregada mais próxima. No caso de Quarto é Reserva. No caso, de item de pedido é Pedido, e assim vai. Eu não procuro item de pedido sem o pedido. Entendo que muitos o façam, mas eu considero isso uma violação do modelo OO para esses objetos. O mesmo que para quarto e reserva.
Enfim, não vejo nenhum mal em utilizar-me da reserva para procurar pelos quartos.

danielbussade

Olá a todos , no livro do Page Jones ‘Fundamentals of object-oriented design in UML’, logo no capitulo 4 onde ele fala de Classes diagrams,ele define e cita um exemplo de associação que o seguinte:

LibraryPatron and LibraryBook geram a associação Borrowing, neste caso a associção é somente ‘conceitual’, pois eu nao preciso definir( no contexto do livro) nenhuma operacao em Borrowing. Mas no caso do exemplo temos:

Hospesdes-Quarto -> Reservas

A relação Hospesdes- Quarto gera uma associação Reservas, que neste caso faz sentido transformar a associção em uma classe concreta, visto que esta associação tem responsabilidades proprias.Uma delas seria de encontrar os quartos disponiveis, visto que a disponibilidade do quarto depende da reserva.

Entao essa operacao deveria estar no Repository Reserva, mas concordando com o taborda, o Repository Reserva deve retornar uma lista de reservas, porque isso?

Pensando um pouco, se voce pede a um repositorio que busque informacoes de reserva, porque ele deveria retornar quartos? nao vejo o sentido disso. Ora se quero informacoes do quarto pergunto ao quarto, se quero informacoes de reservas(entenda que reserva aqui e o que diz se um quarto esta disponivel ou nao), peço ao Repository de reservas, uma vez que com a reservas consigo chegar ate o quarto.

Portanto minha opção seria a segunda, com as ressalvas acima.

joellobo

Será que é isso que o cliente entende por reserva?

Emerson_Macedo

No início da discussão, eu havia pensado em colocar em TodosQuartos. Olhando novamente para o texto do requisito, que imagino que tenha sido uma conversa com o usuário/cliente do sistema, mudei de opinião pela seguinte razão:

O hospede quer ficar no hotel, não necessariamente será num quarto. Pode ser que o hotel tenha quarto, suite, chalé, ou qualquer outro espaço passível de hospedagem. Coloco isso só pra reforçar como a coisa pode ser mais abrangente. Dessa forma, o cliente espera receber opções de reserva que por acaso são quartos.

Portanto, como o fluxo parte sempre de uma possibilidade de reserva (i.e. quarto disponível), não vejo motivo para buscar isso em TodosQuartos, mas sim em TodasReservas.

Sobre o que retornar, acredito também que deva retornar uma lista de reservas possívels (i.e. quartos disponíveis) mas objetos Reserva e não Quarto. Dessa forma, quando o hospede escolher a opção de reserva que lhe satisfaz, a próxima ação poderia ser: reserva.confirmar(), por exemplo. Caso contrário, ficaria incoerente termos quarto.reservarPara(periodo), já que Quarto não conhece Reserva.

Claro que ai entram questões técnicas, que não é o ponto da discussão.

[]s

mario.fts

não consegui ler tudo ainda, li mais ou menos metade da discursão.

Acho que o método fica em Todasreservas mesmo. faz mais sentido.

O nome Todasreservas, Todas Pessoas, e etc são melhores que qualquer nome XxxxxRepositório. até pq repositório em portugues não é exatamente a mesma coisa que repository em ingles. eles usam essa palavra com frequência, nós não.

vou ler o resto e depois posto minhas considerações. mas já favoritei o tópico, esse tipo de discursão vale mais que muito curso por ai.

[]'s

Y

Emerson Macedo:
rodrigoy:

Num determinado ponto do sistema há o seguinte requisito:

  • Ao efetuar a reserva o sistema deverá exibir uma lista de quartos disponíveis para o período da estadia do hóspede.

Pergunta: Quem responde pela lista de quartos disponíveis para o período?


No início da discussão, eu havia pensado em colocar em TodosQuartos. Olhando novamente para o texto do requisito, que imagino que tenha sido uma conversa com o usuário/cliente do sistema, mudei de opinião pela seguinte razão:

O hospede quer ficar no hotel, não necessariamente será num quarto. Pode ser que o hotel tenha quarto, suite, chalé, ou qualquer outro espaço passível de hospedagem. Coloco isso só pra reforçar como a coisa pode ser mais abrangente. Dessa forma, o cliente espera receber opções de reserva que por acaso são quartos.

Portanto, como o fluxo parte sempre de uma possibilidade de reserva (i.e. quarto disponível), não vejo motivo para buscar isso em TodosQuartos, mas sim em TodasReservas.

Sobre o que retornar, acredito também que deva retornar uma lista de reservas possívels (i.e. quartos disponíveis) mas objetos Reserva e não Quarto. Dessa forma, quando o hospede escolher a opção de reserva que lhe satisfaz, a próxima ação poderia ser: reserva.confirmar(), por exemplo. Caso contrário, ficaria incoerente termos quarto.reservarPara(periodo), já que Quarto não conhece Reserva.

Claro que ai entram questões técnicas, que não é o ponto da discussão.

[]s

Isso é muito proximo da proposta do Taborda no seu primeiro post nesse topico. Acho que como forma de implementacao é valida, mas parece fugir um pouco da “ubiquitous language”, nenhum hospede pergunta pelas reservas possiveis, mas pelos quartos disponiveis.

Esse é o unico empecilho que vejo pra essa decisao, não sei se é motivo suficiente pra nao adotar. Mas pra implementacao da busca acho que é por aí mesmo.

Eu tenho um sistema com um problema parecido, com a diferenca que é roupas em vez de quartos. E eu escolhi o caminho errado, fiz com que as roupas soubessem se estao reservadas ou nao. Como é um aplicativo relativamente pequeno isso nao me da muita dor de cabeca, mas volta e meia eu estou alterando a implementacao de Roupa, quando deveria estar alterando apenas as reservas. Ou seja, o metodo deve estar sim no repositorio de reservas e os quartos nao devem saber nada sobre reservas.

Ja tem até um TODO pra alterar la, mas…

rodrigoy

Algumas pessoas não entenderam bem, para falar a verdade um quarto tem várias reservas. Reservas são futuras e passadas.

Tem outras considerações que farei Taborda… só estou sem tempo agora.

fantomas

Mas rodrigoy, se um quarto TEM várias reseservas por que no seu modelo (UML) a associação entre as 2 entidades está com a navegação partindo da Reserva para o Quarto me dizendo que eu APENAS consigo navegar das reservas para os quartos e não dos quartos para as reservas?

Abraços

rodrigoy

Navegabilidade e Multiplicidade são coisas diferentes. Mas isso foi só um comentário sobre o código do Taborda.

Um quarto tem reservas no passado, no presente e no futuro. De qualquer forma, a multiplicidade alí não muda o problema…

Para falar a verdade, achei que isso era meio lógico também. Um quarto pode ter reservas para hoje, para a semana que vêm e para daqui 1,2,3 meses…

fantomas

YvGa:
Isso é muito proximo da proposta do Taborda no seu primeiro post nesse topico. Acho que como forma de implementacao é valida, mas parece fugir um pouco da “ubiquitous language”, nenhum hospede pergunta pelas reservas possiveis, mas pelos quartos disponiveis.

Esse é o unico empecilho que vejo pra essa decisao, não sei se é motivo suficiente pra nao adotar. Mas pra implementacao da busca acho que é por aí mesmo.

Eu tenho um sistema com um problema parecido, com a diferenca que é roupas em vez de quartos. E eu escolhi o caminho errado, fiz com que as roupas soubessem se estao reservadas ou nao. Como é um aplicativo relativamente pequeno isso nao me da muita dor de cabeca, mas volta e meia eu estou alterando a implementacao de Roupa, quando deveria estar alterando apenas as reservas. Ou seja, o metodo deve estar sim no repositorio de reservas e os quartos nao devem saber nada sobre reservas.

Ja tem até um TODO pra alterar la, mas…

Acho que entendi…

A minha impressão é que vc acredita que a coisa deveria ser solucionada pelo repositorio “TodosQuartos” e não pelo “TodasReservas”; só não entendi ainda exatamente as razões disto. Estou errado?

Eu opto pelo repositorio “TodasReservas” pelo fato de entender que:

a) A reserva pode ser para um quarto, chalé, apartamento etc…
b) Por conta das datas o objeto em questão (o reservado) sempre é o mesmo fazendo com que a importancia quantitativa fique bem reduzida.
c) O item reservado apenas assumiria um status de reservado dependendo da data hora mencionada.
d) Pelo fato de podermos reservar vários tipos de ítens a reserva seria a abstação ideal para controlar todo o processo.

Agora veja o relato do YvGa (quote acima), parece que a solução aplicada no repositorio “TodosQuartos” não seria uma boa idéia.

flws

sergiotaborda

rodrigoy:
sergiotaborda:

// usando uma mecanismo de busca qq , vc invoca o seguinte
 Collection&lt;Quarto&gt; quartos = store.execute(
Criteria.search(Quarto.class).where("reserva").isNull()
);

 return OnDemandCollection&lt;Reservas&gt; (quartos, Periodo);

A reserva tem 1 quarto, mas o quarto tem 1,0 reservas. O quarto está reservado quando ha no sistema uma reserva que o possui.

Algumas pessoas não entenderam bem, para falar a verdade um quarto tem várias reservas. Reservas são futuras e passadas.

Tem outras considerações que farei Taborda… só estou sem tempo agora.

Antes de mais , só para dizer que o texto que escrevi é para um periodo.
O quarto está reservado , no periodo, quando ha no sistema uma reserva , no periodo, que o possui.

Achei que era claro. Tudo o que disse se baseia na limitação ao periodo de busca.

Marcio_Duran

É bem assim, o hospede liga para o hotel para fazer reserva, o atendente do hotel verifica se existe vaga para reserva , caso ele não tenha a reserva ele comunica ao hospede e pode informar opções de futuras hospedagem ou marcar a reserva no presente momento.

Quando o cliente chega ao hotel, verifica-se junto ao gerente situação de estadia, nesse momento dados do cliente é confirmando e é certificada a estadia.

Existe agora a situação onde o hospede circula dentro do hotel, e instancias começam a surgir relação hospede com ambientes a serem usados fator de consumo e [b]itens são controlados /b todavia existe a forma a de não haver dependência direta com a ação de navegabilidade, ou melhor o cliente pode circular no hotel entre as dependências e não gerar qualquer ação ao controle de consumo sobre as dependencias do hotel sem ocorrência ou abertura de serviços notificados.

Melhor observar assim, tudo o que o objeto cliente depender dentro do hotel invoca controle e gera tarefa, na certa essa informações são refletidas ao repositório do Domínio.

No que vão gerar itens situação de controle, ocorrencia objetocliente nas dependencia do hotel, exemplo uso da lavanderia controle (gera itens), serviço de quarto(gera itens), etc…, caso não, é simplesmente uma navegabilidade ao sistema e consulta ao repositório.

fantomas

rodrigoy:
Pergunta: Quem responde pela lista de quartos disponíveis para o período?

a. O repositório de Quartos?

b. O repositório de Reservas?

c. Faço uma query na UI usando Scriptlet…

Justifique sua resposta.

Blz Marcio, mas qual é a sua resposta para a pergunta do Rodrigoy?

flws

Marcio_Duran

Isso é logo no começo quanto o cliente aciona reserva pra ter estadia, mas a demanda de reserva é gerada de arcordo com a consulta da reserva.


a. O repositório de Quartos? b. O repositório de Reservas?

Acredito que existe um unico repositório para consultar tanto quartos quanto reserva, porque haveria mais de um repositorio, sendo que o mesmo é uma abstração do domínio, podemos entender o repositorio como uma coleção em memoria onde os dados estão sempre disponiveis.

Não.Naturalmente é uma aplicação standalone, ou talvez dependa da tecnologia ser for um beanshell poderia sim.

D

http://tudogratisnaweb2.blogspot.com/

fantomas

:shock: :shock: :shock: :shock: :shock: :shock: :shock:

schmidt.marcelo

Não sou muito de falar em fóruns e afins, mas esse problema me fez querer dar a minha opinião.

Grande mestre Yosha! Convenhamos que as informações que temos são muito pobres. Eu diria até que foram “presumidas” pelo programador que acha que conhece o domínio. Na verdade, verdade mesmo, sinceramente, que diferença faz se a coleção de quartos disponíveis vai ser informada pelo repositório de quartos ou de reservas? Isso vai ser refinado nas próximas iterações de qualquer forma, pois os requisitos vão mudar, como já foi dito.

Mas participando da brincadeira, acredito que a responsabilidade de entregar os quartos disponíveis é de um objeto de domínio, não de repositórios. No meu entendimento de DDD, depois de ler a referência do assunto, repositórios fazem parte da camada de infraestrutura, pois como você mesmo disse, repositórios são apenas coleções de objetos. Então, como já foi dito aqui, uma terceira classe (classe de domínio) deve informar a lista de quartos disponíveis.


Gostaria de ir um pouco mais a fundo com algumas questões ao pessoal aqui!

  1. Um quarto não sabe quando está disponível, reservado, ocupado? Em outras palavras, um quarto não conhece seu “status”?
    Implicações: Se o quarto conhece seu status para uma determinada data, significa uma agregação entre quarto e reserva, o que pode fazer com que eu mude a minha opinião e diga que o respositório de quartos PODE informar os quartos disponíveis. Se ele não conhece o status, é só um objeto de dados com informações do quarto (número, andar, etc) e o seu repositório também é “burro”;
    e 2) Uma reserva é vinculada a um quarto específico?
    Implicações: Se sim (o que parece ter sido “presumido” até agora), existe uma relação de composição entre reserva e quarto, o que me diria, nesse caso, que o repositório de reservas DEVE CONHECER o repositório de quartos, o que, por sua vez, faz “nascer” um agregate (o que, por SUA vez, não muda minha resposta ao questionamento). Se não, não há relação nenhuma entre quartos e reservas, o que simplifica muito a abordagem. Você vai ter uma lista (quantidade) de reservas que vai descontar da lista (quantidade) de quartos do hotel, o que vai dizer não QUAIS, mas QUANTOS quartos estão disponíveis.

Existem muito mais coisas escondidas aí. Não dá prá definir com exatidão como deve ser implementado um determinado requisito. Isso é quase BDUF, na minha opinião.


Precisamos visitar o hotel prá saber como trabalha. Conversar com o product owner prá saber o que ELE quer. hehehe


Enfim, achei muito boa a discussão, gostaria que continuasse, aprendemos muito com essa troca.

sergiotaborda

schmidt.marcelo:

Mas participando da brincadeira, acredito que a responsabilidade de entregar os quartos disponíveis é de um objeto de domínio, não de repositórios. No meu entendimento de DDD, depois de ler a referência do assunto, repositórios fazem parte da camada de infraestrutura, pois como você mesmo disse, repositórios são apenas coleções de objetos.

alguma coisa foi perdida durante a sua leitura  Repositorios não são coleções de objetos. Eles parecem coleções de objetos.

Depois,não parecem coleções de objetos quaisquer, e sim de Entidades. (Não existe repsoitorio de String)

Por fim, Repositorios sim são objetos do dominio, porque contêm regras de pesquisa.Regras de pesquisa são inevitávelmente atreladas ao dominio. (como o caso em estudo mostra)
M
<blockquote><div class="quote-author">sergiotaborda:</div>

alguma coisa foi perdida durante a sua leitura  Repositorios não são coleções de objetos. Eles parecem coleções de objetos.

Depois,não parecem coleções de objetos quaisquer, e sim de Entidades. (Não existe repsoitorio de String)

Por fim, Repositorios sim são objetos do dominio, porque contêm regras de pesquisa.Regras de pesquisa são inevitávelmente atreladas ao dominio. (como o caso em estudo mostra)</blockquote>

Primeiramente repositórios é uma responsabilidade do domínio, nao necessariamente um objeto. Quanto a regras de pesquisa depende muito de cada caso. Um caso não é suficiente pra provar nada. Principalmente discutindo um pseudo dominio.

sergiotaborda
<blockquote><div class="quote-author">mochuara:</div><blockquote><div class="quote-author">sergiotaborda:</div>

alguma coisa foi perdida durante a sua leitura  Repositorios não são coleções de objetos. Eles parecem coleções de objetos.

Depois,não parecem coleções de objetos quaisquer, e sim de Entidades. (Não existe repsoitorio de String)

Por fim, Repositorios sim são objetos do dominio, porque contêm regras de pesquisa.Regras de pesquisa são inevitávelmente atreladas ao dominio. (como o caso em estudo mostra)</blockquote>

Primeiramente repositórios é uma responsabilidade do domínio, nao necessariamente um objeto. Quanto a regras de pesquisa depende muito de cada caso. Um caso não é suficiente pra provar nada. Principalmente discutindo um pseudo dominio.

O que vc escreveu não faz nenhum sentido para mim.
Exactamente porque as regras de pesquisa dependem de cada caso que é necessário o reposiotorio (esse é o problema que ele tenta resolver) Segundo, se algo é uma responsabilidade , em OO alguma objeto terá essa responsabilidade. Isso é o básico do Principio de Separação de Responsabilidades. Não ha como ter algo no dominio e isso não ser responsabilidade de um objecto. Todo este tópico trata repositorio como algo que um objeto é.
Poderia argumentar que pode ser responsabilidade de um conjunto de objetos. Sim, poderia, mas não no caso especifico do repositorio.

Afirmar que “repositorio” é um conceito/responsabilidade/algo abstrato do dominio que não é um objeto é contra sensu para
uma discussão OO onde exactamente se discute qual dos objetos repositorios tem a responsabilidade de prover os objetos de certa
entidade.

schmidt.marcelo

Grande sergiotaborda. Obrigado pelo puxão de orelha.

Realmente me expressei mal, repositórios são (ou melhor, parecem) coleções de ENTIDADES.

Mas isso não muda muito a minha opinião. Prá ter uma resposta mais segura, vai depender muito das respostas aos questionamentos que lancei.

De um lado, se quartos conhecem seu status, o repositório dos quartos pode retornar os disponíveis. Se não conhece, aí o mais lógico seria ter outra classe OU o repositório de reservas o responsável pela informação. Na real, não faz muita diferença a essa altura do projeto. Como mochuara já falou, não temos informações suficientes prá dar uma resposta “certa”.

M
<blockquote><div class="quote-author">sergiotaborda:</div><blockquote><div class="quote-author">mochuara:</div><blockquote><div class="quote-author">sergiotaborda:</div>

alguma coisa foi perdida durante a sua leitura  Repositorios não são coleções de objetos. Eles parecem coleções de objetos.

Depois,não parecem coleções de objetos quaisquer, e sim de Entidades. (Não existe repsoitorio de String)

Por fim, Repositorios sim são objetos do dominio, porque contêm regras de pesquisa.Regras de pesquisa são inevitávelmente atreladas ao dominio. (como o caso em estudo mostra)</blockquote>

Primeiramente repositórios é uma responsabilidade do domínio, nao necessariamente um objeto. Quanto a regras de pesquisa depende muito de cada caso. Um caso não é suficiente pra provar nada. Principalmente discutindo um pseudo dominio.

O que vc escreveu não faz nenhum sentido para mim.
Exactamente porque as regras de pesquisa dependem de cada caso que é necessário o reposiotorio (esse é o problema que ele tenta resolver) Segundo, se algo é uma responsabilidade , em OO alguma objeto terá essa responsabilidade. Isso é o básico do Principio de Separação de Responsabilidades. Não ha como ter algo no dominio e isso não ser responsabilidade de um objecto. Todo este tópico trata repositorio como algo que um objeto é.
Poderia argumentar que pode ser responsabilidade de um conjunto de objetos. Sim, poderia, mas não no caso especifico do repositorio.

Afirmar que “repositorio” é um conceito/responsabilidade/algo abstrato do dominio que não é um objeto é contra sensu para
uma discussão OO onde exactamente se discute qual dos objetos repositorios tem a responsabilidade de prover os objetos de certa
entidade.

Definir repositórios como uma responsabilidade (ao inves de objeto) de domínio me deixa livre para implementar o repositório fora do domínio, enquanto sua interface continua pertencente ao domínio.

Quanto a critérios de pesquisa, IMO se ela pertence de fato ao domínio (depende de cada caso) talvez devesseser implementada em outro objeto para não violar o principio da responsabilidade única (SRP) do repositório que é fornecer um ponto de acesso ao aggregate. Além do benefício de oferecer uma oportunidade de representar critérios de busca fazendo sentido para o especilista de domínio, repositórios são geralmente um conceito estranho para eles.

B

Desculpe pela minha prática de necromancia neste tópico, mas o Philip Calçado postou sobre o uso que estão fazendo num projeto de integração entre sistemas com a idéia do Yoshima de Repositórios do DDD.

http://fragmental.tw/2010/02/24/everyday-tales-anatomy-of-a-refactoring/ (em inglês)

Só quero ver a continuação dessa refatoração deles.

sergiotaborda

Bruno Laturner:
Desculpe pela minha prática de necromancia neste tópico, mas o Philip Calçado postou sobre o uso que estão fazendo num projeto de integração entre sistemas com a idéia do Yoshima de Repositórios do DDD.

http://fragmental.tw/2010/02/24/everyday-tales-anatomy-of-a-refactoring/ (em inglês)

Só quero ver a continuação dessa refatoração deles.

two wrongs don’t make a right.

O problema não é semantico, como as pessoas parecem acreditar.
E a sugestão seguida foi apenas a nomenclatura e não o modelo.
O modelo do TodosX era de uma registro abstrato, não de uma interface.
Extrair a interface para TodosX mas continuar usando XRepository como implementação não mudou uma virgula no modelo.
É algo apenas estético, porque força uma separação (articial) entre o que é considerado “dominio” e o que é considerado “estrutura”.

O repositorio é parte do dominio e não ha vergonha nenhuma nisso. Chame-se como se chamar , com prefixo ou sem. Ele contém regras do dominio
regras que fazem ganhar e perder dinheiro, não apenas coisas de canalização de API (plumbing).
É isto que as pessoas ainda não entenderam.

Coisas como o modelo do repositorio implementa um interface é coisa de DAO. E é realmente isso que o modelo aponto. Uma interface que é implementa na infra , mas usada como um serviço. Ou seja, amanhã é possivel eu implementar outra forma e substituir , ou até ter um façade que escreve nos dois reposiotrios (velho e novo) ao mesmo tempo. Isto é legal no DAO mas é absurdo no Repositorio. Se o repositorio muda, isso significa que o negocio mudou. As regras mudaram. O dominio foi alterado. Não a infra.

O modelo do repositorio inventado pelo proprio Fowler é muito mais coreente que isso e se as pessoas deixassem de pensar em interfaces seria muito mais simples. Definir repositorio como interfaces é como definir cliente e produto como interfaces. É programaticamente válido, mas um erro de abstração.

Repositorios sempre são acompanhados de estratégias. São dois objetos diferentes não uma interface e uma implementação (isso é um Service).
O repositorio contem e concentra as regras de negocio, especialmente que são relevantes a procuras. não contem codigo de infra.
A estratégia só contém codigo de infra e nada de negocio. Ela intrpereta a intenção do repositorio para a tecnologia real.

Um UserRepository tem (não “é”, composição, não herança) estratégias de pesquisa. Em particular ele contém várias. Uma estratégia por rede social. È como se, num sistema de banco de dados o repositorio comunicasse com vários bancos . ele teria uma estratégia por banco.

sergiotaborda
osmio:
Reserva reserva = new Reserva();
reserva.setDataInicioPeriodo(xxx);
reserva.setDataTerminoPeriodo(yyy);
reserva.setTipoAcomodacao("Quarto de luxo");

List&lt;Quarto&gt; quartosDisponiveis = QuartoRepository.getQuartosDisponiveis(reserva);
for (Quarto q : quartosDisponiveis) {
  // lista os quartos disponíveis da melhor maneira
}

Não é o caso do repositório saber quais quartos devem ser disponibilizados de acordo com a reserva?

Isso é o uso de Template Object para fazer a pesquisa.
Vc poderia escrever o mesmo assim

[quote=osmio][code]

List&lt;Quarto&gt; quartosDisponiveis = QuartoRepository.getQuartosDisponiveis(datainicio, dataFim, tipoAcomodacao);

Ou, o que é equivalente

List&lt;Quarto&gt; quartosDisponiveis = QuartoRepository.getQuartosDisponiveis(periodo, tipoAcomodacao);

Isto desacopla a Reserva. Mas veja que cada Quarto tem N reservas, mas cada reserva apenas um quarto.
Então nesse seu modelo, eu tenho um conjunto de quartos, mas ainda terei que escolher 1 e depois criar a reserva.

Poderiamos pensar que a sua pesquisa é equivalente a
List&lt;Reserva&gt; reservasDisponiveis = ReservaRepository.getReservaDisponiveis(periodo, tipoAcomodacao);

Que o Rodrigo já descartou porque "Reserva disponivel" não é um conceito do dominio. Nessa mesma logica "Quarto disponivel" também não é, e portanto nenhuma das duas pesquisas pode ser feita. :)

sergiotaborda

osmio:
sergiotaborda:

Isto desacopla a Reserva. Mas veja que cada Quarto tem N reservas, mas cada reserva apenas um quarto.
Então nesse seu modelo, eu tenho um conjunto de quartos, mas ainda terei que escolher 1 e depois criar a reserva.

E não é este o requisito?
Olhe o primeiro post:

não atende porque vc não efetuou a reserva.

sergiotaborda

osmio:
sergiotaborda:

não atende porque vc não efetuou a reserva.

Então, nesse caso, não é necessário um quarto para fazer uma reserva?

Mas de qualquer forma, a reserva foi feita. Veja novamente:

não foi feita,exactamente, porque, vc não associou um quarto à reserva
Além disso essa reserva que vc cria é apenas um template ela não existe ainda.

Spool
Reserva reserva = new Reserva();
reserva.setDataInicioPeriodo(xxx);
reserva.setDataTerminoPeriodo(yyy);
reserva.setTipoAcomodacao("Quarto de luxo");

List&lt;Quarto&gt; quartosDisponiveis = QuartoRepository.getQuartosDisponiveis(reserva);
for (Quarto q : quartosDisponiveis) {
  // lista os quartos disponíveis da melhor maneira
}

Não é o caso do repositório saber quais quartos devem ser disponibilizados de acordo com a reserva?

Spool

E não é este o requisito?
Olhe o primeiro post:

Reserva controlar, também esta fora de questão para mim.

Spool

Então, nesse caso, não é necessário um quarto para fazer uma reserva?

Mas de qualquer forma, a reserva foi feita. Veja novamente:

Reserva reserva = new Reserva();  
reserva.setDataInicioPeriodo(xxx);      // Estou efetuando uma reserva com data de inicio
reserva.setDataTerminoPeriodo(yyy);  // e data de término
reserva.setTipoAcomodacao("Quarto de luxo"); 

// persistir a reserva antes de achar um quarto, torna a reserva efetivada? Então, persista a reserva aqui.

List&lt;Quarto&gt; quartosDisponiveis = QuartoRepository.getQuartosDisponiveis(reserva);  
for (Quarto q : quartosDisponiveis) {  
  // lista os quartos disponíveis da melhor maneira  
  if (q.getDescricao().equals("Quarto dos sonhos") {
    reserva.addQuarto(q);
  }
} 

// aqui, é necessário atualizar o modelo da reserva novamente para adicionar o(s) quarto(s).
Spool

Então eu tenho que associar um quarto a reserva, depois listar os quartos disponiveis?
Aparentemente, estamos entendendo de forma diferente o requisito.

O objetivo de listar os quartos é justamente selecionar qual o quarto que será associado a reserva. E não efetuar a reserva com um quarto e depois listar os quartos disponíveis.

Criado 11 de agosto de 2009
Ultima resposta 25 de fev. de 2010
Respostas 128
Participantes 29