Эта книга о пооекте, над которым я работал в течение нескольких лет с тех самых пор, как я попробовал почитать Design Patterns (Gamma, Helm, Johnson & Vlissides, Addison-Wesley, 1995), которую часто называют Gang of Four[1] или просто GoF.
Есть глава о шаблонах проектирования в первой редакции книги Thinking in C++, которая эволюционировала во второй том второй редакции Thinking in C++, также вы можете найти главу о шаблонах в первой редакции книги Thinking in Java (Я убрал ее из второй редакции, поскольку книга стала слишком большой, а также потомоу, что я решил написать эту книгу).
Это не вводная книга. Я предполагаю, что вы изучили Thinking in Java или эквивалентный текст прежде, чем перейти к этой книге.
В дополнение, я предполагаю, что вы знакомы с синтаксисом Java. Вы должны хорошо понимать объекты и что они из себя представляют, включая полиморфизм. Кроме того, здесь есть статьи, перекликающиеся с Thinking in Java.
С другой стороны, работая с этой книгой, вы выучите очень много об объектно-ориентированном программировании, рассматривая объекты и их использование в различных ситуациях. Если вы обладаете начальными знаниями об объектах, вам может быть трудно понимать дизайн в этой книге.
Синдром 2000-го года (Y2K)
В книге, которая содержит “технологию решения проблем” в своем подзаголовке, ценно упоминание об одной из величайших ловушек в программировании: преждевременная оптимизация. Каждый раз я выдвигаю эту концепцию, прежде всего, фактически все соглашаются с этим. Кроме того, каждый, как будто бы, резервирует в уме специальный случай “исключая тот случай, с которыми мне пришлось познакомиться, как с обычной проблемой.”
Причина, по которой я назвал это синдромом 2000-го года (Y2K), основывается на специальных знаниях. Компьютеры полны тайн для большинства людей, так что когда кто-либо заявляет, что эти глупые компьютерные программисты забыли оставить достаточно значащих цифр, чтобы запоминать даты года после 1999, то после этого все становятся компьютерными экспертами – “эти вещи не настолько сложные и выглядят, как обычная проблема”. Например, обычно я занимаюсь компьютерным инженерингом, а я начал заниматься встроенными компьютерными системами. В результате, я знаю, что многие встроенные системы не имеют представлении о дате и времени, и даже если они могут получить информацию о дате, они не используют ее в главных расчетах. И теперь я могу сказать, что нет неопределенности относительно устойчивости для всех встроенных систем на 1 января 2000 года. Насколько я могу сказать, единственная память, которая терялась, была о людях, предвещавших гибель – как будто они никогда не говорили подобной чепухи.
Дело в том, что очень легко попасть под влияние привычки, думая, что обычный алгоритм или кусок кода, который вы понимаете, в вашей системе может стать узким местом. Это происходит просто потому, что вы можете представлять себе, что остальные куски кода и все что вы придумаете должны каким-то образом быть намного менее эффективными, чем остальные куски кода, о которых вы не знаете. Но до тех пор, пока вы не запустите реальные тесты, обычно с помощью профайлера, вы реально не можете знать, что происходит. И даже если вы правы, что кусок кода очень неэффективен, помните, что многие программы тратят около 90% своего времени на выполнение 10% кода программы, так что пока кусок кода, о котором вы думаете, не попадет в эти 10%, это не важно.
“Мы должны забыть о маленькой эффективности, говорите 97% вашего времени: Преждевременная оптимизация - это корень всех бед. ”—Donald Knuth
Контекст и композиция
Один из терминов, которые, как вы увидите, используется снова и снова в литературе по шаблонам проектирования, это контекст. Фактически, одно общее определение шаблонов проектирования - “это решение проблем в контексте”. Шаблоны GoF часто имеют “контекст объекта”, с которым взаимодействует программист в качестве клиента. С одной стороны, для меня имеет место, что такой объект доминирует над набором шаблонов, и я начинаю спрашивать, что это такое.
Контекст объекта часто выступает в роли маленького фасада, прячущего сложность всего остального шаблона, а в дополнение он часто управляется операциями шаблона. Изначально он выглядит для меня так, как будто нет реальной сущности для реализации, использования и понимания шаблона. Однако, я запомнил одно существенно важное утверждение, сделанное в GoF: “предпочитайте композицию наследованию”. Контекст объекта позволяет вам использовать шаблон в композиции, а это может быть основной ценностью.
Слово о проверенных исключениях
-
Лучший способ использования исключений, это унификация отчетов об ошибках: стандартный механизма, с помощью которого сообщается об ошибках, вместо винегрета игнорируемых приближений, которые мы имеем в C (а также C++, в который просто добавлены исключения, а не используется исключительно этот подход). Наибольшее преимущество Java над C++ в том, что исключения — это просто способ сообщения об ошибке.
-
"Игнорирование" в предыдущем параграфе - это другая возможность. Теория говорит о том, что компилятор заставляет программиста либо обрабатывать исключения, либо передавать их путем указания спецификации, внимание программистов всегда будет обращено на возможность ошибки и они должным образом позаботятся об этом. Я думаю, что проблема в нашем непроверенном предположении, что разработчиков языков уходят в область психологии. Моя теория заключается в том, что когда кто-либо собирается что-то сделать, и вы постоянно досаждаете ему неприятностями, он будет использовать наиболее быстрое существующее устройство, чтобы заставить исчезнуть это раздражение, чтобы он мог завершить начатое, возможно он позже вернется и уберет это устройство. Я заметил, что сделал нечто подобное в первой редакции Thinking in Java:
...
} catch (SomeKindOfException e) {}
Затем я забыл об этом до тех пор, пока не стал переписывать. Сколько людей подумали, что это хороший пример и последовали ему? Martin Fowler начал просматривать подобный код и понял, что люди хотели перехватить исключения и они должны исчезнуть. Накладные расходы проверки исключений имеют обратный эффект своего предназначения, который может всплыть при экспериментах (и сейчас я верю, что проверенные исключения были экспериментом, основанным на том, что кто-то думал, что это хорошая идея, и я верил, что это хорошая идея, до недавнего времени).
Когда я начал использовать Python, все исключения появлялись, но ни одно случайно не "исчезало". Если вы *хотите* поймать исключение, вы можете, но вы не обязаны писать кучу кода каждый раз при обработке исключений. Оно идет туда, где вы хотите поймать его, или они все выходят наружу, если вы забыли (и таким образом они напомнят о себе), но они не исчезнут, во всех возможных случаях. Теперь я верю, что проверенные исключения поощряют людей делать их исчезнувшими. Плюс к этому, они делают код менее читабельным.
В заключение, я думаю, что мы должны реализовывать экспериментальную
природу исключений и рассматривать их с осторожностью, прежде чем предположить,
что все, что касается исключений в Java - это хорошо. Я верю, что владение единым
механизмом для обработки ошибок - это превосходно, и я верю, что использование
разделяемых каналов (механизма обработки исключений) для передачи исключений
далее - это хорошо. Но я помню один из ранних аргументов обработки исключений
в C++, который заключался в том, что программисту необходимо позволить разделять
секцию кода, в которой он просто хочет завершить работу, от секции, в которой
он обрабатывает ошибку, а для меня это не выглядит, как будто проверка исключений
делает это разделение. Вместо этого исключения способствуют внедрению (огромного
количества) кода в ваш "нормально работающий код", а это шаг назад.
Мой опыт работы с поддержкой исключений в Python подтверждает это, и если я
не изменю мнения относительно этой проблемы, я намереваюсь помещать гораздо
больше RuntimeException в мой код на Java.
← | Предисловие | Концепция шаблона | → |