Для меня решающим обстоятельством является то, что для обеспечения логической согласованности [G11] таблицу следует объявить приватной и предоставить доступ к ней через функцию вида julianDateOfLastDayOfMonth. Но похоже, такая функция никому не нужна. Более того, если этого потребует новая реализация DayDate, таблицу можно будет легко вернуть на место. Поэтому я ее переместил.
Далее следуют три группы констант, которые можно преобразовать в перечисления (строки 162–205).
Первая из трех групп предназначена для выбора недели в месяце. Я преобразовал ее в перечисление с именем WeekInMonth.
public enum WeekInMonth {
FIRST(1), SECOND(2), THIRD(3), FOURTH(4), LAST(0);
public final int index;
WeekInMonth(int index) {
this.index = index;
}
}
Со второй группой констант (строки 177–187) дело обстоит сложнее. Константы INCLUDE_NONE, INCLUDE_FIRST, INCLUDE_SECOND и INCLUDE_BOTH определяют, должны ли включаться в диапазон конечные даты. В математике в подобных случаях используются термины «открытый интервал», «полуоткрытый интервал» и «замкнутый интервал». Мне кажется, что математические названия выглядят более понятно [N3], поэтому я преобразовал группу в перечисление DateInterval с элементами CLOSED, CLOSED_LEFT, CLOSED_RIGHT и OPEN.
Третья группа констант (строки 18–205) определяет, должно ли в результате поиска конкретного дня недели возвращаться последнее, предыдущее или ближайшее вхождение. Выбрать подходящее имя для такого перечисления непросто. В итоге я остановился на имени WeekdayRange с элементами LAST, NEXT и NEAREST.
Возможно, вы не согласитесь с выбранными мной именами. Мне они кажутся логичными, но у вас может быть свое мнение. Однако сейчас константы приведены к форме, которая позволяет легко изменить их в случае необходимости [J3]. Они передаются не в виде целых чисел, а в виде символических имен. Я могу воспользоваться функцией переименования своей рабочей среды для изменения имен или типов, не беспокоясь о том, что я пропустил где-то в коде -1 или 2 или объявление аргумента int осталось плохо описанным.
Поле description в строке 208 нигде не используется. Я удалил его вместе с методами доступа [G9].
Также был удален вырожденный конструктор по умолчанию в строке 213 [G12]. Компилятор сгенерирует его за нас.
Метод isValidWeekdayCode (строки 216–238) пропускаем — мы удалили его при создании перечисления Day.
Мы подходим к методу stringToWeekdayCode (строки 242–270). Комментарии Javadoc, не добавляющие полезной информации к сигнатуре метода, только загромождают код [C3],[G12]. В комментарии есть всего один содержательный момент — он описывает возвращаемое значение -1. Но после перехода на перечисление Day этот комментарий стал неверным [C2]. Сейчас метод сообщает об ошибке, выдавая исключение IllegalArgumentException. Я удалил комментарий.
Также я удалил все ключевые слова final в объявлениях аргументов и переменных. На мой взгляд, реальной пользы от них не было, а программу они загромождают [G12]. Удаление final противоречит мнению некоторых экспертов. Например, Роберт Симмонс (Robert Simmons) [Simmons04, p. 73] настоятельно рекомендует «…почаще вставлять final в своем коде». Разумеется, я с этим не согласен. У final имеются свои полезные применения (например, при объявлении отдельных констант), но в остальных случаях это ключевое слово не приносит реальной пользы. Возможно, я так считаю еще и потому, что типичные ошибки, выявляемые при помощи final, уже выявляются написанными мной модульными тестами.
Мне не понравились повторяющиеся команды if [G5] внутри цикла for (строки 259 и 263); они были объединены в одну команду if при помощи оператора ||. Также я использовал перечисление Day для управления циклом for и внес ряд других косметических изменений.
Мне пришло в голову, что метод в действительности не принадлежит DayDate. Фактически это функция разбора Day, поэтому я переместил ее в перечисление Day. Но после этого перечисление Day стало занимать довольно много места. Поскольку концепция Day не зависит от DayDate, я вывел перечисление Day из класса DayDate в собственный исходный файл [G13].
Кроме того, я переместил следующую функцию weekdayCodeToString (строки 272–286) в перечисление Day и переименовал ее в toString.
public enum Day {
MONDAY(Calendar.MONDAY),
TUESDAY(Calendar.TUESDAY),
WEDNESDAY(Calendar.WEDNESDAY),s
THURSDAY(Calendar.THURSDAY),
FRIDAY(Calendar.FRIDAY),
SATURDAY(Calendar.SATURDAY),
SUNDAY(Calendar.SUNDAY);
public final int index;
private static DateFormatSymbols dateSymbols = new DateFormatSymbols();
Day(int day) {
index = day;
}