воскресенье, апреля 08, 2007

Распространение приложений и .NET

Много лет назад все уши были прожужжаны рассказами о том, как приятно, чертовски приятно, будет работать с разными версиями библиотек в .NET. В пример, понятно, приводились, библиотеки COM, в которых не покладающие рук программисты легко изменяли функциональность хорошо известных снаружи классов. Мало приятного, если старый код начинает работать по-новому или вообще перестаёт делать нечто ожидаемое, не спорю. Но так ли сильно .NET помогает в решении этой проблемы?

GAC, копирование собственной версии в собственный же каталог - это всё понятно. Номинально (именно номинально) это закрывает проблему. А на самом деле? Новые средства среды и языка дают и новые возможности что-то сделать не так. Например. Библиотека А и библиотека Б. Обе используют класс, объявленный в библиотеке В. Причё используют его на разделяемой основе: типа, сначала первая что-то сделала полезного, потом другая с тем же экземпляром. Плюс к этому - одна другую грузит, например, динамически. При этом в случае А - В идёт в одном с ней каталоге, а в случае Б - в GAC. Пока библиотеки В одинаковы всё будет хорошо. Но если нет? Заметьте, что какой-нибудь видный деятель может с лёгкостию неимоверной просто не поменять версию В при внесении изменений в неё. Я не завидую тому, кто решит понять, в чём же дело в данном конкретном случае. Есть ли в этом случае упрощение развёртывания? Не сказал бы. Особенно в средах, в которых администратор занимается запуском с колёс: разворачивает все присылаемые ему инсталляции в разные каталоги (на всякий случай) и начинает химичить (у нас было так). Пример из жизни: в позапрошлую пятницу репликация была настроена и запущена. В понедельник с утра дёргают: ничего не работает. Суббота и воскресенье - дни нерабочие. Проблема была в том, что в понедельник с утра администратор получил новую версию основной системы, установил, чем-то там она ему не понравилась (да, имеет такие полномочия!) и он её снёс. А библиотека Икс имела старый номер версии и установилась в GAC поверх старой. Репликатор же для ряда задач использует Reflection. Результатом является ошибка вот такого вида:

Unhandled Exception: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. at System.Reflection.Module.GetTypesInternal(StackCrawlMark& stackMark) at System.Reflection.Assembly.GetTypes()

Есть идеи почему так? Вот то-то же. На ровном месте падало, совершенно неожиданно, где просто не могло. А вот поди ж.

Так что нету нигде никакой простоты, в маркетинговых материалах разве что...

Комментариев нет: