Читаем Чистый код. Создание, анализ и рефакторинг полностью

  int offsetToTarget = targetDayOfWeek.index - getDayOfWeek().index;

  if (offsetToTarget <= 0)

    offsetToTarget += 7;

  return plusDays(offsetToTarget);

}

Далее идет функция getNearestDayOfWeek (строки 695–726), которую мы исправляли на с. 309. Внесенные тогда изменения не соответствуют тому шаблону, по которому были преобразованы две последние функции [G11]. Я преобразовал функцию по тем же правилам, а также воспользовался ПОЯСНИТЕЛЬНЫМИ ВРЕМЕННЫМИ ПЕРЕМЕННЫМИ [G19] для разъяснения алгоритма.

public DayDate getNearestDayOfWeek(final Day targetDay) {

  int offsetToThisWeeksTarget = targetDay.index - getDayOfWeek().index;

  int offsetToFutureTarget = (offsetToThisWeeksTarget + 7) % 7;

  int offsetToPreviousTarget = offsetToFutureTarget - 7;

  if (offsetToFutureTarget > 3)

    return plusDays(offsetToPreviousTarget);

  else

    return plusDays(offsetToFutureTarget);

}

Метод getEndOfCurrentMonth (строки 728–740) выглядит немного странно — перед нами метод экземпляра, который «завидует» [G14] собственному классу, получая аргумент DayDate. Я преобразовал его в полноценный метод экземпляра, а также заменил несколько имен более содержательными.

public DayDate getEndOfMonth() {

  Month month = getMonth();

  int year = getYear();

  int lastDay = lastDayOfMonth(month, year);

  return DayDateFactory.makeDate(lastDay, month, year);

}

Переработка weekInMonthToString (строки 742–761) оказалась очень интересным делом. Используя средства рефакторинга своей IDE, я сначала переместил метод в перечисление WeekInMonth, созданное ранее на с. 312. Затем я переименовал его в toString и преобразовал из статического метода в метод экземпляра. Все тесты прошли успешно. (Догадываетесь, к чему я клоню?)

Затем я полностью удалил метод! Пять проверок завершились неудачей (строки 411–415, листинг Б.4, с. 417). Я изменил эти строки так, чтобы в них использовались имена из перечисления (FIRST, SECOND, . . .). И все тесты прошли. А вы догадываетесь, почему? И понимаете ли вы, почему каждый из этих шагов был необходим? Функция рефакторинга проследила за тем, чтобы все предыдущие вызовы weekInMonthToString были заменены вызовами toString для перечисления weekInMonth, а во всех перечислениях реализация toString просто возвращает имена…

К сожалению, мои ухищрения ни к чему не привели. Как бы элегантно ни выглядела эта замечательная цепочка рефакторинга, в итоге я понял, что единственными пользователями этой функции были тесты, которые я только что изменил. И я удалил тесты.

Стыдно дважды наступать на одни грабли! Определив, что функция relativeToString (строки 765–781) не вызывается нигде, кроме тестов, я просто удалил функцию вместе с ее тестами.

Наконец-то мы добрались до абстрактных методов абстрактного класса. Первый метод выглядит знакомо: toSerial (строки 838–844). На с. 316 я присвоил ему имя toOrdinal. Рассматривая его в новом контексте, я решил, что его лучше переименовать в getOrdinalDay.

Следующий абстрактный метод, toDate (строки 838–844), преобразует DayDate в java.util.Date. Почему метод объявлен абстрактным? Присмотревшись к его реализации в SpreadsheetDate (строки 198–207, листинг Б.5, с. 428), мы видим, что он не зависит ни от каких подробностей реализации класса [G6]. Поэтому я поднял его на более высокий уровень абстракции.

Методы getYYYY, getMonth и getDayOfMonth абстрактны. Метод getDayOfWeek — еще один метод, который следовало бы извлечь из SpreadSheetDate — тоже не зависит от DayDate. Или все-таки зависит? Присмотревшись внимательно (строка 247, листинг Б.5, с. 428), мы видим, что алгоритм неявно зависит от «точки отсчета» дней недели (иначе говоря, от того, какой день недели считается днем 0). Таким образом, хотя функция не имеет физических зависимостей, которые нельзя было бы переместить в DayDate, у нее имеются логические зависимости.

Подобные логические зависимости беспокоят меня [G22]. Если что-то зависит от реализации на логическом уровне, то что-то должно зависеть и на физическом уровне. Кроме того, мне кажется, что сам алгоритм можно было бы сделать более универсальным, чтобы существенно меньшая его часть зависела от реализации [G6].

Перейти на страницу:

Все книги серии Библиотека программиста

Программист-фанатик
Программист-фанатик

В этой книге вы не найдете описания конкретных технологий, алгоритмов и языков программирования — ценность ее не в этом. Она представляет собой сборник практических советов и рекомендаций, касающихся ситуаций, с которыми порой сталкивается любой разработчик: отсутствие мотивации, выбор приоритетов, психология программирования, отношения с руководством и коллегами и многие другие. Подобные знания обычно приходят лишь в результате многолетнего опыта реальной работы. По большому счету перед вами — ярко и увлекательно написанное руководство, которое поможет быстро сделать карьеру в индустрии разработки ПО любому, кто поставил себе такую цель. Конечно, опытные программисты могут найти некоторые идеи автора достаточно очевидными, но и для таких найдутся темы, которые позволят пересмотреть устоявшиеся взгляды и выйти на новый уровень мастерства. Для тех же, кто только в самом начале своего пути как разработчика, чтение данной книги, несомненно, откроет широчайшие перспективы. Издательство выражает благодарность Шувалову А. В. и Курышеву А. И. за помощь в работе над книгой.

Чед Фаулер

Программирование, программы, базы данных / Программирование / Книги по IT

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных