Probleminha OOAD (DDD Repositórios)

[quote=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?

[/quote]

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

[quote=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.[/quote]

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…

[quote=rodrigoy]Err… vocês não acham isso um pouco estranho não?
(…)[/quote]
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.

[quote=luistiagos][quote=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.[/quote]

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…[/quote]

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:

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?

[quote=luistiagos][quote=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.[/quote]

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…[/quote]

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/0201835959

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.

[quote=viniciusv][quote=luistiagos][quote=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.[/quote]

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…[/quote]

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/0201835959[/quote]

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…

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 

[quote=rodrigoy][quote=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.
[/quote]

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?[/quote]

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.

[quote=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.

[/quote]

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.”

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

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.

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.

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.[/quote]

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.

Não uso essa nomenclatura ‘Repositorio’.

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

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…

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

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.[/quote]

[quote=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.
[/quote]
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.