Файл: Руководство по стилю программирования и конструированию по.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 30.11.2023
Просмотров: 785
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
ГЛАВА
5 Проектирование при конструировании
99
쐽
Модуль 1 передает в Модуль 2 управляющий флаг, определяющий дальнейшую работу Модуля 2. Этот подход подразумевает, что Модуль 1 должен сделать предположения о внутренней работе Модуля 2, а именно о том, что Модуль
2 собирается делать с управляющим флагом. Если Модуль 2 определяет для управляющего флага специфический тип данных (перечисление или объект), этот вид сопряжения, вероятно, будет вполне приемлем.
쐽
Модуль 2 использует глобальные данные после их изменения Модулем 1. При этом Модуль 2 предполагает, что Модуль 1 был вызван в нужное время и изме- нил данные так, как нужно Модулю 2.
쐽
Интерфейс Модуля 1 утверждает, что метод
Module1. Initialize() должен быть вызван до метода
Module1.Routine(). Модуль 2 знает, что Module1.Routine() как- то вызывает метод
Module1.Initialize(), поэтому он просто создает экземпляр
Модуля 1 и вызывает
Module1.Routine() без предварительного вызова метода
Module1.Initialize().
쐽
Модуль 1 передает Объект в Модуль 2. Модуль 1 знает, что Модуль 2 использует только три метода Объекта из семи, поэтому он инициализирует Объект лишь частично, только теми данными, что нужны этим трем методам.
쐽
Модуль 1 передает в Модуль 2 Базовый Объект. Модуль 2 знает, что на самом деле Модуль 1 передал ему Производный Объект, поэтому он приводит тип
Базового Объекта к типу Производного Объекта и вызывает методы, специфи- ческие для Производного Объекта.
Семантическое сопряжение опасно тем, что изменение кода в используемом мо- дуле может так нарушить работу использующего модуля, что компилятор этого не определит. Обычно это приводит к очень тонким проблемам, которые никто не соотносит с изменениями используемого модуля, что превращает отладку в сизифов труд.
Суть слабого сопряжения в том, что грамотно спроектированный модуль предо- ставляет дополнительный уровень абстракции: разработав его, вы можете прини- мать его как данное. Это снижает общую сложность программы и позволяет сосре- доточиваться в каждый момент времени только на одном аспекте. Если для исполь- зования модуля нужно учитывать сразу несколько аспектов: механизм внутренней работы, изменения глобальных данных, неясную функциональность, — сила абст- ракции исчезает, и модуль перестает облегчать управление сложностью.
Классы и методы — главные интеллектуальные инструменты снижения сложности. Если они не упрощают вашу работу, они не исполняют свои обязанности.
Старайтесь использовать популярные шаблоны
проектирования
Шаблоны проектирования — это готовые шаблоны, позво- ляющие решать частые проблемы разработки. Конечно, есть проблемы, требующие совершенно новых решений, но боль- шинство уже встречалось разработчикам, поэтому их можно решить, применяя проверенные подходы, или шаблоны. В число популярных шаблонов проектиро- вания входят Адаптер, Мост, Декоратор, Фасад, Фабричный метод, Наблюдатель, http://cc2e.com/0585
100
ЧАСТЬ
II
Высококачественный код
Одиночка, Стратегия и Шаблонный метод. О шаблонах проектирования см. книгу
«Design Patterns» Эриха Гаммы, Ричарда Хелма, Ральфа Джонсона и Джона Влис- сидеса (Gamma, Helm, Johnson, and Vlissides, 1995).
Шаблоны имеют ряд достоинств, не характерных для полностью самостоятельного проектирования программы.
Шаблоны снижают сложность, предоставляя готовые абстракции Если вы скажете: «В этом фрагменте для создания экземпляров производных классов применяется шаблон “Фабричный метод”», — другие программисты поймут, что ваш код включает богатый набор взаимодействий и протоколов программирова- ния, специфических для названного шаблона.
Шаблон «Фабричный метод» позволяет создавать экземпляры любого класса, про- изводного от указанного базового класса, причем отдельные производные классы отслеживаются только самим «Фабричным методом». Обсуждение шаблона «Фа- бричный метод» см. в разделе «Replace Constructor with Factory Method» (Замена конструктора на «Фабричный метод») книги «Refactoring» (Fowler, 1999).
Если вы будете использовать шаблоны, другие программисты легко поймут вы-бранный вами подход к проектированию без подробного обсуждения кода.
Шаблоны снижают число ошибок, стандартизируя детали популярных
решений Проблемы проектирования содержат нюансы, которые полностью проявляются только после решения проблемы один или два раза (или три, или четыре, или…). Шаблоны — это стандартизованные способы решения частых проблем, заключающие мудрость, накопленную за годы попыток решения этих проблем, и исправления неудачных попыток.
Так что, с концептуальной точки зрения, применение шаблона проектирования похоже на использование библиотеки кода вместо написания собственного кода.
Многие программисты рано или поздно решают создать собственный вариант алгоритма быстрой сортировки, но каковы шансы, что его первая версия окажется безошибочной? Так же и в проектировании: многие проблемы довольно похожи на уже решенные задачи, и при столкновении с ними изобретать велосипед ни к чему.
Шаблоны имеют эвристическую ценность, указывая на возможные ва-
рианты проектирования Проектировщик, знакомый с популярными шабло- нами, может с легкостью перебрать список шаблонов и спросить себя: «Какие из них соответствуют моей проблеме проектирования?» Перебрать набор известных вариантов гораздо проще, чем создавать собственное решение с нуля. Кроме того, код, основанный на популярном шаблоне, будет понятнее, чем код, полностью разработанный самостоятельно.
Шаблоны упрощают взаимодействие между разработчиками, позволяя
им общаться на более высоком уровне Шаблоны проектирования не только помогают управлять сложностью, но и способны ускорить обсуждение проектов, позволяя разработчикам размышлять и делиться мыслями на более высоком уровне.
Если вы скажете: «Не могу решить, какой шаблон следует использовать в данной ситуации: “Создатель” или “Фабричный метод”», — вы в нескольких словах сообщи- те очень подробную информацию — конечно, если и вам, и вашему собеседнику известны эти шаблоны. Представьте, насколько больше времени потребовалось
ГЛАВА
5 Проектирование при конструировании
101
бы для обсуждения деталей кода шаблонов «Создатель» и «Фабричный метод» и сравнения этих двух подходов.
Если вы еще не сталкивались с шаблонами проектирования, изучите табл. 5-1, где описаны некоторые из самых популярных шаблонов.
Табл. 5-1. Популярные шаблоны проектирования
Шаблон Описание
Абстрактная фабрика
Поддерживает создание наборов родственных объектов пу-
(Abstract Factory) тем определения вида набора, но не вида каждого отдельно- го объекта.
Адаптер (Adapter)
Преобразует интерфейс класса в другой интерфейс.
Мост (Bridge)
Создает интерфейс и реализацию, так что их можно изме- нять независимо друг от друга.
Компоновщик
Состоит из объекта, содержащего дополнительные объекты
(Composite) такого же типа, позволяя клиентскому коду взаимодейство- вать с объектом верхнего уровня и не заботиться о деталь- ных объектах.
Декоратор (Decorator)
Динамически назначает объекту виды ответственности без создания отдельных подклассов для каждой возможной конфигурации видов ответственности.
Фасад (Facade)
Предоставляет согласованный интерфейс к коду, который в противном случае не предоставлял бы согласованного интерфейса.
Фабричный метод
Создает экземпляры классов, производных от конкретного
(Factory Method) базового класса, причем отдельные производные классы от- слеживаются только «Фабричным методом».
Итератор (Iterator)
Этот серверный объект предоставляет доступ к каждому элементу набора в последовательном порядке.
Наблюдатель (Observer)
Поддерживает синхронизацию нескольких объектов, при которой объект уведомляет набор связанных объектов об изменениях любого члена набора.
Одиночка (Singleton)
Предоставляет глобальный доступ к классу, который может иметь один и только один экземпляр.
Стратегия (Strategy)
Определяет набор динамически взаимозаменяемых алгоритмов или видов поведения.
Шаблонный метод
Определяет структуру алгоритма, оставляя некоторые
(Template Method) детали реализации подклассам.
Если раньше вы не встречались с шаблонами проектирования, при взгляде на табл. 5-1 у вас может возникнуть мысль: «Почти все эти идеи мне уже знакомы».
Этим во многом и объясняется ценность шаблонов проектирования. Они известны большинству опытных программистов, а присвоение шаблонам запоминающихся названий позволяет быстро и эффективно делиться мыслями.
С шаблонами связаны две ловушки. Первая — насильственная адаптация кода к какому-нибудь шаблону. Иногда легкое изменение кода в соответствии с извест- ным шаблоном может сделать код более понятным. Но если адаптация кода к стандартному шаблону требует слишком крупного изменения, это может привести к усложнению программы.
102
ЧАСТЬ
II
Высококачественный код
Вторая — применение шаблона, продиктованное не целесообразностью, а жела- нием испытать шаблон в деле.
Вообще применение шаблонов проектирования — это эффективный инструмент управления сложностью. Некоторые хорошие книги по этой теме указаны в конце главы.
1 ... 11 12 13 14 15 16 17 18 ... 104
Другие эвристические принципы
В предыдущих разделах были рассмотрены основные эвристические принципы проектирования ПО. Ниже описаны менее полезные, однако заслуживающие упо- минания эвристические принципы.
Стремитесь к максимальной связности
Понятие связности (cohesion) возникло в области структурного проектирования и обычно обсуждается в том же контексте, что и сопряжение (coupling). Связность характеризует то, насколько хорошо все методы класса или все фрагменты мето- да соответствуют главной цели, — иначе говоря, насколько сфокусирован класс.
Классы, состоящие из очень похожих по функциональности блоков, обладают высокой степенью связности, и наша эвристическая цель состоит в том, чтобы целостность была как можно выше. Связность — полезный инструмент управления сложностью, потому что чем лучше код класса соответствует главной цели, тем проще запомнить все, что код выполняет.
Стремление к связности на уровне методов давно считается полезным эвристи- ческим принципом. На уровне классов эвристический принцип связности во многом выражен в более общем эвристическом принципе адекватного определения абстракций, что уже обсуждалось в этой главе и будет еще обсуждаться в главе
6. Абстрагирование полезно и на уровне методов, но в этом случае принципы абстрагирования и связности более равноправны.
Формируйте иерархии
Иерархия — это многоуровневая структура организации информации, при которой наиболее общая или абстрактная репрезентация концепции соответствует вершине, а более детальные специализированные репрезентации — более низким уровням.
При разработке ПО иерархии обнаруживаются, например, в наборах классов и в последовательностях вызовов методов (уровень 4 на рис. 5-2).
Формирование иерархий уже более 2000 лет является важным средством управле- ния сложными наборами информации. Так, Аристотель использовал иерархию для организации царства животных. Люди часто организуют сложную информацию
(такую как эта книга) при помощи иерархических схем. Ученые обнаружили, что люди в целом находят иерархии естественным способом организации сложной информации. Рисуя сложный объект (скажем, дом), люди рисуют его иерархиче- ски. Сначала они рисуют очертания дома, затем окна и двери, а после этого — еще более подробные детали. Они не рисуют дом по отдельным кирпичам, доскам или гвоздям (Simon, 1996).