Nenhum problema - vc pode separar os DAOs, inclusive: um pra fazer queries e outro pra fazer modificacoes, e deixar os DAOs que modificam coisas escondidinhos dentro das entidades do modelo
Nao era mais facil fazer a validacao ser um punhado de Listeners que roda antes dos DAOs? Assim, o seu domain model continua coeso e representando as entidades direitinho, e o Service Layer cuida de prover as queries
Qual o uso de AOP que tornaria a coisa melhor aqui? Colocar o mecanismo de observer/observable encapsulado em um aspecto separado?
Apoiadissimo
Nao diria “mais focado em TestCase”, pq no fim das contas o JForum eh um forum, nao um monte de barrinhas verdes e felizes. Mas… o monte de barrinhas verdes e felizes ajudaria o JForum imensamente a ser um forum cada vez melhor
A idéia de usar listeners é legal, mas manter isso estáticamente é uma péssima idéia. Não sei como está hoje, mas os DAOs são 100% stateless? Por que se não forem você vai ter problemas.
Nesse primeiro momento não precisa, mas seria bom mover a configuração dos listeners para fora do código java, facilitando a configuração.
Outra coisa, validação usando listeners não me parece uma boa idéia, mesmo usando o conceito legal de VetoListeners do modelo de eventos dos JavaBens. Não seria melhor prover esse tipo de funcionalidade, como validação, atraves de decoradores?
Ou seja, antes do teu serviço executar, uma série de decoradores vão realizar tarefas como validar permissões, existencia e tudo mais.
E qual a vantagem de usar decorator em vez de listeners? Primeiro que fica menos intrusivo para o serviço o fato dos decorators existirem, segundo que somente a Factory dos serviços precisa se preocupar em decorá-los. A desvantagem é que precisa tormar cuidado quando passar this como parâmetro.
Não sei se esse código existe ou não, mas o correto não seria usar updates e deletes verificando o número de registros alterados. Tem a interação com caching, mas fica parecido.
Atualizar o maxPostId
update topics set max_post_id = ? where topic_id = ? and max_post_id < ?
ou se o banco tiver uma função de seleção de maior valor (mysql):
update topics set max_post_id = GREATEST(max_post_id, ?) where topic_id = ?
Para o caso de apagar topicos sem posts:
delete from topics where topic_id = ? and not exists (select * from posts where posts.topic_id = topics.topic_id)
+1 pra ideia dos decorators - fica mais limpinho, mesmo… ai voce pode espetar outros tipos de tratamento dos dados nos listeners (ou fazer coisas emocionantes tipo logging), e tambem te ajudam a tirar a logica dos DAOs.
Ao inves de fazer um metodo no DAO que apaga um post, decrementa o numero de posts do usuario, decrementa o numero de posts da thread, decrementa o numero de posts do topico e frita uns bifes, vc faz varios listenerzinhos que escutam a mensagem postDeleted
[quote=cv]+1 pra ideia dos decorators - fica mais limpinho, mesmo… ai voce pode espetar outros tipos de tratamento dos dados nos listeners (ou fazer coisas emocionantes tipo logging), e tambem te ajudam a tirar a logica dos DAOs.
Ao inves de fazer um metodo no DAO que apaga um post, decrementa o numero de posts do usuario, decrementa o numero de posts da thread, decrementa o numero de posts do topico e frita uns bifes, vc faz varios listenerzinhos que escutam a mensagem postDeleted ;)[/quote]
Só toma cuidado para não trocar spaghetti por raviolli.
Bom, o update pro max post id sempre vai ter que existir, independente da maneira como eh feito. Em bancos que suportam subqueries, ate da para automatizar com um
update topics set max_post_id = (select max(post_id) from .... ) where topic_id = ?
mas ainda assim preciso ter um metodo que pega o max post manualmente, para os casos de bancos sem subqueries (aka mysql < 4.1).
Em relacao a remover o registro da topics caso nao haja posts, a diferenca do teu exemplo eh que voce manda dar o delete de cara, sem verificar antes de eh necessario ou nao… nao chega a ser uma big coisa.
[quote=cv]+
Ao inves de fazer um metodo no DAO que apaga um post, decrementa o numero de posts do usuario, decrementa o numero de posts da thread, decrementa o numero de posts do topico e frita uns bifes, vc faz varios listenerzinhos que escutam a mensagem postDeleted ;)[/quote]’
Bom, mas no fundo ainda existiria os respectivos metodos no dao, nao?! (mesmo que eles fossem chamados por algum observer)
Bom, de fato vai ter que ficar para o futuro. Eh inviavel levar sozinho dois refactorings pesados assim, que demandam um grande esforco para codificar e testar.
HHm… teste da interface web? (ou proximo disso?)… o Selenium eh mto bom, e com certeza vou usa-lo.
[quote=Rafael Steil]
Bom, mas no fundo ainda existiria os respectivos metodos no dao, nao?! (mesmo que eles fossem chamados por algum observer)
Rafael[/quote]
Eu vejo a camada de DAO fazendo somente o plumbing entre banco e aplicação. Os métodos devem ser, em geral, atômicos e não produzir qualquer efeito colateral além do óbvio.
Então sim, os daos continuariam tendo os métodos para falar com a base de dados e fazem nada além disso.
Quanto ao comentario sobre o delete. Eu ignorei detalhes sobre caching para simplificar a coisa, supondo que você tem somente o topic_id, não tem como evitar ir ao banco, certo? Essa era minha sugestão, se precisar fazer um select count() melhor mandar o delete ou update direto. Com mysql < 4.1 acho que rola fazer uma gambiarra com multi-table delete/update para burlar a falta de subqueries.
Em relacao ao caching, o que eu comecei a fazer tambem eh criar uma implementacao cached do DAO, que fica na frente da implementacao concreta. Atualmente, o codigo esta assim:
Estava lendo este tópico antigo e gostaria saber se atualmente o código do Jforum que está no Github pode ser considerado um bom exemplo de arquitetura ou ainda há muito código da versão antiga que precisa de melhorias e refatoração ?
Estou procurando alguns projetos maiores de código aberto usando padrão MVC para verificar como foram feitas as implementações do controller, serviços , autorização, etc. Exemplos mais didáticos as vezes não mostra muito claramente como resolver alguns problemas mais práticos, por exemplo, uma view que tem um grande número de dependências, no JForum, por exemplo, há construtores com uns 10 parâmetros.
a maior parte do código do JForum 3 é novo, e que foi reutilizado foi aprimorado na medida do possível até o momento. Tem algumas coisas lá (como o esquema de serviços) que estou reavaliando a implementação, pois o que tinha em mente no início era ter toda uma API desconectada do ambiente Web, mas hoje em dia vi que era algo meio idiota querer chegar em tal ponto. Isso não significa que está ruim, é mais uma questão conceitual.
A respeito dos construtores dos Controllers, ao meu ver não tem muito como fazer diferente… talvez, em alguns casos bem especificos, daria para diminuir esse número se algumas das dependências fossem diluídas por outros componentes, mas isso precisa ter uma finalidade bem específica. Querer diminuir só porque parece ter “bastante” é um motivo muito fraco, que pode acabar causando confusão em outras pontas se você não prestar atenção na maneira de refatorar.