As a basic strategy, I would almost always avoid storing the same the same piece of information in two different places/classes of a data model, that leads too easily to unmaintainable code. If you start having attributes like numberOfMonths
in two classes (like it was suggested in another answer), they can deviate from each other, you might have to write code to prevent this, have to care which is the "leading" version of that attribute, might have to duplicate documentation, and so on.
One solution you suggested was "A parent field so we can traverse back up the object to get the data". That is fine when in your business domain each PaidByItem
object is related somehow to one Xyz
and one Aaa
object. Then it makes sense to express that relationship also in code by a reference:
public class PaidByItem {
int feeAmount = 100;
Xyz xyz; // lets assume this is Java or C#, so a reference, no copy!
AAA aaa;
// ...
public double totalAmount (){
return feeAmount * xyz.numberOfMonths / aaa.daysPerYear;
}
}
Non-sensical names like Xyz
or Aaa
, however, don't tell us much about the real domain. There can be lots of reasons why you do not want to introduce a dependency from Xyz
or Aaa
into PaidByItem
. For example, they could lead to a cyclic dependency you need to avoid, or these kind of relationships/references simply don't make any sense from the domain point of view. For these cases, it is often be better to use your other suggestion "A separate calculation class to get the data, perform the calc and return a value". Or, you change the design to
public double totalAmount (int numberOfMonths, int daysPerYear){
return feeAmount * numberOfMonths / daysPerYear;
}
which means the caller of this method has the responsibility to make sure the totalAmount
functions is called with the right parameters from the right objects. The last option makes most sense when those parameters like numberOfMonths
are not required to come from a specific, referenced object.
TLDR: avoid redundant storage, pick the solution which represents your business domain most appropriately.