Monday, February 13, 2006

Simple Refactoring

Refactoring doesn't have to be, and generally should not be, a complex and time-consuming activity. By using some simple refactoring practices it is possible to greatly simplify code and save time for other people reading the code in question. Here is an example:

Here is the refactored code for calculating the number of hours remaining in the month:


public static int calculateNumberOfRemainingHoursInMonthFromDate(Date fromDate) {
return hoursBetween(startOfNextMonth(fromDate), startOfDay(fromDate));
}

And here is the original code:

public static int calculateNumberOfRemainingHoursInMonthFromDate(Date fromDate) {
Calendar startCal = Calendar.getInstance();
startCal.setTime(fromDate);
int startDay = startCal.get(Calendar.DAY_OF_MONTH);
int maxHoursInMonth = 0;
Calendar calendar = Calendar.getInstance();
calendar.setTime(fromDate);

calendar.set(Calendar.SECOND, calendar.getMinimum(Calendar.SECOND));
calendar.set(Calendar.MINUTE, calendar.getMinimum(Calendar.MINUTE));
calendar.set(Calendar.HOUR_OF_DAY,
calendar.getMinimum(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.DAY_OF_MONTH, startDay);
Date startDate = calendar.getTime();

calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
Date endDate = calendar.getTime();

long milliseconds = endDate.getTime() - startDate.getTime();
maxHoursInMonth = (int) (milliseconds / 1000 / 60 / 60);

maxHoursInMonth = correctHoursForAprilTo720(maxHoursInMonth);

return maxHoursInMonth;
}

Below are the utility functions used in the refactored code:

private static int hoursBetween(Date endDate, Date startDate)
long millisecondsRemainingInMonth = endDate.getTime() -
startDate.getTime();
int hoursRemainingInMonth =
(int) (millisecondsRemainingInMonth / 1000 / 60 / 60);
hoursRemainingInMonth = correctHoursForAprilTo720(hoursRemainingInMonth);
return hoursRemainingInMonth;
}

private static Date startOfNextMonth(Date date) {
Date initializedDate = startOfDay(date);
Calendar toDateCalendar = Calendar.getInstance();
toDateCalendar.setTime(initializedDate);
toDateCalendar.add(Calendar.MONTH, 1);
toDateCalendar.set(Calendar.DAY_OF_MONTH, 1);
return toDateCalendar.getTime();
}

private static Date startOfDay(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));
cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
Date startDate = cal.getTime();
return startDate;
}

No comments: