Dúvida/Ajuda arquitetura projeto

Olá a todos!

Estou fazendo um projeto pessoal e gostaria da opinião de vocês a respeito da arquitetura utilizada. O sistema é sobre controle financeiro pessoal e consiste basicamente de CRUDs para entidades auxiliares(Conta, Tipo de Conta e Forma de Pagamento) e para a entidade principal(Lançamento). Essa última, além do CRUD, também tem buscas avançadas e relatórios. As tecnologias que estou usando: Maven, Spring, Jboss Seam, Hibernate
Segue abaixo o exemplo para o CRUD de Contas.

HibernateRepository.java(package common.infrasctructure)

public abstract class HibernateRepository<T, ID extends Serializable> extends HibernateDaoSupport {

   //metodos padroes com implementacao usando hibernate..add, find's, update, remove
 
}

ContaRepository.java(package conta.domain)

public interface ContaRepository {
   //metodos padroes..add, find's, update, remove
   ...
   Conta findByDescricao(String descricao);
}

ContaRepositoryHibernate.java(package conta.infrastructure)

public class ContaRepositoryHibernate extends HibernateRepository<Conta, Integer>
        implements ContaRepository {

   //implementacao apenas dos metodos que nao estao em HibernateRepository

    public Conta findByDescricao(String descricao) {
        QuerySpecification query = new QuerySpecification()
            .addRestriction(Restriction.equals("descricao", descricao));
        List<Conta> res = findByListOfCriterion(Converter.convertToListOfHibernateCriterion(query));
        if(res.size() == 0) {
            return null;
        }
        return res.get(0);
   
    }

}

*QuerySpecification. Faz parte de uma biblioteca que fiz para montar consultas em alto-nível. A classe Converter faz a conversão para um List de Criterion ou para SQL puro. O método findByListOfCriterion vem de HibernateRepository.

E na minha Action eu chamo por exemplo

..
    @End
    public void add() {
        contaRepository.add(conta);
        facesMessages.add("#{messages['label.conta.inserida']}");
        conta = new Conta();
    }
..

No Spring eu fiz os métodos do repository que não começam com “find” como Transacional.

Dúvida 1: Se eu precisasse por exemplo, antes de inserir a Conta, verificar se já existe uma conta com aquela descrição e, caso afirmativo, lançar uma exception. Eu poderia fazer esse check no add de ContaRepositoryHibernate ou o correto seria criar um service que faz a validação/inserção usando o repository e na minha action eu chamo o service ao invés de diretamente o Repository?Ou outro jeito?E no caso de usar o Service, mudaria no Spring para a Transação ser em cima do Service ao invés do Repository.

Falando agora sobre a entidade Lancamento, na parte de relatórios. Um relatório exemplo seria um que listasse todos os lançamentos de um período e no final mostrasse o total de entrada, saída e o saldo.
Dúvida 2: Eu preciso criar um Bean para representar a esturura desses dados, certo?Com um List de lancamentos, totalEntrada, totalSaida e Saldo. Qual seria a nomenclatura correta para esse tipo de Classe?RelatorioSimplesDeLancamentos.java seria o suficiente ou é interessante usar algum sufixo(DTO, VO…?). Em qual package o deixaria, junto com a entidade Lancamento em lancamento.domain?
Dúvida 3: Para montar esse relatório eu vou precisar buscar um List de lancamentos no BD e ir manipulando esses dados para preencher o RelatorioSimplesDeLancamentos.java. Isso eu posso fazer direto no Repository ou é interessante criar um Service que pede ao Repository os dados e então os manipula?

Qualquer sujestão será bem-vinda.

Desde já muito obrigado!
Luciano

E ai LucianoM86 ,

Pô, ninguem deu bola pro teu post!?!?

O problema que estas suas dúvidas pode trazer um monte de discussão, vai ver foi isso.

Vamos lá, vou dar minha opinião quem sabe alguem mais se anima.

Resposta 1:
Se entendi direito, na minha opinião você poderia colocar a verificação em um serviço; o serviço por sua vêz utilizaria o repositório para realizar a consulta. Assim vc poderia realizar uma verificação sem fazer um inclusão. Fazer a verificação ao incluir também funciona mas fica parecido com aquelas ações com mais de um objetivo (verificar e incluir) ao mesmo tempo e isso não é bom. E por fim acredito que se vc colocar as transações nos serviços talvez o sistema fique um pouco mais flexivel muito embora tenha visto sistemas que a transação foi colocada nos repositórios.

Resposta 2:
De novo não sei se entendi direito, mas se vc tem uma lista de objetos que lhe diz se os valore serão adicionados e subtraidos você não precisa de um objeto para lidar com totais porque eles são resultado de somatória. Bata percorrer a lista, somar, subtrair e totalizar e pronto. Quanto ao sufixo durante este tempo eu (e mais uma montão de gente) tenho colocado sufixos mas estou começando a evitar este tipo de coisa. Se vc optar por VO ou DTO deixe no dominio. Por favor faça uma revisão sobre as diferenças entre DTO e VO nas literaturas do Sr. Martin e Eric.

