Технологии программирования
Шрифт:
При разработке системы динамического моделирования необходимо выполнить следующие шаги:
— по объектной модели определяем активные объекты; эти объекты имеют атрибуты с периодически обновляемыми значениями;
— определяем дискретные события; такие события соответствуют дискретным взаимодействиям объекта (например, включение питания) и реализуются как операции объекта;
— определяем непрерывные зависимости (например, зависимости атрибутов от времени), при этом значения таких атрибутов должны периодически обновляться в соответствии с зависимостью;
— моделирование управляется объектами, отслеживающими
Разработка системы реального времени аналогична разработке системы с интерактивным интерфейсом.
При разработке системы управления транзакциями необходимо выполнить следующие шаги:
— отобразить объектную модель на базу данных;
— определить асинхронно работающие устройства и ресурсы с асинхронным доступом; в случае необходимости определить новые классы;
— определить набор ресурсов (в том числе структур данных), к которым необходим доступ во время транзакции (участники транзакции);
— разработать параллельное управление транзакциями; системе может понадобиться несколько раз повторить неудачную транзакцию, прежде чем выдать отказ.
8.14. ГИБРИДНЫЕ ТЕХНОЛОГИИ ПРОЕКТИРОВАНИЯ
Процедурно-ориентированный и объектно-ориентированный подходы к программированию различаются по своей сути и обычно ведут к совершенно разным решениям одной задачи. Этот вывод верен как для стадии реализации, так и для стадии проектирования: вы концентрируете внимание или на предпринимаемых действиях, или на представляемых сущностях, но не на том и другом одновременно.
Тогда почему метод объектно-ориентированного проектирования предпочтительнее метода функциональной декомпозиции? Главная причина в том, что функциональная декомпозиция не дает достаточной абстракции данных. А отсюда уже следует, что проект будет менее податливым к изменениям; менее приспособленным для использования различных вспомогательных средств; менее пригодным для параллельного развития; менее пригодным для параллельного выполнения.
Дело в том, что функциональная декомпозиция вынуждает объявлять "важные" данные глобальными, поскольку если система структурирована как дерево функций, всякое данное, доступное двум функциям, должно быть глобальным по отношению к ним. Это приводит к тому, что "важные" данные "всплывают" к вершине дерева по мере того, как все большее число функций требует доступа к ним.
В точности так же происходит в случае иерархии классов с одним корнем, когда "важные" данные всплывают по направлению к базовому классу (рис. 8.16).
Рис. 8.16. Игнорирование классов и их наследования
Рассмотрим второй вариант — проект, который игнорирует наследование. Считать наследование всего лишь деталью реализации — значит игнорировать иерархию классов, которая может непосредственно моделировать отношения между понятиями в области приложения. Такие отношения должны быть явно выражены в проекте, чтобы дать возможность разработчику продумать их.
Таким образом, политика "никакого наследования" приведет лишь к тому, что в системе будет отсутствовать
Рассмотрим третий вариант, относящийся к проекту, в котором игнорируется статический контроль типов. Распространенные доводы в пользу отказа на стадии проектирования от статического контроля типов сводятся к тому, что "типы — это продукт языков программирования" или что "более естественно рассуждать об объектах, не заботясь о типах", или "статический контроль типов вынуждает нас думать о реализации на слишком раннем этапе". Такой подход вполне допустим до тех пор, пока он работает и не приносит вреда.
Рассмотрим следующую аналогию: в физическом мире мы постоянно соединяем различные устройства, и существует кажущееся бесконечным число стандартов на соединения. Главная особенность этих соединений — они специально спроектированы таким образом, чтобы сделать невозможным соединение двух устройств, не рассчитанных на него, т. е. соединение должно быть сделано единственным правильным способом. Вы не можете подсоединить радиотрансляционный приемник к розетке с высоким напряжением. Если бы вы смогли сделать это, то сожгли бы приемник или сгорели сами.
Здесь практически прямая аналогия: статический контроль типов эквивалентен совместимости на уровне соединения, а динамические проверки соответствуют защите или адаптации в цепи. Результатом неудачного контроля как в физическом, так и в программном мире будет серьезный ущерб. В больших системах используются оба вида контроля (рис. 8.17).
На раннем этапе проектирования вполне достаточно простого утверждения:
Рис. 8.17. Игнорирование статического контроля типов
"Эти два устройства необходимо соединить", но скоро становится существенным, как именно следует их соединить: "Какие гарантии дает соединение относительно поведения устройств?" или "Возникновение каких ошибочных ситуаций возможно?", или "Какова приблизительная цена такого соединения?"
Переход на новые методы работы может быть мучителен для любой организации. Поскольку в объектно-ориентированных языках возможны несколько схем программирования, язык допускает постепенный переход на него, используя следующие преимущества такого перехода:
1) изучая объектно-ориентированное проектирование, программисты могут продолжать работать по технологии структурного программирования;
2) в окружении, бедном на программные средства, использование объектно-ориентированных языков может принести значительные выгоды.
Рис. 8.18. Гибридный проект
Идея постепенного, пошагового овладения объектно-ориентированными языками и технологий их применения, а также возможность смешения объектно-ориентированного кода с кодом структурного программирования естественно приводит к проекту, имеющему гибридный стиль. Большинство интерфейсов можно пока оставить на процедурном уровне, поскольку что-либо более сложное не принесет немедленного выигрыша (рис. 8.18).