Чтение онлайн

ЖАНРЫ

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

pCar->Release;

 }

 pAntique->Release;

}

Заметьте, что, если понадобится изменить тип pAntique, в первом листинге придется менять и IID, а во втором все произойдет автоматически, так как оператор __uuidof всегда получает нужный IID отталкиваясь от pAntique.

Более того, если воспользоваться возможностями самого C++, можно создать универсальные классы-обертки, еще более упрощающие жизнь программиста. Так при использовании CComPtr или поддержки COM компилятором (compiler COM support) можно написать примерно такой код:

CComPtr<IAntique> spIAntique;

HRESULT hr = spIAntique.CoCreateInstance(__uuidof(Pinto));

if (SUCCEEDED(hr)) {

 CComQIPtr<ICar> spICar(spIAntique);

 if (spIUnknown) hr = spICar->AvoidFuelTankCollision;

 if (SUCCEEDED(hr)) hr = spIAntique->Appreciate;

}

Хотя этот код, несомненно, проще и безопаснее, он все же далек от

идеала, причем как с точки зрения простоты и читабельности, так и с точки зрения типобезопасности. Ведь только во время исполнения программы будет точно известно, реализует объект эти интерфейсы или нет. Несмотря на использование __uuidof, чтобы заставить COM работать с C++, нужно отключить систему проверки типов C++ на время трансляции объектных ссылок COM в C++-типы. В отличие от этого, интеграция COM с виртуальной машиной Java Microsoft позволяет написать следующее:

IAntique antique = new Pinto;

ICar car = (ICar)antique;

car.AvoidFuelTankCollision;

antique.Appreciate;

Заметьте, что этот код наиболее близок к чистому коду на C++, разве что объект создается динамически, но компоненты и нельзя создавать на стеке.

Это пример, как и самый первый, загружает компонент на основании его типа, а не имени файла. Оба примера разрешают точки входа в компонент, используя средства приведения типов, а не символьные точки входа. Первое различие – Microsoft VM for Java выполняет огромную работу по состыковке системы типов Java с системой типов COM, и программистам не приходится делать этого вручную. Это и есть движущая сила для новой платформы – обеспечить универсальную среду исполнения компонентов, которой сможет воспользоваться любой компилятор, средство или служба. Новая среда – это и есть CLR!

А теперь взгляните на то, как выглядел аналогичный код в VB 6:

Dim thePinto as new Pinto, antique as IAntique

Set antique = thePinto

Dim car as ICar

Set car = antique

car.AvoidFuelTankCollision

antique.Appreciate

Сравните этот код с Java-кодом. На первый взгляд они идентичны, но не спешите делать окончательные выводы. Заметьте, что оператор Set в VB 6 кардинально отличается от приведения типов в Java. По сути Set аналогичен вызову QueryInterface (QI). Результат выполнения QI будет известен только на этапе выполнения, а приведение типа к базовому классу (интерфейсу) можно проверить еще на стадии компиляции.

Типобезопасность – это еще один постулат CLR.

Итак, CLR – это рантайм-среда, призванная упростить и обезопасить работу с компонентами для любого совместимого с ней средства или языка. Замечательно, скажете вы, но зачем же было ломать все и вся? Не лучше ли было подправить спецификацию COM, уточнить требования, предъявляемые к языкам программирования, ведь, например, VB совсем чуть-чуть не удовлетворяет этим требованиям? Это была бы, хотя и бурная, но эволюция. А так снова революция с неизбежным разрушением всего старого и с еще более неизбежной "наклепкой" всего нового. Причем это новое – не маленькая фитюлька, а то самое ВСЁ. На этот вопрос можно ответить, если задаться вопросом: а что, собственно, надо Microsoft? Постепенно улучшая свое программное обеспечение, с каждой новой версией доводить его до совершенства, тем самым поддерживать своих пользователей и зарабатывать уважение. Уважение?! А зачем оно Microsoft? Естественно, Microsoft жаждет не уважения, а господства, полного захвата рынка. Причем эти планы должны выполняться в среде открытой, практически честной конкуренции, где Microsoft может полагаться только на деньги, решительность и напористость.

При таком раскладе эволюция смерти подобна. Надо ломать при малейшем подозрении на несоответствие высоким идеалам, и строить заново. А уж если строить, то, конечно же, новый мир.

Есть и другое объяснения того, почему Microsoft так решительно отвергла все свои наработки и взялась за новую лучшую концепцию. Лучше всего эту версию изложил Ron Burk из WDJ. Вот его версия:

История программных революций от Microsoft, вкратце: Сначала были Windows API и DLL Hell. Революцией №1 было DDE – помните, как ссылки позволили нам создавать статусные строки, отражающие текущую цену акций Microsoft? Примерно тогда же Microsoft создала ресурс VERSION INFO, исключающий DLL Hell. Но другая группа в Microsoft нашла в DDE фатальный недостаток – его писали не они!

Для решения этой проблемы они создали OLE (похожее на DDE, но другое), и я наивно вспоминаю докладчика на Microsoft-овской конференции, говорящего, что скоро Windows API перепишут как OLE API, и каждый элемент на экране будет ОСХ-ом. В OLE появились интерфейсы, исключающие DLL Hell. Помните болезнь с названием "по месту", при которой мы мечтали встроить все свои приложения в один (возможно, очень большой) документ Word? Где-то в то же время Microsoft уверовала в религию C++, возникла MFC решившая все наши проблемы еще раз.

Но OLE не собиралась, сложа руки смотреть на это, поэтому оно заново родилось под именем COM, и мы внезапно поняли, что OLE (или это было DDE?) будет всегда – и даже включает тщательно разработанную систему версий компонентов, исключающую DLL Hell. В это время группа отступников внутри Microsoft обнаружила в MFC фатальный недостаток – его писали не они! Они немедленно исправили этот недочет, создав ATL, который как MFC, но другой, и попытались спрятать все замечательные вещи, которым так упорно старалась обучить нас группа COM. Это заставило группу COM (или это было OLE?) переименоваться в ActiveX и выпустить около тонны новых интерфейсов (включая интерфейсы контроля версий, исключающие DLL Hell), а заодно возможность сделать весь код загружаемым через броузеры, прямо вместе с определяемыми пользователем вирусами (назло этим гадам из ATL!).

Группа операционных систем громким криком, как забытый средний ребенок, потребовала внимания, сказав, что нам следует готовиться к Cairo, некой таинственной хреновине, которую никогда не могли даже толком описать, не то, что выпустить. К их чести, следует сказать, что они не представляли концепции "System File Protection", исключающей DLL Hell.

Но тут некая группа в Microsoft нашла фатальный недостаток в Java – её писали не они! Это было исправлено созданием то ли J, то ли Jole, а может, и ActiveJ (если честно, я просто не помню), точно такого же как Java, но другого. Это было круто, но Sun засудило Microsoft по какому-то дряхлому закону. Это была явная попытка задушить право Microsoft выпускать такие же продукты, как у других, но другие.

Помните менеджера по J/Jole/ActiveJ, стучащего по столу туфлей и говорящего, что Microsoft никогда не бросит этот продукт? Глупец! Все это означало только одно – недостаток внимания к группе ActiveX (или это был COM?). Эта невероятно жизнерадостная толпа вернулась с COM+ и MTS наперевес (может, это стоило назвать ActiveX+?). Непонятно почему к MTS не приставили COM или Active или X или + – они меня просто потрясли этим! Они также грозились добавить + ко всем модным тогда выражениям. Примерно тогда же кое-кто начал вопить про Windows DNA (почему не DINA) и "Windows Washboard", и вопил некоторое время, но все это почило раньше, чем все поняли, что это было.

К этому моменту Microsoft уже несколько лет с нарастающей тревогой наблюдала за интернет. Недавно они пришли к пониманию, что у Интернет есть фатальный недостаток: ну, вы поняли. И это приводит нас к текущему моменту и технологии .NET (произносится как "doughnut" (пончик по-нашему), но по-другому), похожей на Интернет, но с большим количеством пресс-релизов. Главное, что нужно очень четко понимать – .NET исключает DLL Hell.

В .NET входит новый язык, C#, (выясняется, что в Active++ Jspresso был фатальный недостаток, от которого он и помер). .NET включает виртуальную машину, которую будут использовать все языки (видимо, из-за фатальных недостатков в процессорах Интел). .NET включает единую систему защиты (есть все-таки фатальный недостаток в хранении паролей не на серверах Microsoft). Реально проще перечислить вещи, которых .NET не включает. .NET наверняка революционно изменит Windows-программирование… примерно на год.

Еще одну версию причин ломки старого можно прочесть в статье про C#.

Ну да ладно, давайте попробуем разобраться, чем же так хороша новая концепция, что из-за нее бросаются все прошлые наработки.

Новаторства CLR

CLR – новая реализация идей, впервые в общедоступной форме изложенных в модели программирования COM. В CLR программисты загружают компоненты по типу, а не имени файла; разрешают точки входа, используя операции приведения типов, а не символьные точки входа. Модель программирования CLR в фундаментальном отношении не отличается от модели программирования COM. Итак, если модель программирования CLR так похожа модель программирования COM, зачем она вообще нужна? Ответ лежит в реализации.

По мнению группы разработчиков CLR из Microsoft, корень всех проблем кроется в эволюции информации о типах COM. Первые COM– интерфейсы вообще не имели универсального описания. Потом ввели IDL. Он был предназначен для генерации proxy/stub-DLL, которая, в свою очередь, использовалась dk вызовов методов интерфейсов между процессами или удаленными компьютерами.

Параллельно развивалась ветка VB, в которой появились бинарные описания компонентов под названием OLB (Object Library). Впоследствии OLB превратились в TLB (Type Library) но сути своей от этого не поменяли. Сначала в TLB-описаниях можно было использовать только очень ограниченный набор подтипов, что не давало применять их как единый стандарт описания компонентов. Так что существовало три вида описания типов: IDL, библиотеки типов и генерируемые MIDL /Oicf-строки, вставляемые внутрь proxy/stub-DLL. Ни один из этих трех форматов не стал абсолютным стандартом, и в одном формате можно записать информацию, которую невозможно представить в двух других. Это усложняло жизнь как разработчикам инфраструктуры COM, так и обычным программистам, создающим приложения из компонентов. Со временем библиотеки типов стали стандартом де-факто, но возможность обходиться без них, а иногда и вообще обходиться без описания типов, создавала некоторую неопределенность. Так, описание большинства низкоуровневых интерфейсов доступно только в виде заголовочных файлов C++, и, значит, недоступно для разработчиков, использующих более высокоуровневые языки типа VB или Java (например, OLE 2 API, или OLE DB API).

К тому же библиотеки типов COM описывают только типы, экспортированные из компонента. Информация об экспортированных типах позволяет средствам, работающим с COM, реализовать возможности наподобие IntelliSense в Visual Basic или декларативной архитектуры сервисов COM+. Это замечательно, но, по мнению господ из Microsoft, этого недостаточно. В COM не было возможности определить, от каких внешних компонентов зависит компонент. В то время как COM здорово поработал, чтобы сделать dumpbin.exe /exports устаревшим, он ничего не сделал, чтобы заменить dumpbin.exe /imports. Отсутствие информации о зависимостях затрудняет верное определение состава DLL (и их версий), необходимых для нормальной работы компонента.

Вот если бы хранить в библиотеке типов не только информацию об экспортированных вовне типах, а еще и обо всех (в том числе внешних) остальных типах, используемых в библиотеке… Тогда можно было бы точно определять список компонентов, а через них и библиотек, от которых зависит наша библиотека. К тому же это сделало бы возможным создание ряда сервисов, например, автоматической сериализации, отслеживания графа объекта, или автоматического принятия пре– и пост-условий. Большинство разработчиков, использующих COM в своей работе, давно хотели иметь полную информацию о типах. Все эти возможности заложены в CLR.

Главное достоинство CLR – всепроникающая, расширяемая, качественная информация о типах. В CLR все типы – а не только экспортированные из компонента – имеют runtime-описания типов. В CLR вы можете перейти к любому объекту и исследовать каждый аспект его определения типов, включая его представление. Это фундаментальный отход от классического COM, где открытые (public) интерфейсы были доступны, но представление объекта было скрыто.

Но вы можете заметить, что многие языки программирования имеют свою, встроенную информацию о типах. Правильно, но в большинстве случаев, это информация времени компиляции. Она недоступна, если объект не загружен, или извне этого объекта. К тому же нет единого стандарта информации о типах для языков программирования. CLR и является таким универсальным и переносимым между языками стандартом, предоставляющим информацию о типах в любой момент времени, вне зависимости от того, загружен объект в данный момент или нет.

Поделиться с друзьями: