Pais e filhos... O que faz mais sentido?

Bem… Essa é rapidinha:

Suponhamos uma classe Pai que contém N Filhos…

Quando vamos adicionar um Filho na classe Pai o que faz mais sentido é chamar o método addFilho() na classe pai. Entretanto essa abordagem não é um overhead? Pois pra chamar esse método eu precisaria carregar o objeto Pai do banco (ou whatever) pra memória apenas pra mandar pro banco (ou whatever).

Não seria mais fácil chamar direto o cara que adiciona o filho e passar o id do pai?

Exemplo:

Ao invés de fazer isso:

	public void execute() throws Exception {
		Filho filho = //cria o filho com tudo o q precisa...
		Pai pai = paiRepository.find(getPaiId());
		pai.addFilho(filho);
	}

Fazer algo como:

	public void execute() throws Exception {
		Filho filho = //cria o filho com tudo o q precisa...
		filhoRepository.add(getPaiId(), filho);
	}

Na primeira abordagem acho que fica muito mais na linguagem do domínio, já na segunda não… Mas na primeira eu carrego informações (todas as informações que o pai possui) que não vou utilizar…

E ai? O que faz mais sentido?

Hasta!

Uma vantagem da primeira abordagem é que você checa se o id do pai é válido implicitamente. Não há o risco de tentar inserir um id de pai inválido e receber uma SQLException por erro de foreign key (ou, pior ainda, ficar com um banco inconsistente, se não houver constraints)

Sim… Faz sentido… Embora meu repositório de filhos possa fazer essa checagem também.

Mas o ponto aqui é se vale a pena carregar informações do pai (nome, endereço, animal preferido…) apenas pra adicionar um filho. Ou então apenas chamar o repositório e adicionar o filho sem a necessidade de carregar dados do pai que não serão utilizados pra nada!!!

Será que vale o custo “apenas para ficar na linguagem do domínio”? (essa foi pra cutucar mesmo… hehehe)

Em geral, eu diria que sim. Lembre-se que há uma boa chance do pai estar em cache. Além disso, hoje em dia você bota um quad core com 16 giga num rack com dinheiro de pinga. Não faz sentido ficar com dó de fazer uma query levezinha como essa e tornar seu código menos robusto.

Se vc usa hibernate, da uma olhada em lazy loading e vc vai ver q nao serao trazidos todos os dados do pai nao.

Se vc usa jdbc, vc pode muito bem implementar uma situação que não traga todos os dados do banco sem problemas.

Prefiro a primeira opção.

Talvez você não tenha notado, mas não é provável acontecer de um usuário passar um id sem olhar o dado do Pai a que ele pertence. Talvez até, o id não seja de conhecimento do usuário, sendo algo que só é de interesse interno da aplicação. Então, a consulta do registro do Pai será feito de qualquer jeito, dispensando uma otimização inútil.

Provavelmente havera mais regras para o addFilho(Filho f) do que simplesmente saber se o pai existe, e essas regras ficariam estranhas se fossem colocadas no repositorio de filhos. Alem de que vc parte de cabeca para um implementacao procedural. Nada contra desde que vc saiba exatamente o que esta fazendo e as consequencias disso.

Sera que esse minimo benficio que vc teria economizando uma chamada ao banco compensa a fuga da implementacao logica da regra.

a primeira abordagem é a que faz mais sentido por todos os motivos. A segunda aboragem é utilizada quando vc tem um sistema orientado a banco e é comum, contudo não podemos dizer que faz sentido misturar objetos com ids.

Por outro lado, em OO a relação de composição é feita com os objetos. Ninguem lhe assegura que existam Ids por detrás dos panos.

Ainda por outro lado, o pai é aquilo que se chama um agregado. Faz sentido falar apenas do pai sem os filhos, mas nunca dos filhos sem o pai , logo o pai tem que estar sempre presente (exemplo: pedido-itens. Pedido pode ser maniplado sem os itens, mas os itens não podem ser manipulados sem o pedido)

A relação de composição é muito forte, tão forte que um Id não é suficiente.

Sugestão: Pense primeiro em implementar da melhor forma e optimize depois. Um código bem organizado e bem codificado tende a ser mais facil de aplicar optimizações. Talvez você perceba que esse trecho de código não precisa de nenhuma optimização, pois está atendendo bem a necessidade.

http://www.acm.org/ubiquity/views/v7i24_fallacy.html