Duplicate Code and Ceremony in Java
Thursday, July 21st, 2011How would you kill this duplication in a strongly typed, static language like Java?
private int calculateAveragePreviousPercentageComplete() { int result = 0; for (StudentActivityByAlbum activity : activities) result += activity.getPreviousPercentageCompleted(); return result / activities.size(); } private int calculateAverageCurrentPercentageComplete() { int result = 0; for (StudentActivityByAlbum activity : activities) result += activity.getPercentageCompleted(); return result / activities.size(); } private int calculateAverageProgressPercentage() { int result = 0; for (StudentActivityByAlbum activity : activities) result += activity.getProgressPercentage(); return result / activities.size(); } |
Here is my horrible solution:
private int calculateAveragePreviousPercentageComplete() { return new Average(activities) { public int value(StudentActivityByAlbum activity) { return activity.getPreviousPercentageCompleted(); } }.result; } private int calculateAverageCurrentPercentageComplete() { return new Average(activities) { public int value(StudentActivityByAlbum activity) { return activity.getPercentageCompleted(); } }.result; } private int calculateAverageProgressPercentage() { return new Average(activities) { public int value(StudentActivityByAlbum activity) { return activity.getProgressPercentage(); } }.result; } private static abstract class Average { public int result; public Average(List<StudentActivityByAlbum> activities) { int total = 0; for (StudentActivityByAlbum activity : activities) total += value(activity); result = total / activities.size(); } protected abstract int value(StudentActivityByAlbum activity); } |
if this were Ruby
@activities.inject(0.0){ |total, activity| total + activity.previous_percentage_completed? } / @activities.size @activities.inject(0.0){ |total, activity| total + activity.percentage_completed? } / @activities.size @activities.inject(0.0){ |total, activity| total + activity.progress_percentage? } / @activities.size |
or even something more kewler
average_of :previous_percentage_completed? average_of :percentage_completed? average_of :progress_percentage? def average_of(message) @activities.inject(0.0){ |total, activity| total + activity.send message } / @activities.size end |