Программирование на Visual C++. Архив рассылки
Шрифт:
Заметьте, что, если понадобится изменить тип pAntique, в первом листинге придется менять и IID, а во втором все произойдет автоматически, так как оператор __uuidof всегда получает нужный IID отталкиваясь от pAntique.
Более того, если воспользоваться возможностями самого C++, можно создать универсальные классы-обертки, еще более упрощающие жизнь программиста. Так при использовании CComPtr или поддержки COM компилятором (compiler COM support) можно написать примерно такой код:
Хотя
Заметьте, что этот код наиболее близок к чистому коду на C++, разве что объект создается динамически, но компоненты и нельзя создавать на стеке.
Это пример, как и самый первый, загружает компонент на основании его типа, а не имени файла. Оба примера разрешают точки входа в компонент, используя средства приведения типов, а не символьные точки входа. Первое различие – Microsoft VM for Java выполняет огромную работу по состыковке системы типов Java с системой типов COM, и программистам не приходится делать этого вручную. Это и есть движущая сила для новой платформы – обеспечить универсальную среду исполнения компонентов, которой сможет воспользоваться любой компилятор, средство или служба. Новая среда – это и есть CLR!
А теперь взгляните на то, как выглядел аналогичный код в VB 6:
Сравните этот код с 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),
Группа операционных систем громким криком, как забытый средний ребенок, потребовала внимания, сказав, что нам следует готовиться к 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 – новая реализация идей, впервые в общедоступной форме изложенных в модели программирования 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.