Обучающие курсы:

Обучение профессии "Разработчик C#" + стажировка в Mail.ru
Обучение профессии "Разработчик Python" + трудоустройство
Обучение профессии "Веб-разработчик" + стажировка в Mail.ru


Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей







Стиль проектирования


The Errors of TeX

Очень сложно отделить стиль проектирования от стиля кодирования. Мы попытались поместить в очередном разделе те вопросы, которые обычно проявляются, когда вы начинаете писать реальный код.

В этом разделе внимание уделяется принципам и практическим вопросам, область применения которых больше, чем просто отдельный класс или функция. Классические примеры — баланс между простотой и ясностью (рекомендация 6), избежание преждевременной оптимизации (рекомендация 8) и пессимизации (рекомендация 9). Эти рекомендации применимы не только на уровне кодирования отдельной функции, но и к большим областям — проектированию классов и модулей или к решениям с далеко идущими последствиями по поводу архитектуры приложений. (Они применимы также для всех программистов. Если вы считаете иначе — еще раз прочтите приведенную выше цитату Кнута и даже заучите ее на память.)

Многие из прочих рекомендаций этого и следующего разделов имеют дело с управлением зависимостями — краеугольным камнем проектирования программного обеспечения и часто повторяющейся в данной книге темой. Остановитесь и задумайтесь над произвольной методикой проектирования программного обеспечения — любой хорошей методикой. Какую бы методику вы ни выбрали, так или иначе вы столкнетесь с ослаблением зависимостей. Наследование? Разрабатываемый код должен делать производный класс как можно менее зависимым от базового класса. Минимизация использования глобальных переменных? Снижает дальнодействующие зависимости, осуществляемые посредством широко видимых разным частям программы данных. Абстракция? Устраняет зависимости между кодом, который управляет концепциями, и кодом, который их реализует. Сокрытие информации? Делает код клиента менее зависимым от деталей реализации. Забота об управлении зависимостями отражается в устранении совместного использования состояния (рекомендация 10), применении сокрытия информации (рекомендация 11) и прочем.

В этом разделе самой важной нам кажется рекомендация 6: " Главное — корректность, простота и ясность".

5. Один объект — одна задача

Резюме

Концентрируйтесь одновременно только на одной проблеме. Каждый объект (переменная, класс, функция, пространство имен, модуль, библиотека) должны решать одну точно поставленную задачу. С ростом объектов, естественно, увеличивается область их ответственности, но они не должны отклоняться от своего предназначения.

Обсуждение

Хорошая идея, будучи высказанной вслух, должна быть пояснена одним предложением. Аналогично, каждая сущность в программе должна иметь одно ясное предназначение.

Объект с разнородными предназначениями обычно несоразмерно трудно использовать, поскольку он представляет собой нечто большее, чем просто сумму решений, сложностей и ошибок составляющих его частей. Такой объект больше по размеру (зачастую без особых на то причин) и сложнее в применении и повторном использовании. Зачастую такие объекты имеют весьма убогий интерфейс для каждого из своих отдельных предназначений, поскольку частичное перекрытие разных областей функциональности приводит к невозможности четкой реализации в каждой из них.

Объекты с разнородными функциями обычно трудны для проектирования и реализации. "Множественная ответственность" зачастую приводит к тому, что количество возможных вариантов поведения и состояния объектов разрастается в соответствии с законами комбинаторики. Предпочтительнее использовать короткие функции с четко указанным единственным предназначением (см. также рекомендацию 39), маленькие классы, предназначенные для решения одной конкретной задачи, и компактные модули с четко очерченными границами.

Абстракции высокого уровня предпочтительно строить из меньших низкоуровневых абстракций. Избегайте объединения нескольких низкоуровневых абстракций в большой низкоуровневый конгломерат. Реализация сложного поведения из набора простых существенно легче решения обратной задачи.

Примеры

Пример I. reallос. В стандарте С функция real1ос пользуется дурной славой плохо спроектированной функции. Она делает одновременно слишком много дел: выделяет память, если ей передано значение NULL, освобождает ее, если передан нулевой размер, перераспределяет ее на том же месте, если это возможно, или перемещает ее, если такое перераспределение невозможно. Это уже не просто расширение функциональности. Данная функция обычно рассматривается всеми как пример недальновидного, ошибочного проектирования.

Пример 2. basic_string. В стандарте C++ std::basic_string служит таким же пользующимся дурной славой примером проектирования монолитного класса. В этот раздутый до неимоверных размеров класс добавлены все функции, о которых только можно было подумать. Этот класс пытается быть контейнером, что не совсем ему удается; в нем так и остается неразрешенным вопрос между применением итераторов и индексированием. Кроме того, в нем совершенно необоснованно дублируется множество стандартных алгоритмов. В то же время этот класс оставляет очень мало возможностей для расширения. (См. пример к рекомендации 44).



 
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru