ORM classes with collections; trying to focus on parent class rather than children
Let's say I have a Farmer class and a Farmer has a collection of pigs.
If I'm using an ORM like Hibernate I can cascade updates to the Farmer Pig collection so that I can do something like this from my controller:
Pig pig = new Pig("Charlie");
farmer.addPig(pig);
farmerService.save(farmer);
My farm service knows nothing about the Pig. Depending on the requirements of the application, I might not even need Pig DAO. I'm only interested in farmers.
Cool, but what happens when the pigs turn into bacon?
farmer.removePig(pig);
farmerService.save(farmer);
The problem is that in a stateless web application I need to create a pig somehow, which I will go to the RemovePig Farmer method.
I could do:
// manual search Farmer collection - requires loading all pigs.
// Yes, I could just pass id to removePig, but it confuses the example
pig = farmer.getPigById(id);
farmer.removePig(pig);
farmerService.save(farmer);
or
// loads up a pig, and hopefully it belongs to the farmer
pig = farmerService.getPigById(id);
farmer.removePig(pig);
farmerService.save(farmer);
The latter seems to be better, but if I'm going to add a getPigById () method to my farming service, I might also just have a savePig () method. This would change the focus from Farmer to Pig.
pig = farmerService.getPigById(id); farmerService.removePig(pig);
Yeah, and look at even less code. However, this violates the logical view of wanting to work with Farmers and their pig collections rather than individual pigs. I no longer see the explicit removal of the pig from the farmer, all this is implicit and vice versa.
I seem to run into this problem a lot. The class that needs to be in focus is the Farmer. Pigs are secondary. But it is difficult to work with collections of pigs without sliding down the slope, to work with individual pigs, whose changes are simply reflected when the farmers reboot with persistence.
What advice can you offer me in this matter?
a source to share
In the script, I'm leaning towards your second approach. The fact that you are in a non-state should not be reflected in your object model, just how you are restoring your state in a particular HTTP request. This is done here:
pig = farmerService.getPigById(id);
This code must be present in the controller (in an MVC or MVP pattern). Then the rest of the code continues as usual:
farmer.removePig(pig);
farmerService.save(farmer);
The particular controller that handles the current request should be responsible for maintaining that state of the current pig. It should be responsible for sending the pig id to the browser and responsible for translating that pig id into a pig object. The way he does it is his own, but using the call for farm service makes the most sense. From here, you can further automate this translation by having an id-to-object generic call and vice versa.
Your opinion that this domain model should be farmer-centric is correct and consistent with the domain-centric design. The Farmer's class in this case is a collection of pigs and therefore defines a boundary around a collection of pigs. All pigs' access must go through the farmer. This way you have a clear agreement on how pigs are created, destroyed, and modified. So your last approach doesn't sound like it did before.
a source to share