org.jfree.date.SerialDate 451 Листинг Б.16. SpreadsheetDate.java (окончательная версия) 1 /* ======================================================================== 2 * JCommon : библиотека классов общего назначения для платформы Java(tm) 3 * ======================================================================== 4 * 5 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 6 * ... 52 * 53 */ 54 55 package org.jfree.date; 56 57 import static org.jfree.date.Month.FEBRUARY; 58 59 import java.util.*; 60 61 /** 62 * Представляет дату с использованием целого числа, по аналогии с реализацией 63 * в Microsoft Excel. Поддерживаемый диапазон дат: 64 * с 1 января 1900 по 31 декабря 9999. 65 * <p/> 66 * Учтите, что в Excel существует намеренная ошибка, вследствие которой год 67 * 1900 считается високосным, тогда как в действительности он таковым не является. 68 * Дополнительная информация приведена на сайте Microsoft в статье Q181370: 69 * <p/> 70 * http://support.microsoft.com/support/kb/articles/Q181/3/70.asp 71 * <p/> 72 * По правилам Excel 1 января 1900 = 1. По правилам этого класса 73 * 1 января 1900 = 2. 74 * В результате номер дня этого класса будет отличаться от номера Excel 75 * в январе и феврале 1900...но затем Excel прибавляет лишний день 76 * (29 февраля 1900, который в действительности не существует!), и с этого 77 * момента нумерация дней совпадает. 78 * 79 * @author David Gilbert 80 */ 81 public class SpreadsheetDate extends DayDate { 82 public static final int EARLIEST_DATE_ORDINAL = 2; // 1/1/1900 83 public static final int LATEST_DATE_ORDINAL = 2958465; // 12/31/9999 84 public static final int MINIMUM_YEAR_SUPPORTED = 1900; 85 public static final int MAXIMUM_YEAR_SUPPORTED = 9999; 86 static final int[] AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 87 {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 88 static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 89 {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; 90 91 private int ordinalDay; 92 private int day; 93 private Month month; 94 private int year; продолжение
452 Приложение Б. org.jfree.date.SerialDate Листинг Б.16 (продолжение) 95 96 public SpreadsheetDate(int day, Month month, int year) { 97 if (year < MINIMUM_YEAR_SUPPORTED || year > MAXIMUM_YEAR_SUPPORTED) 98 throw new IllegalArgumentException( 99 "The 'year' argument must be in range " + 100 MINIMUM_YEAR_SUPPORTED + " to " + MAXIMUM_YEAR_SUPPORTED + "."); 101 if (day < 1 || day > DateUtil.lastDayOfMonth(month, year)) 102 throw new IllegalArgumentException("Invalid 'day' argument."); 103 104 this.year = year; 105 this.month = month; 106 this.day = day; 107 ordinalDay = calcOrdinal(day, month, year); 108 } 109 110 public SpreadsheetDate(int day, int month, int year) { 111 this(day, Month.fromInt(month), year); 112 } 113 114 public SpreadsheetDate(int serial) { 115 if (serial < EARLIEST_DATE_ORDINAL || serial > LATEST_DATE_ORDINAL) 116 throw new IllegalArgumentException( 117 "SpreadsheetDate: Serial must be in range 2 to 2958465."); 118 119 ordinalDay = serial; 120 calcDayMonthYear(); 121 } 122 123 public int getOrdinalDay() { 124 return ordinalDay; 125 } 126 127 public int getYear() { 128 return year; 129 } 130 131 public Month getMonth() { 132 return month; 133 } 134 135 public int getDayOfMonth() { 136 return day; 137 } 138 139 protected Day getDayOfWeekForOrdinalZero() {return Day.SATURDAY;} 140 141 public boolean equals(Object object) { 142 if (!(object instanceof DayDate)) 143 return false; 144
org.jfree.date.SerialDate 453 145 DayDate date = (DayDate) object; 146 return date.getOrdinalDay() == getOrdinalDay(); 147 } 148 149 public int hashCode() { 150 return getOrdinalDay(); 151 } 152 153 public int compareTo(Object other) { 154 return daysSince((DayDate) other); 155 } 156 157 private int calcOrdinal(int day, Month month, int year) { 158 int leapDaysForYear = DateUtil.leapYearCount(year - 1); 159 int daysUpToYear = (year - MINIMUM_YEAR_SUPPORTED) * 365 + leapDaysForYear; 160 int daysUpToMonth = AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH[month.toInt()]; 161 if (DateUtil.isLeapYear(year) && month.toInt() > FEBRUARY.toInt()) 162 daysUpToMonth++; 163 int daysInMonth = day - 1; 164 return daysUpToYear + daysUpToMonth + daysInMonth + EARLIEST_DATE_ORDINAL; 165 } 166 167 private void calcDayMonthYear() { 168 int days = ordinalDay - EARLIEST_DATE_ORDINAL; 169 int overestimatedYear = MINIMUM_YEAR_SUPPORTED + days / 365; 170 int nonleapdays = days - DateUtil.leapYearCount(overestimatedYear); 171 int underestimatedYear = MINIMUM_YEAR_SUPPORTED + nonleapdays / 365; 172 173 year = huntForYearContaining(ordinalDay, underestimatedYear); 174 int firstOrdinalOfYear = firstOrdinalOfYear(year); 175 month = huntForMonthContaining(ordinalDay, firstOrdinalOfYear); 176 day = ordinalDay - firstOrdinalOfYear - daysBeforeThisMonth(month.toInt()); 177 } 178 179 private Month huntForMonthContaining(int anOrdinal, int firstOrdinalOfYear) { 180 int daysIntoThisYear = anOrdinal - firstOrdinalOfYear; 181 int aMonth = 1; 182 while (daysBeforeThisMonth(aMonth) < daysIntoThisYear) 183 aMonth++; 184 185 return Month.fromInt(aMonth - 1); 186 } 187 188 private int daysBeforeThisMonth(int aMonth) { 189 if (DateUtil.isLeapYear(year)) 190 return LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH[aMonth] - 1; 191 else 192 return AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH[aMonth] - 1; 193 } 194 195 private int huntForYearContaining(int anOrdinalDay, int startingYear) { продолжение
454 Приложение Б. org.jfree.date.SerialDate Листинг Б.16 (продолжение) 196 int aYear = startingYear; 197 while (firstOrdinalOfYear(aYear) <= anOrdinalDay) 198 aYear++; 199 200 return aYear - 1; 201 } 202 203 private int firstOrdinalOfYear(int year) { 204 return calcOrdinal(1, Month.JANUARY, year); 205 } 206 207 public static DayDate createInstance(Date date) { 208 GregorianCalendar calendar = new GregorianCalendar(); 209 calendar.setTime(date); 210 return new SpreadsheetDate(calendar.get(Calendar.DATE), 211 Month.fromInt(calendar.get(Calendar.MONTH) + 1), 212 calendar.get(Calendar.YEAR)); 213 214 } 215 }
Перекрестные ссылки Перекрестные ссылки для «запахов кода» и эвристических правил из приложения А организованы по принципу Номер_главы-Номер_страницы. C1 16-306, 16-309, 17-323 C2 16-309, 16-312, 16-320, 17-323 C3 16-311, 16-312, 16-314, 17-323 C4 17-323 C5 17-324 E1 17-324 E2 17-324 F1 14-266, 17-325 F2 17-325 F3 17-325 F4 16-304, 16-314, 17-325 G1 16-307, 17-325 G2 16-305, 17-326 G3 16-305, 17-326 G4 16-308, 17-326 G5 16-308, 16-313, 16-317, 16-320, 17-327 G6 6-128, 16-309, 16-311, 16-315, 16-318, 16-319, 17-328 G7 16-309, 17-329 G8 16-311, 17-329 G9 16-311, 16-312, 16-314, 17-330 G10 5-107, 16-311, 17-330 G11 15-295, 16-311, 16-314, 16-317, 17-330 G12 16-312, 16-313, 16-314, 16-315, 16-320, 17-331 G13 16-313, 16-314, 17-331 В
456 Приложение В. Перекрестные ссылки G14 16-314, 17-331 G15 16-315, 17-333 G16 16-315, 17-333 G17 16-315, 17-334, 17-337 G18 16-315, 16-316, 16-317, 17-334 G19 16-316, 16-317, 17-335 G20 16-316, 17-335 G21 16-317, 17-336 G22 16-318, 17-336 G23 3-63, 14-265, 16-319, 17-338 G24 16-320, 17-338 G25 16-320, 17-339 G26 17-340 G27 17-340 G28 15-293, 17-341 G29 15-394, 17-341 G30 15-295, 17-341 G31 15-296, 17-342 G32 15-296, 17-343 G33 15-298, 17-343 G34 3-60, 6-128, 17-344 G35 5-111, 17-345 G36 6-126, 17-346 J1 16-306, 17-347 J2 16-308, 17-347 J3 16-311, 16-312, 17-348 N1 15-296, 16-307, 16-309, 16-310, 16-314, 16-315, 16-316, 16-319, 17-349 N2 16-307, 17-351 N3 16-312, 16-314, 17-352 N4 15-294, 16-316, 17-352 N5 2-45, 14-248, 17-353 N6 15-293, 17-353 N7 15-294, 17-354 T1 16-304, 16-305, 17-354 T2 16-304, 17-354 T3 16-305, 17-354
Перекрестные ссылки 457 T4 17-355 T5 16-305, 16-306, 17-355 T6 16-305, 17-355 T7 16-306, 17-355 T8 16-306, 17-355 T9 17-356
Эпилог На конференции по гибким методологиям, проходившей в Денвере в 2005 году, Элизабет Хедриксон1 вручила мне зеленый браслет наподобие тех, которые стали такими популярными после Ланса Армстронга. На браслете было написано «Одержим тестированием». Я с гордостью носил этот браслет. С тех пор как Кент Бек научил меня методологии разработки через тестирование (TDD) в 1999 году, я действительно стал буквально одержим этой темой. Но потом случилось нечто странное. Я обнаружил, что не могу снять этот браслет, причем вовсе не потому, что он застрял у меня на запястье. Браслет открыто формулировал мою профессиональную этику. Он стал визуальным признаком моего стремления к написанию самого лучшего кода, который я могу написать. Мне казалось, что снять его – значит предать эту этику вместе с моими устремлениями. Браслет так и остается у меня на запястье. Занимаясь программированием, я вижу его периферийным зрением. Он постоянно напоминает мне о том обещании, которое я дал сам себе – обещании писать чистый код. 1 http://www.qualitytree.com/
Алфавитный указатель A Ant, проект 95 ArgsException, класс объединение исключений 267 Args, класс конструирование 218 реализация 218 ArgumentMarshaler, класс 238 AspectJ, язык 187 assePersonNamertEquals 59 assePersonNamert, директивы 151 C Callable, интерфейс 359 CAS, операция 361 clientScheduler 352 ClientTest.java 350 Clover 296 ComparisonCompactor, модуль 280 ConcurrentHashMap, реализация 205 ConTest, программа 215, 376 CountDownLatch, класс 205 D DateInterval, перечисление 311 DayDateFactory 302 DayDate, класс 299 DIP (Dependency Inversion Principle) 30, 172 DoubleArgumentMarshaler, класс 265 DTO (Data Transfer Objects) 120 E Eclipse 41 EJB, архитектура 189 errorMessage, метод 278 Error, класс 65 Executor 353 ExecutorClientScheduler.java 353 F false, аргумент 324 final, ключевое слово 305 FitNesse, проект размеры файлов 95 стиль кодирования 110 G getNextId, метод 357 goto, команды 66 H HashTable 361 HTML, в исходном коде 88 I IntelliJ 41 InvocationHandler, объект 183 J jar, файлы 321 Java аспекты 184 исходные файлы 95 многословность 224 эвристики 339 Javadoc для каждой функции 82 как балласт 304 сохранение форматирования 299
460 Алфавитный указатель java.util.concurrent, пакет 205 JBoss AOP 184 JCommon, библиотека 295 JDepend, проект 95 JUnit 50, 95, 279 L log4j, пакет 137 LOGO, язык 52 M main, функция 176 Month, перечисление 306 N null возвращение 131 при вызове методов 132 случайная передача 133 NullPointerException 131 O OCP, принцип 30, 54 P POJO (Plain-Old Java Objects) 211 PUTFIELD, инструкция 357 R Runnable, интерфейс 359 S Spring Framework 178 switch/case, цепочки 319 synchronized, ключевое слово 208 T TDD (разработка через тестирование) 238 testNG, проект 95 this, переменная 357 throws, секция 127 Time and Money, проект 95 TODO, комментарии 77 Tomcat, проект 95 TO, ключевое слово 52 try/catch, блоки 64 try, блоки 125 А АБСТРАКТНАЯ ФАБРИКА, паттерн 55, 176, 302 абстрактные интерфейсы 114 абстрактные классы 171, 301, 320 абстрактные методы 312 абстракция зависимость классов 172 код на неверном уровне 320 разделение уровней 337 смешение уровней 53 уровни 53 автоматизация инструментовки кода 214 алгоритмы повторение 65 понимание 328 аннотации, в AspectJ 187 АОП (аспектно-ориентированное программирование) 181 аргументы командной строки 217 конструктора 177 унарные формы 57 флаги 58 функции 56 аспектно-ориентированное программирование (АОП) 181 аспекты, в АОП 182 атомарная операция 356 атрибуты 76 Б базовые классы 320 байт-код 203 Бек, Кент 17, 50, 90, 192, 280 бизнес-логика 130 бинарные функции 56, 58 блокировка с ожиданием 370 Буч, Грэди 23 В венгерская запись 38, 325 взаимная блокировка 206, 369 взаимное исключение 206, 370 вложенные структуры 63 волшебные числа 325 воспроизводимость, многопоточные ошибки 210 временная привязка 288
Алфавитный указатель 461 вызовы методов 357 выразительность кода 26 выходные аргументы 57, 62, 317 Г Гамма, Эрик 280 Гилберт, Дэвид 295 горизонтальное выравнивание 106 горизонтальное форматирование 104 грамотное программирование 24 границы некорректное поведение 318 отделение известного от неизвестного 140 чистые 141 группы влияние плохого кода 18 стандарты кодирования 330 Д данные абстракция 113 инкапсуляция 204 копии 204 Дейкстра, Эдгар 66 ДЕКОРАТОР, паттерн 302 Джеффрис, Рон 24, 319 длинные содержательные имена 56 дублирование кода 66 устранение 194 формы 194 Ж жесткая привязка 193 З зависимости внедрение 177 логические 310 между методами 362 поиск 278 заголовок, объединение функций 86 закон Деметры 118, 338 закономерности сбоев 347 закрывающие фигурные скобки 86 запахи кода, список 314 запросы, отделение от команд 62 защищенные переменные 99 И иерархия вызовов 127 иерархия наследования 340 избыточность 35 изменения изоляция 172 структурирование 168 тестирование 144 изоляция изменений 172 имена абстракции, уровень 343 выбор 197 изменение 56 классов 299 короткие 45 пространство решения 42 функций 327 имена классов 40 именованные константы 331 инкапсуляция 157 инструментовка 376 интерфейсы кодирование 39 написание 140 реализация 171 хорошо определенные 321 исключения вместо кодов ошибок 124 инициирование 124 непроверяемые 127 передача контекста 128 искусственная привязка 323 искусство чистого кода 20 история изменений 297 исходные файлы, смешение языков 317 К кадр 356 Каннингем, Уорд 26 классы выбор имен 40, 164 инструментовка в ConTest 376 как существительные 67 компактность 157 объявление переменных экземпляров 100 потоково-небезопасные 361 связность 161 клиент/сервер, приложение 349 клиентская блокировка 208, 364
462 Алфавитный указатель код 16 выражение 72 завершения 209 закомментированный 87, 316 мертвый 322 плохой 17 правила Бека 24 простота 33 удобочитаемость 327 форматирование 95 команды, отделение от запросов 62 комментарии HTML 88 TODO 77 избыточные 79, 315 как неизбежное зло 71 недостоверные 81 неточные 72 неуместные 315 плохие 78 удаление 311 устаревшие 315 хорошие 73 конкретные классы 171 константы наследование 299 перечисления 340 конструкторы, перегрузка 40 контекст 43, 128 концепции вертикальное разделение 97 имена 33 разделение 320 корректное завершение 209 Л Леблана, закон 18 Ли, Дуг 376 логические аргументы 218, 317 логические зависимости 310, 328 локальные комментарии 88 локальные переменные 357 М масштабирование 178 мертвые функции 317 мертвый код 317, 322 методы вызов с флагом 306 зависимости 362 методы (продолжение) имена 40 классов 159 преобразование статических 307 минимальный код 24 многопоточность мифы 201 причины использования 200 многопоточный код 373 на Java 5 205 тестирование 210 модели выполнения 206 модульные тесты 143, 197, 296 Монте-Карло, тестирование 375 мысленные преобразования 39 Н неблокирующие решения 360 необоснованная структура 335 неоднозначности в коде 332, 339 непроверяемые исключения 127 номенклатуры, стандартные 344 нормальные формы баз данных 66 нуль-арные функции 56 Ньюкирк, Джим 137 О обедающие философы, модель 207 область видимости вырожденная 109 исключения 125 общие переменные 366 отступы 108 обработка ошибок 22, 63 обратимая блокировка 206, 372 объектно-ориентированное проектирование 29 объекты копирование 204 определение 115 сравнение со структурами данных 115 объекты передачи данных 120 однопоточная модель 368 операторы, приоритет 106 оптимистичная блокировка 360 ОСОБЫЙ СЛУЧАЙ, паттерн 131 ОТЛОЖЕННАЯ ИНИЦИАЛИЗАЦИЯ 175 отрицательные условия 333 отступы, в коде 108
Алфавитный указатель 463 очевидное поведение 318 очевидный код 26 ошибки граничных условий 297 П паттерны, названия 197 перезагрузка 363 переименование 34 переключение задач 212 переменные локальные 322 неясный контекст 43 объявление 100, 322 перемещение в другой класс 303 переменные экземпляров в классах 161 объявление 100 переработка как итеративный процесс 294 последовательная 193 тестовый код 149 перестановки 355 перечисления 340 пессимистичная блокировка 360 плохие комментарии 78 плохой код 17 побочные эффекты 61 описание в именах 346 повторное использование 195 полиморфизм 54, 319 полиморфное поведение функций 326 посредники 182 ПОСТРОЕНИЕ-ОПЕРАЦИЯПРОВЕРКА, паттерн 148 потоки конкуренция за ресурсы 371 конфликты 361 независимость 204 пояснительные переменные 327 правило бойскаута 29, 285 предикаты 40 предупреждения компилятора 319 префиксы 38, 345 приватные функции 322 принцип единой ответственности (SRP) 30, 159 принцип наименьшего удивления 318 принцип открытости/закрытости (OCP) 30, 54 присваивание 106 проверяемые исключения 127 программирование определение 16 структурное 66 программисты как авторы 28 ответственность 20 парадокс 20 производительность многопоточные решения 201 пара клиент/сервер 350 повышение 350 простой код 24 профессионализм программиста 40 процедурный код 117 процедуры, сравнение с объектами 117 процессы, конкуренция за ресурсы 207 пулы потоков 359 пустые строки, в коде 97 пути выполнения 354 Р размер файла, в Java 95 разработка через тестирование (TDD) 238 реализация дублирование 194 скрытие 114 ресурсы глобальный порядок выделения 372 конкуренция 207 риск изменений 168 С связность классов 161 поддержание 162 селекторы, аргументы 324 серверная блокировка 208, 365 серверный код 351 сервлет, модель веб-приложений 200 сериализация 300 сигнатуры функций 62 Симмонс, Роберт 305 СИНГЛЕТ, паттерн 302 синхронизация 204 системы управления исходным кодом 83 сложность, управление 161 события 58
464 Алфавитный указатель содержательные имена 56, 341 сообщения об ошибках 128, 278 списки аргументов 60 списки импорта 339 средства безопасности, отключение 318 стандарт кодирования 330 статические методы 326 статические функции 307 стек операндов 357 сторонний код изучение 137 интеграция 137 СТРАТЕГИЯ, паттерн 319 Страуструп, Бьёрн 21 строковые аргументы 218 структурное программирование 66 счетчики циклов 39 Т тернарные функции 56, 59 тестовые пакеты автоматизация 238 модульные тесты 143, 296 тестовые сценарии 264 закономерности сбоев 298 отключение 76 тесты быстрота 154 грязные 144 запуск 375 независимость 154 отключение 347 очевидность 154 повторяемость 154 своевременность 154 чистые 144 эвристики 346 типы аргументов, добавление 233 Томас, Дэйв 23, 319 У удобочитаемость 95 унарные функции 56 унаследованный код 339 уровень абстракции 53 Ф фабрики 176 Фаулер, Мартин 314 Физерс, Майкл 24 форматирование горизонтальное 104 функции временная привязка 288 длина 50 имена 56, 327 как глаголы 67 компактность 197 мертвые 317 одна операция 333 приватные 322 структурное программирование 66 функциональная зависть 323 Х Хант, Энди 22, 319 Ц циклическое ожидание 371 Ч чистые тесты 144 чистый код искусство 20 описание 21 чтение сверху вниз 53 сравнение с написанием кода 28 чистый код 23 чувство кода 21 Ш ШАБЛОННЫЙ МЕТОД, паттерн 319 шумовые комментарии 83 Э Эванс, Эрик 344 эстафета 334 эффективность кода 22 Я языки простота 26 смешение в исходных файлах 317 смешение в комментариях 298 уровень абстракции 16 ясность 40