Resposta 3:
Novo indico colocar nos serviços.

P.S Tente fazer uma revisão (eu vivo fazendo isso rsrsr) sobre serviços e repositórios (aqui no forum tem bastante assunto sobre isto), percebo que suas dúvidas tem origem na incerteza do que seja realmente estas coisas; não esquenta a cabeça, muitos tem duvidas sobre isto.

flws

Oi fantomas!

Obrigado pelas respostas, é o pessoal ta meio queto…haha, mas ta valendo.

Sobre o item1: O que você quis dizer é que eu criaria um service e la teria algo como…

..
public void add(Conta conta) throws ExcpetionQualquer {
   if(repository.jaPossuiAConta(conta)) {
      throw new ExcpetionQualquer("ja existe uma conta com essa descrição...");
   }
   repository.add(conta);
}
..

Sobre o item 2: Na verdade como vou mostrar o relatório em tela, eu disse sobre criar uma Classe específica que representasse os dados do relatório, assim eu faria o processamento no Service e na tela eu faria somente a exibição.

Vou revisar os padrões sim!O do Fowler tenho em casa, do Evans deve estar em algum navio ou algo do tipo vindo da Amazon! :smiley:

Obrigado!
Abraço!

LucianoM86,

Na minha opinião poderia ser assim mesmo, mas seria bom refletir sobre o seguinte detalhe sobre este problema:

  • Se a parte usuária dos seus serviços precisar saber apenas se a conta existe ou não, vc tem um serviço para isto? Se tiver blz. Normalmente um serviço de consulta já resolve; ou seja, consultou, retornou resultado conclui-se que a conta existe e pronto.

flws

fantomas,

A verificação se uma conta existe ou não eu posso fazer com um método no repository(como mostrado). Mas a operação como um todo não precisaria estar no service?(como o exemplo)

Flw!

Na minha opinião sim, o seu exemplo está ok sem problemas.

O que eu quiz dizer foi o seguinte: na hipotese de alguem precisar saber apenas (não incluir a conta) se uma conta existe, deveria haver um outro serviço para isto também. Resumindo… se quiser acessar algum repositorio tem que ser através de um serviço. Estou dizendo isto porque alguns desenvolvedores preferem acessar o repositório na action diretamente, sem passar por um serviço; e eu, por enquanto sou contrario a esta estratégia.

[]'s

hum…entendi seu ponto de vista!
No caso dos meus CRUDs hoje, onde não existe esse tipo de verificação nem nada, eu estou acessando o repositório diretamente da Action…já que se tivesse o Service, ele apenas iria delegar para o repositório…isso que você é contrário?Mesmo não tendo nenhuma lógica no service(caso ele exista)?

Abraços!

[quote=LucianoM86]hum…entendi seu ponto de vista!
No caso dos meus CRUDs hoje, onde não existe esse tipo de verificação nem nada, eu estou acessando o repositório diretamente da Action…já que se tivesse o Service, ele apenas iria delegar para o repositório…isso que você é contrário?Mesmo não tendo nenhuma lógica no service(caso ele exista)?
[/quote]

Exatamente!

Mas não critico quem faz isto pelo seguinte:

  1. Parece redundante pela ausencia de lógica no serviço, como vc bem falou.
  2. Dá uma terrivel impressão que a gente está enchendo o sistema com código “inútil”.
  3. Admito que também não parece prático.

Na minha opinião o projetista tem que estár conciente do que está fazendo. Se o contexto/requisitos do sistema forem um pouco radicais onde haja a necessidade de se fazer acessos por diferentes clients como swing, front controllers, web services e sabe-se lá Deus o que mais, seria uma estratéria mais interessante se apenas fossem utilizados serviços. Além de fazer a estratégia de trabalho ficar mais clara dentro do projeto; de outra maneira, fica aquela forma não homogenia em que hora o acesso é feito diretamente pelo repositório outra hora pelo service. Se colocar regras do tipo “operações simples acessa diretamento pelo repositório” e “operações complexas acessa pelo serviço” acaba criando polemica; uma operação pode simples para vc mas pode ser complexa para mim, e aí tá feita a confusão, o sistema fica uma bagunça só.

Mas se o sistema for “simples” sem acessos “malucos” e estavel acredito que não haja problema, aliás acho que tem uma discussão enorme aqui no forum sobre isso, só não lembro qual é o topico.

Resumindo… na minha opinião quem lida com arquitetura tem que estar atento e ser flexível, senão acaba “construindo um caminhão para carregar um grão de feijão” sem falar no aumento desnecessário da complexidade.

[]'s

fantomas,

obrigado mais uma vez pela sua opnião. Eu já li muitos desses posts “intermináveis” mas muito produtivos…

Mas é isso ai, nada tem uma “receita”, o jeito é fazer conforme a necessidades mesmo!

Abraços,
Luciano