|
Каковы самые общие цели проектирования? Конечно, простота, но в чем
критерий простоты? Поскольку мы считаем, что проект должен развиваться
во времени, т.е. система будет расширяться, переноситься,
настраиваться и, вообще, изменяться массой способов, которые невозможно
предусмотреть, необходимо стремиться к такой системе проектирования
и реализации, которая была бы простой с учетом, что она будет
меняться многими способами. На самом деле, практично допустить,
что сами требования к системе будут меняться неоднократно за период
от начального проекта до выдачи первой версии системы.
Вывод таков: система должна проектироваться максимально простой
при условии, что она будет подвергаться серии изменений. Мы должны
проектировать в расчете на изменения, т.е. стремиться к
Лучшее решение - выделить части системы, которые вероятнее всего будут
меняться, в самостоятельные единицы, и предоставить программисту или
разработчику гибкие возможности для модификаций таких единиц. Это
можно сделать, если выделить ключевые для данной задачи понятия
и предоставить класс, отвечающий за всю информацию, связанную с
отдельным понятием (и только с ним). Тогда изменение будет затрагивать
только определенный класс. Естественно, такой идеальный способ
гораздо легче описать, чем воплотить.
Рассмотрим пример: в задаче моделирования метеорологических
объектов нужно представить дождевое облако. Как это сделать?
У нас нет общего метода изображения облака, поскольку его вид зависит
от внутреннего состояния облака, а оно может быть задано только
самим облаком.
Первое решение: пусть облако изображает себя само. Оно подходит
для многих ограниченных приложений. Но оно не является достаточно
общим, поскольку существует много способов представления облака:
детальная картина, набросок очертаний, пиктограмма, карта и т.п.
Другими словами, вид облака определяется как им самим, так и его
окружением.
Второе решение заключается в том, чтобы предоставить самому облаку
для его изображения сведения о его окружении. Оно годится для
большего числа случаев. Однако и это не общее решение. Если мы
предоставляем облаку сведения об его окружении, то нарушаем основной
постулат, который требует, чтобы класс отвечал только за одно
понятие, и каждое понятие воплощалось определенным классом.
Может оказаться невозможным предложить согласованное определение
"окружения облака", поскольку, вообще говоря, как выглядит облако
зависит от самого облака и наблюдателя. Чем представляется облако
мне, сильно зависит от того, как я смотрю на него: невооруженным
глазом, с помощью поляризационного фильтра, с помощью метеорадара и т.д.
Помимо наблюдателя и облака следует учитывать и "общий фон", например,
относительное положение солнца. К дальнейшему усложнению картины
приводит добавление новых объектов типа других облаков, самолетов.
Чтобы сделать задачу разработчика практически неразрешимой, можно
добавить возможность одновременного существования нескольких
наблюдателей.
Третье решение состоит в том, чтобы облако, а также и другие
объекты, например, самолеты или солнце, сами описывали себя по
отношению к наблюдателю. Такой подход обладает достаточной
общностью, чтобы удовлетворить большинство запросов+. Однако,
он может привести к значительному усложнению и большим накладным
расходам при выполнении. Как, например, добиться того, чтобы
наблюдатель понимал описания, произведенные облаком или другими
объектами?
+ Даже эта модель будет, по всей видимости, не достаточной для таких
предельных случаев, как графика с высокой степенью разрешимости.
Я думаю, что для получения очень детальной картины нужен другой
уровень абстракции.
Дождевые облака - это не тот объект, который часто встретишь
в программах, но объекты, участвующие в различных операциях ввода
и вывода, встречаются часто. Поэтому можно считать пример с облаком
пригодным для программирования вообще и для разработки библиотек
в частности. Логически схожий пример в С++ представляют манипуляторы,
которые используются для форматирования вывода в потоковом
вводе-выводе ($$10.4.2). Заметим, что третье решение не есть "верное
решение", это просто более общее решение. Разработчик должен
сбалансировать различные требования системы, чтобы найти уровень
общности и абстракции, пригодный для данной задачи в данной области.
Золотое правило: для программы с долгим сроком жизни правильным
будет самый общий уровень абстракции, который вам еще понятен и
который вы можете себе позволить, но не обязательно абсолютно
общий. Обобщение, выходящее за пределы данного проекта и
понятия людей, в нем участвующих, может принести вред, т.е.
привести к задержкам, неприемлемым характеристикам, неуправляемым
проектам и просто к провалу.
Чтобы использование указанных методов было экономично и
поддавалось управлению, проектирование и управление должно
учитывать повторное использование, о чем говорится в $$11.4.1 и
не следует совсем забывать об эффективности (см. $$11.3.7).