I have three methods that I need to call multiple times only varying the date parameter of each. The natural solution to avoid code duplication is to put the three methods in a loop and iterate over the varying dates.
The problem with that approach is that I need to keep track of the results of each method call along with the dates that produced the result so that I can build the DTOs. So, I'm not sure how to employ a loop without resulting in redundant & verbose code or if a loop is even the right solution to avoid code duplication.
Here's my code:
LocalDate sevenDaysAgo = endDate.minusDays(7);
Map<String, BigDecimal> sevenDayValues = client.getValues(productIds, sevenDaysAgo, endDate);
Map<String, BigDecimal> sevenDayGrossValues = client.getBaselineValues(grossProductIds, sevenDaysAgo, endDate, "gross");
Map<String, BigDecimal> sevenDayNetValues = client.getBaselineValues(netProductIds, sevenDaysAgo, endDate, "net");
//calling same methods again varying start date
LocalDate thirtyDaysAgo = endDate.minusDays(30);
Map<String, BigDecimal> thirtyDayValues = client.getValues(productIds, thirtyDaysAgo, endDate);
Map<String, BigDecimal> thirtyDayGrossValues = client.getBaselineValues(grossProductIds, thirtyDaysAgo, endDate, "gross");
Map<String, BigDecimal> thirtyDayNetValues = client.getBaselineValues(netProductIds, thirtyDaysAgo, endDate, "net");
//and again
LocalDate sixtyDaysAgo = endDate.minusDays(60);
Map<String, BigDecimal> sixtyDayValues = client.getValues(productIds, sixtyDaysAgo, endDate);
Map<String, BigDecimal> sixtyDayGrossValues = client.getBaselineValues(grossProductIds, sixtyDaysAgo, endDate, "gross");
Map<String, BigDecimal> sixtyDayNetValues = client.getBaselineValues(netProductIds, sixtyDaysAgo, endDate, "net");
//and yet again
LocalDate ninetyDaysAgo = endDate.minusDays(90);
Map<String, BigDecimal> ninetyDayValues = client.getValues(productIds, ninetyDaysAgo, endDate);
Map<String, BigDecimal> ninetyDayGrossValues = client.getBaselineValues(grossProductIds, ninetyDaysAgo, endDate, "gross");
Map<String, BigDecimal> ninetyDayNetValues = client.getBaselineValues(netProductIds, ninetyDaysAgo, endDate, "net");
List<ProductValuesDto> dtos = new ArrayList<>();
//now build the dtos. Need to know the date range
//that the values correspond to (see buildDtos method)
buildDtos(dtos,
productId,
sevenDayValues,
thirtyDayValues,
ninetyDayValues,
threeHundredSixtyFiveDayValues);
buildDtos(dtos,
grossProductIds,
sevenDayGrossValues,
thirtyDayGrossValues,
ninetyDayGrossValues,
threeHundredSixtyFiveDayGrossValues);
buildDtos(dtos,
netProductIds,
sevenDayNetValues,
thirtyDayNetValues,
ninetyDayNetValues,
threeHundredSixtyFiveDayNetValues);
return dtos;
}
public void buildDtos(List<ProductValuesDto> dtos,
List<String> productIds,
Map<String, BigDecimal> sevenDayValues,
Map<String, BigDecimal> thirtyDayValues,
Map<String, BigDecimal> ninetyDayValues,
Map<String, BigDecimal> threeHundredSixtyFiveDayValues) {
for(String productId : productIds) {
ProductValuesDto dto = ProductValuesDto
.builder(productId)
.sevenDayValue(sevenDayValues.get(productId))
.thirtyDayValue(thirtyDayValues.get(productId))
.ninetyDayValue(ninetyDayValues.get(productId))
.threeHundredSixtyFiveDayValue(threeHundredSixtyFiveDayValues.get(productId))
.build();
dtos.add(dto);
}
}
The client methods all return Map<String, BigDecimal> where the key is the productId and the value is assessed value of the product over the start to end date.
A few notes:
clientmethods are defined in a third party library that I cannot change- The DTO will be handed back to a client of my application. It needs to have fields as noted in the builder.
- The offset days (7, 30, 60, 90) are static requirements. But it's possible (although unlikely) that a 120 day offset may be added in the future.
- I'm using Java 8 and open to using functional programming techniques.