1. СОМ как улучшенный C++
template <class Т, class Ex>
class list_t : virtual protected CPrivateAlloc {
list<T**> m_list;
mutable TWnd m_wnd;
virtual ~list_t(void);
protected:
explicit list_t(int nElems, ...);
inline operator unsigned int *(void) const
{ return reinterpret_cast <int*>(this) ; }
template <class X> void clear(X& rx) const throw(Ex);
};
Аноним, 1996
C++ уже давно с нами. Сообщество программистов на C++ весьма обширно,
и большинство из них хорошо знают о западнях и подводных камнях языка.
Язык C++ был создан высоко квалифицированной командой разработчиков, которые,
работая в Bell Laboratories, выпустили не только первый программный продукт
C++ (CFRONT), но и опубликовали много конструктивных работ о C++. Большинство
правил языка C++ было опубликовано в конце 1980-х и начале 1990-х годов.
В этот период многие разработчики C++ (включая авторов практически каждой
значительной книги по C++) работали на рабочих станциях UNIX и создавали
довольно монолитные приложения, использующие технологию компиляции и компоновки
того времени. Ясно, что среда, в которой работало это поколение программистов,
была в основном создана умами всего сообщества C++.
Одной из главных целей языка C++ являлось позволить программистам строить
типы, определенные пользователем (user-defined types - UDTs), которые
затем можно было бы использовать вне их исходного контекста. Этот принцип
лег в основу идеи создания библиотек классов, или структур, какими мы
знаем их сегодня. С момента появления C++ рынок библиотек классов C++
расширялся, хотя и довольно медленно. Одной из причин того. что этот рынок
рос не так быстро, как можно было ожидать, был NIH-фактор (not invented
here - <изобретен не здесь>) среди разработчиков C++. Использовать код
других разработчиков часто представляется более трудным, чем воспроизведение
собственных наработок. Иногда это представление базируется исключительно
на высокомерии разработчика. В других случаях сопротивление использованию
чужого кода проистекает из неизбежности дополнительного умственного усилия,
необходимого для понимания чужой идеологии и стиля программирования. Это
особенно верно для библиотек-оберток (wrappers), когда необходимо понять
не только технологию того, что упаковано, но и дополнительные абстракции,
добавленные самой библиотекой.
Другая проблема: многие библиотеки составлены с расчетом на то, что
пользователь будет обращаться к исходному коду данной библиотеки как к
эталону. Такое повторное использование <белого ящика> часто приводит к
огромному количеству связей между программой клиента и библиотекой классов,
что с течением времени усиливает неустойчивость всей программы. Эффект
чрезмерной связи ослабляет модульный принцип библиотеки классов и усложняет
адаптацию к изменениям в реализации основной библиотеки. Это побуждает
пользователей относиться к библиотеке как всего лишь к одной из частей
исходного кода проекта, а не как к модулю повторного использования. Действительно,
разработчики фактически подгоняют коммерческие библиотеки классов под
собственные нужды, выпуская <собственную версию>, которая лучше приспособлена
к данному программному продукту, но уже не является оригинальной библиотекой.
Повторное использование (reuse) кода всегда было одной из классических
мотиваций объектного ориентирования. Несмотря на это обстоятельство, написание
классов C++, простых для повторного использования, довольно затруднительно.
Помимо таких препятствий для повторного использования, как этап проектирования
(design-time) и этап разработки (development-time),
которые уже можно считать частью культуры C++, существует и довольно большое
число препятствий на этапе выполнения (runtime), что делает объектную
модель C++ далекой от идеала для создания программных продуктов повторного
использования. Многие из этих препятствий обусловлены моделями компиляции
и компоновки, принятой в C++. Данная глава будет посвящена техническим
проблемам приведения классов C++ к виду компонентов повторного использования.
Все задачи будут решаться методами программирования, которые базируются
на готовых общедоступных (off-the-shelf) технологиях. В этой главе будет
показано, как, применяя эти технологии, можно создать архитектуру для
повторного использования модулей, которая позволяла бы динамично и эффективно
строить системы из независимо сконструированных двоичных компонентов.
Распространение программного обеспечения и язык С++
Динамическая компоновка и С++
C++ и мобильность
Инкапсуляция и С++
Отделение интерфейса от реализации
Абстрактные базы как двоичные интерфейсы
Полиморфизм на этапе выполнения
Расширяемость объекта
Управление ресурсами
Где мы находимся?
|