Здравствуйте, Sinclair, Вы писали:
S>Ну, мы же люди взрослые. Понимаем, что в управляемой среде такие трюки запрещены. Как и reinterpret_cast вместе со static_cast.
Ксожалени, нет. Такую проверку можно вставить только в компилятор. Остальные на нее будут чиахать, так как даже приметива такого нет.
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ксожалени, нет. Такую проверку можно вставить только в компилятор. Остальные на нее будут чиахать, так как даже приметива такого нет.
Вот именно! Я и говорю — НАДО ЕГО ВНЕСТИ В .NET. Вы что думаете, я не заметил, что его там нет? Более того, я заметил, что custom attribute такой не будет иметь никакой ценности, пока за ним не следит компилятор.
... << RSDN@Home 1.1 alpha 1 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>"А баба Яга — против!" (c) Мультик. Извини, просто ты так эмоционально реагируешь.
С чего ты взял?
ГВ>>>А что ты будешь делать, если для некоего нового типа данных ещё нет обработчика среди дополнительных сборок? AVK>>Напишу и скомпиляю в отдельную сборку.
ГВ>И что? Где же помощь reflection?
Помощь рефлекшена в том что мне не надо пересобирать старый проект. Более того — если источник данных и их потребитель это отдельные продукты, то мне достаточно только обновить источник данных и предоставить необходимые конверторы, не трогая потребителя совершенно.
ГВ>Только в том, что ты выполнишь вместо подстановки средствами механизма виртуальных функций подстановку средствам атрибутов? Т.е., грубо говоря, слоты размещаются не в VMT, а в атрибутах.
Рефлекшен гибче полиморфизма и предоставляет больше возможностей меньшими усилиями. Кроме того рефлекшен не требует наследования от какого то класса, а иногда это заметно удобнее.
ГВ>Обязанность по поддержанию адекватного набора конвертеров по прежнему лежит на программисте. С той лишь разницей, что для .Net он будет делать сборки, а на C++ скорее всего, — .dll или Shared Objects.
Разница только в одном — в отсутствие рефлекшена все это ты можешь осуществить только внутри своего продукта. Как только часть цепочки оказывается ввиде бинарного модуля без исходников то сразу все становится много печальнее.
ГВ>>>OK, я тебя понял. И то, к чему ты упомянул про дополнительные сборки в каталогах программы — тоже. И сразу хочу задать встречный вопрос. А кто напишет для моей программы нужные именно ей конвертеры? Предположим, что речь идёт не о банльной конвертации в строковое представление, а например, в хливких шорьков, метОда использования которых известна только мне. Я позволю себе задать этот вопрос, поскольку спор начинался с общих фраз.
AVK>>Это уже совсем другой вопрос.
ГВ>Да нет, в том-то и дело, что это две стороны одно и того же вопроса.
Не надо перескакивать на другие темы, если нет больше аргументов так и скажи что был не прав.
AVK>>Главное что при добавлении новых типов старый код менять не нужно. Это уменьшает количество работы и гарантирует от глюков, связанных с тем что ты поменял тип, но забыл поменять его мап.
ГВ>При такой ситуации (необрабатываемые данные во внешнем источнике данных) — всегда возможны глюки, а вернее — runtime-ошибки.
Если все поведение системы определяется в одном месте их вероятность значительно меньше. Как например ты напишешь на плюсах систему конфигурирования, так чтобы для внесения новой переменной в конфигурацию нужно было бы всего лишь добавить поле в класс, ее содержащий, так чтобы все остальное — механика сохранения/загрузки, пользовательский интерфейс и прочая адаптировались под изменения автоматически? А при помощим рефлекшена это возможно, и оно, помимо снижения объема работы срахует от ошибок, в том числе и в рантайме просто потому что их негде сделать, изменения требуют от тебя чисто декларативных действий и никакой правки алгоритмов.
ГВ>И где я говорил, что новые конвертеры, обрабатывающие сигнатуры новых типов данных источника не могут подгружаться? В default-ветке switch-а вполне может стоять что-то вроде:
ГВ>
ГВ>где и будет выполняться поиск по map, если заранее предусмотренного конвертера нет. А map будет заполняться библиотеками драйверов.
Неужели сам не видишь насколько все получается более громоздким? В дотнете для поддержки нового типа я напишу так:
[ConvertType("SomeType")]
class SomeTypeConverter : TypeConverter
{
public override Convert() {...}
}
Скомпилирую в отдельную сборку и положу в каталог приложения. Все. Никаких мапов, свитчей и прочей пурги не надо. И неважно что где то внутри их видимо будет похожая механика — главное что это будет происходить автоматически. Мне не надо ничего править, дописывать где то мапы, менять свитчи и прочее, мне не надо даже управляющий код пересобирать. Весь остальной код подстроится автоматом. И вот это прелести решения на шаблонах лишены, для них необходим исходный код и полная пересборка всех задействованных алгоритмов, не говоря уж о необходимости ручной регистрации типов в кеше и правки этой регистрации при каждом(!) изменении конвертеров. И это если не вспоминать о раздувании кода и жутко медленной компиляции.
ГВ>Кстати, мне немного неясно, что ты имеешь ввиду под словами "поменял тип, но забыл поменять его мап".
То и имею ввиду. Тип добавил (изменил название), а мап нет — в результате глюки.
ГВ>>>1. Программа выдаст пустые строки или сообщение об ошибке в зависимости от контекста. ГВ>>>2. Я разберусь с тем, что происходит и сделаю Upgrade своей проги. AVK>>Причем править придется старый код. А это действительно кривой дизайн.
ГВ>Не факт.
Факт. И очень странно что ты этого не видишь. Раньше в дисскусиях ты высказывал интересные вещи с неплохим подходом к дизайну. Но сейчас, извини за прямоту, явно видно что ты зациклился на технологиях которые хорошо знаешь и упорно не желаешь сойти с наезженной колеи. Поэтому в упор не видишь очевидных вещей — многие задачи, особенно связанные с компонентными и глубоко конфигурируемыми системами решаются на С++ значитьно более сложно и громоздко.
ГВ> Ситуация может потребовать изменения как всей проги, так и только написания для неё дополнительного адаптера/конвертера и т.п. Для твоего случая справедливо то же самое, так что не надо преждевременно обобщать.
Тем не менее, как показывает практика, чаще все таки нужно добавлять функционал, а не перекраивать старый низкоуровневый код. И в таком случае использование плюсов не лучший вариант решения проблемы.
AVK>>Ну уж нет, ты не про rtti-based подход говорил, ты говорил просто про использование rtti.
ГВ>А, ну вот уже лучше, о терминах договариваемся.
Нет уж, цитата благо осталась.
VD>Дык информация о типах нужна то обычно в рантайме, а вот тут у плюсов идеологический калапс. Его авторы просто не думали о рантайме при проектировании языка.
Они сознательно ограничивали его рассмотрение. И ИМХО, совершенно разумно, поскольку необходимость "самоанализа" (он же — rtti) в сущности, является ошибкой дизайна.
Извини, но тут явно и без обиняков сказано — применение rtti является ошибкой дизайна, поэтому рантайм в С++ сознательно такой куцый. Извини, но трактовать твою фразу как то иначе просто не возможно. И тебе на пальцах показали что как раз невозможность применения rtti как раз частенько снижает управляемость и универсальность кода, а значит является ошибкой дизайна.
ГВ>Progress, однако. А то твоя иллюстрация никак не противоречила моим тезисам. Думаю, что это естественно, поскольку "опыт — не пропьёшь". Понимаешь, ты просто привёл пример того же самого правильного LSP-дизайна, только опирающегося на подстановку, выполняемую с помощью атрибутов, а не виртуальными функциями и абстрактными интерфейсами.
Знаешь в чем я с тобой не согласен? В том что реализовать все это добро нужно руками. Это может быть интересно первый, десятый раз. В двадцатый раз это уже вызвает раздражение. И то что в итоге на шарпе я реализую тот же самый дизайн в разы(!) быстрее, более гибко и с меньшим количеством глюков нежели на плюсах низводит все остальные плюсы и минусы в разряд шашечек, и никакие умные книжки ситуацию существенно не изменят.
ГВ> Так что, противоречия, на самом деле — нет. Принципы дизайна остались теми же самыми.
А про принципы никто и не спорит. Вопрос в реализации. А многие паттерны реализуются с использованием рефлекшена в разы проще и быстрее. Та же абстрактная фабрика, где на плюсах никогда не избавится от зависимости фабрики и производимой ею продукции.
ГВ>Ну да, часть задач дотнет берёт на себя, но я это и не собирался опровергать, знаешь, было бы глупо.
А к чему тогда слова о безусловной кривости rtti?
AVK>>Это все понятно. Только вот некривой подход с использованием шаблонов идет лесом, как только оказывается что часть кода недоступна на момент компиляции. Ты привых не использовать компоненты, поэтому тебе кажется что твой подход всегда лучше, а на деле это совсем не так.
ГВ>Причём тут моё наличие или отсутствие привычки использовать компоненты?
При том что ты упорно отказываешься замечать фатальный недостаток плюсовых шаблонов и решений на их основе — шаблоны существуют только в момент компиляции и только внутри проекта.
ГВ>Я привык жёстко организовывать программу,
В этом и проблема. Жестко организованные программы может и уместны там, где нужно достич перформанса любой ценой, но в большинстве случаев это все таки не очень хороший дизайн, существенно снижающий управляемость и масштабируемость проекта.
ГВ> чтобы обеспечивать её надёжность (и скорость).
Скорость возможно, а вот надежность обеспечивается несколько другими способами.
ГВ> Это отнюдь не означает, что в ней мест, где используются компоненты (библиотеки, модули — хоть груздём назови).
Они может и есть, но все твои шаблонные навороты между ними уже не действуют.
AVK>>Вот только компилятор не может гарантировать того чего может не знать.
ГВ>Естественно. И, ИМХО, "правильный" дизайн должен вести к снижению количества подобных ситуаций.
Не обязательно. Это всего лишь залатывание дыр. Существование компонентно ориентированных сред это реальность, данная нам в ощущениях и дизайн тут не при чем. Объективные факторы заставляют делать программы, собирающиеся из набора модулей, а не представляющие собой неделимый и монолитный кусок. Полтора десятка лет развития технологий компонентного программирования ясно показали — они себя оправдали, более того, альтернативы им в настоящий момент нет. И средства разработок, пытающиеся это игнорировать рискуют оказаться никому не нужными. Уже сейчас шарп по количеству вакансий догнал С++, а по количеству новых проектов пожалуй опережает его. А прошло меньше полутора лет с релиза.
ГВ>Просто это повышает надёжность,
Нте, надежности это к сожалению не повышает, более того, из-за практически полного отсуствия каких бы то ни было возможностей контроля кода в рантайме еще ее и снижает. Дотнетный код, благодаря строгому контролю со стороны рантайма значительно надежнее плюсового и это уже доказано практикой. Кошмар ловли ошибок неделями благополучно забыт, за последние полгода в моем коде не было ни одной ошибки, на локализацию которой я потратил больше 10 минут. Не было ни одной ошибки, из-за которой глюки были не в том коде, который непосредственно ошибку содержал. Так что про надежность лучше не стоит.
ГВ> быстродействие и упрощает дальнейшие модификации.
Усложняет дальнейшие модификации. Особенно забавно будет получаться когда проект состоит из нескольких процессов.
ГВ>И потом, как это компилятор может не знать?
А вот так — части кода может просто не существовать, часть кода представляет собой купленные на стороне компоненты, которые в любой момент могут обновиться. Главная особенность компонентной среды — на момент исполнения информация о типах полностью не доступна. Максимум что может быть это некий базовый интерфейс — но как только этого базового интерфейса станет не хватать тебе придется менять и его и все зависимые от него модули. И если эти модули разрабатывали другие люди то необходимость править давно отлаженный и забытый код вызовет массу положительных эмоций в твою сторону.
ГВ>Проблема-то не в обработке внешних данных, где от анализа нельзя избавиться по определению, а в применении RTTI-based дизайна внутри программы. Значение термина "RTTI-based" я объяснял предыдущим постом.
Не пытайся перевести разговор на другое, термин rtti-based изначально не фигурировал, твоя попытка перевести все на обсуждение терминологий выглядит нелепой отмазкой.
Здравствуйте, AndrewVK, Вы писали:
AVK>А про принципы никто и не спорит. Вопрос в реализации. AVK>А многие паттерны реализуются с использованием рефлекшена в разы проще и быстрее.
ну ну AVK>Та же абстрактная фабрика, где на плюсах никогда не избавится от зависимости фабрики и производимой ею продукции.
Не стоит так категорично высказаватся про язык который плохо знаешь. Практика показывает что при помощи rtti и не сложных шаблонов на С++ можно сделать уневерсальную фабрику классов. С учень удобным и дурака-устойчевым интерфейсом. Причем реализации классов могут лежать в разных длл.
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Не стоит так категорично высказаватся про язык который плохо знаешь. Практика показывает что при помощи rtti и не сложных шаблонов на С++ можно сделать уневерсальную фабрику классов. С учень удобным и дурака-устойчевым интерфейсом. Причем реализации классов могут лежать в разных длл.
Вот только такую реализацию непоймет деже другой компилятор С++. О других языках и коворить не приходится. Отсюда и рождаются разные фабрики классов на GUID-ах. Ты Эсеншал КОМ от Дона Бокса читал? Так подробно рассказано почему КОМ написан так как нкписан.
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
AVK>>Та же абстрактная фабрика, где на плюсах никогда не избавится от зависимости фабрики и производимой ею продукции. WH>Не стоит так категорично высказаватся про язык который плохо знаешь. Практика показывает что при помощи rtti и не сложных шаблонов на С++ можно сделать уневерсальную фабрику классов. С учень удобным и дурака-устойчевым интерфейсом. Причем реализации классов могут лежать в разных длл.
Для качественной реализации фабрики необходима возможность поднятия экземпляра по имени класса. Все реализации на основе шаблонов все равно требуют чтобы где нибудь явно прописывали список классов, которые может производить фабрика, а это уже менее качественная реализация.
Здравствуйте, AndrewVK, Вы писали:
AVK>Для качественной реализации фабрики необходима возможность поднятия экземпляра по имени класса.
Есть. AVK>Все реализации на основе шаблонов все равно требуют чтобы где нибудь явно прописывали список классов, которые может производить фабрика, а это уже менее качественная реализация.
Единого списка нет.
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Извини, что долго молчал.
ГВ>>Здесь немного поподробнее, плз. CreateObject<>() как я понял, реализован в exe-шнике. Далее он обращается к конкретному синглтону (например — C_MyCoolSingleton), который создаёт объект Sensor. Ну там понятно: карта, по которой отображается sensorName на конкретный синглтон и т.п. WH>Каждая длл содержит указатель на супер фабрику классов те обьект который содержит карту фабрик. Супер фабрика может возвращать только I_OBject. CreateObject реализован в длл вобще это просто удобный акцессор к супер фабрике со встроенным dynamic_cast
dynamic_cast<> вызывается в CreateObject? Если CreateObject возвращает общий интерфейс I_Object, то зачем в нём dynamic_cast<> ?
ГВ>>Мне просто нужно понять структуру зависимостей модулей. Если вызов dynamic_cast<C_MyCoolSensor> есть в исходниках exe-шника, и других библиотеках, это одно, а если только в библиотеках сенсоров, то — другое. WH>Только в длл ехешник об обьектах ни чего не знает.
OK, значит dynamic_cast<> нужен только для получения частного типа из общего.
ГВ>>Вот тут тоже немного не понятно: указатель на объект, содержащий фабрику классов передаётся в экспортируемую функцию? Логично было бы предположить, что указатель передаётся из неё... WH>Указатель на супер фабрику в длл, указатель на енумератор фабрик из длл. После чего фабрики из енумератора заносятся в карту супер фабрики.
То есть суперфабрика передаётся для саморегистрации библиотеки, а саморегистрация выполняется вызовом енумератора суперфабрикой. OK, для регистрации реализован соответствующий "микроалфавит".
ГВ>>Ещё, ты говорил, что библиотеки содержат формы настройки. Формы просто в виде модальных диалогов или в виде чего-то типа PropertyPage? В смысле — они встраиваются в какой-то оборачивающий диалог или показываются независимо? WH>Да как угодно.
// ... поиск фабрики-синглтона по имени соотв. классаreturn pFactory->Create(); // Возвращён I_Object
Теперь .exe получил в своё распоряжение обобщённый интерфейс I_Object, что-то у него спросил — и сбросил обратно в соответствующую .dll, выбор которой осуществляется примерно тем же способом, что и поиск сигнлтона-фабрики.
Интерфейс .dll, или интерфейс обобщённого синглтона, предоставляемого .dll:
int RunSomeOperation(I_Object*)
Реализация RunSomeOperation() в библиотеке, где "живёт", например TheIBMSensor:
int RunSomeOpertion(IObject *pSensor)
{
TheIBMSensor *pIBMSensor = dynamic_cast<TheIBMSensor*>(pSensor);
if (!pIBMSensor) return error_code_of_invalid_sensor;
// Дальше пошли обращения к pIBMSensor
pIBMSensor -> ...
}
ИМХО, другого обобщенного случая здесь быть не может, поскольку ты утверждаешь, что exe не меняется в зависимости от набора .dll.
---------------
Подтверди, пожалуйста, или опровергни.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
[...]
S>>Извращения — это для тренировки мозгов. После которой простые и эффективные решения будут писаться куда проще и эффективней
VD>Проблема, в том, что С++ заставляет тренеровать могзги вместо выполнения основной рабты.
"Не умом поразить тщился, — с достоинством ответил отец Кин. — ...Умные нам ненадобны. Надобны верные." (А. и Б. Стругацкие, "Трудно быть богом").
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, VladD2, Вы писали:
ГВ>>"моей программы" — имеется ввиду та программа, которую разрабатывает и контролирует конкретный дизайнер. VD>А компонент это тоже "твоя программа"? Или он обязан быть частью дезайрена?
А откуда взялось это противопоставление? Компонент обязан вписываться в дизайн, а не наоборот. Если он не подходит, то нужно вводить дополнительную функциональность или посылать нахрен данный конкретный компонент и заменять его другим, более подходящим. В противном случае архитектура ограничивается используемыми средствами, что не есть good. ИМХО, разумеется
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Геннадий Васильев, Вы писали:
VD>Мне уже достаточно силно надовел этот бесполезный спор. Двай я тебе покажу твой любимый С++ и его "прямой" дизайн в действии, а потом мы сравним это с аналогом на шарпе...
VD>Вот типичный компонент созданный средствами С++ (COM):
[skip — пример класса]
Ну и что ты демонстрируешь этим? То, как чаще всего, вероятно, пишут. ATL — неплохая библиотека, но, ИМХО, главное её достоинство — широкая распространённость. Сам посуди: реализацию QueryInterface можно спАрить с наследованием от заданного интерфейса, объявления элементов — вынести в виртуальные базовые классы и т.п. Другое дело, что ATL написана для VC6, который начинал сходить с ума от сложного наследования, где чередовались шаблоны и виртуальное наследование... так то — проблемы компилятора, альтернативы которому имеются уже достаточно давно.
VD>Надо признаться, что это красивая обертка на атл-е. Без нее код бы занимал бы раз в 10 больше места. VD>И главный метод (QueryInterface) выглядил бы так:
VD>
class ServiceProvider : public BasicCoClassImplement<...>
{
public:
virtual HRESULT GetService(IID* iid, void **ppv)
{
return QIBase::QueryInterface(iid, ppv);
}
}
class CTest : public ServiceProvider, Requestable<ITest1>, Requestable<ITest2>
{
// Рабочие методы ITest1 и ITest2
}
Если заинтересует, расскажу о реализации Requestable и т.п., но суть дела не в этом. Ты демонстрируешь одну и ту же ситуацию — проверку композиции в рантайме.
VD>А вот примеры использования. VD>С++:
VD>
VD>PS
VD>И не надо рассказывать, сказки, что можно вообще избавиться от рантайм проверок. Так как иначе это не будут компоненты (их нелзя будет создавать и использовать в рантайме).
Не путай, пожалуйста, рантайм-проверки результатов операций управления ресурсами и рантайм-проверки типов, т.е. — верификацию композиции. Понятие "компонент", как и "модуль" вовсе не означает необходимости проверок типов.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, VladD2, Вы писали:
ГВ>>Разницу чуешь? VD>Чую, что тебе ненравится, но почему обяснить ты не в силах.
Либо плохо объясняю, либо плохие слушатели.
ГВ>> Это может быть единственным выходом, но я оценивать его всё равно буду негативно (или, если хочешь — с грустью, тоской, щемящим сердцем, великоросской рефлексией, сквозь зелёную бутылку, с поллитрой в руках, скрипя зубами, с самурайским мечом меж зубами, — ряд синонимов можно продолжить), поскольку присущие ему черты неизбежно останутся. VD>Так как ты не докозал, что "присущие черты" плохи. Будет считать это утверждение основанное на небоснованных спорных предпосылках. ОК?
Ну на здоровье, можешь считать, что ненадёжность, обусловленная недостаточной композиционной проработкой, это — хорошо. И ещё с тем, что оверхед, связанный с необходимостью хоть какой-то компенсации этой ненадёжности — это кул. Я разве против? Но я не думаю, что эти факторы имеют преимущественно позитивную оценку у потребителей софта.
ГВ>>Или ты считаешь, что я должен прыгать от счастья, раз мне пришлось воспользоваться этим, единственным выходом? VD>Я считаю, что обчиняя нужно приводить доказательства вины. Хотя бы если об этом попросили несогласные. Или не обвинять.
Абсолютно согласен. Вот и привожу.
ГВ>>Поскольку моя личная негативная оценка не может быть предметом обсуждения VD>А зачем ты ее высказываешь? Раз высказал, значит она уже автоматом может стать предметом...
Личную оценку нет смысла обсуждать, поскольку спор о вкусах легко может превратиться в упражнения по базарному красноречию. А вот объективные характеристики и прочее — обсуждать очень даже интересно. И поводом для их обсуждения как раз может послужить личная оценка. Кстати, не находишь, что здесь появляются очень интересные высказывания?
ГВ>>, в силу субъективизма и возможной неадекватной её трактовки собеседниками то я: а) отказался от такой формулировки, но б) сформулировал описание характерных черт критикуемого мной подхода более точно. VD>И таки так и не дал доказательств своим критическим суждениям.
Доказательство наличия оверхеда
Время исполнения вызова (T) при использовании rtti: Trtti = Ta + Tc, где Ta — время анализа полученного типа, Tc — время собственно вызова.
Время исполнения вызова (T) без использовании rtti, а именно — compile-time type information для статической типизации, ctti: Tctti = Tc, где Tc — время собственно вызова.
Вывод: Trtti > Tctti
Доказательство снижения надёжности композиции
Надёжность композиции — вероятность корректного сочетания типов данных во время выполнения программы.
Оценим надёжность композиции на основе оценки надёжности выполнения вызова метода некоторого интерфейса.
P — вероятность отказа выполнения вызова.
Для случая с использованием rtti
Prtti = Pa + Ps, Pa — вероятность отказа в результате анализа (получены некорректные данные), Ps — вероятность ошибки транслятора.
Учтём, что: 0 < Pa < 1; Ps << 1
Для случая выполнения анализа в compile-time
Pctti = Ps
Дополнительное соображение: величина Pa отражает надёжность выполнения всех алгоритмов, работа которых прямо или косвенно участвует в выполненнии runtime-анализа.
Вывод: D > 1, т.е., использование ctti обеспечивает бОльшую надёжность композиции, чем использование rtti.
ГВ>>Поскольку разработчики C++ (Страуструп, во всяком случае, насколько я это знаю) придерживались схожих взглядов, я счёл возможным в декларативной форме присоединиться к ним. Декларативную же и краткую форму выбрал сознательно, поскольку сообщение написал в форум. VD>Тбе декларативно и заявили, что ты не прав, в месте с Страуструпом. Что ты еще хочешь?
Вот я и доказываю свою правоту.
ГВ>>Ну как, понятно объяснил? Или стрелочки логических связей нарисовать? VD>Такую позицию не стоило и озвучивать. Она ровным чсетом никому ничего не дает.
Не надо за всех расписываться. Дискуссия на самом деле небезынтересная получается.
ГВ>>А относительно "в некоторых не еденственный но намного боле простой"... Так опять ты апеллируешь к тому, что разница простой-сложный настолько велика, что это фактически — единственный выход для которого либо справедливо то, что я уже сказал, либо... несправедливо вообще ничего, поскольку "простой" и "сложный" — тоже субъективные оценки. VD>Твои рассуждения противоречат логике. Любой дизайн тем лучше чем проще и эффективнее он решает поставленную задачу имеющимися средствами. А понятие "криво" является сугубо отнсительным. Так что если решение единственное, то кривым его называть бессмысленно.
Почему? Представь, например, что некто свалился в лужу дерьма. Измазался относительно слабо (во чудо-то!). Выбираться можно только вброд, но измазаться придётся ещё больше. Единственное это решение? Скорее всего — да. Будет он материться по этому поводу? Будет, я думаю.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Доказательство наличия оверхеда ГВ>Время исполнения вызова (T) при использовании rtti: Trtti = Ta + Tc, где Ta — время анализа полученного типа, Tc — время собственно вызова. ГВ>Время исполнения вызова (T) без использовании rtti, а именно — compile-time type information для статической типизации, ctti: Tctti = Tc, где Tc — время собственно вызова.
ГВ>Вывод: Trtti > Tctti
И какое отношение этот вывод имеет к теме? Задачи выполняемые в рантайме, при условии правильного проектирования не могут быть выполнены в компайлтайме. Следователно "Trtti > Tctti" в этом случае пустое сотрясение воздуха.
По отношению к требовательным к скорости участкам кода конечно любая интерпретация — это плохо. Но... 1) в большем коиличестве случаев время затрачивамое на интепретацию не критично (ведь относительно понятий о времени людей эта интерпретация происходит очень быстно), 2) на базе информации о типах можно создавать код (компоненты) и использовать его. Причем код можно создавать как JIT, так и в процессе компиляции.
Таким образом, можно сделать вывод, что при безкрамотном использовании информации о типах можно получить ощутимое снижение производительности. Но при грамотном, все бедет в пордке. Так что меняй катигоричность утверждений. Вводи слово "может".
ГВ>Доказательство снижения надёжности композиции
ГВ>Надёжность композиции — вероятность корректного сочетания типов данных во время выполнения программы.
Не детерминированы "композиция" и "корректное сочетание типов". Да и вообще утверждение выглядит спорно. Так что эго мы отбрасывам до уточнения.
ГВ>Оценим надёжность композиции на основе оценки надёжности выполнения вызова метода некоторого интерфейса.
Дальще идут какие-то цыфры взятые с потолка и замалчивание реальной правды. Так что я пропущу все эти бессмысленные рассуждения и отвечу просто на вывод...
ГВ>Вывод: D > 1, т.е., использование ctti обеспечивает бОльшую надёжность композиции, чем использование rtti. ГВ>Вот я и доказываю свою правоту.
Попробуем не пудрить себе и другим мозги, а проанализировать, что же конкретно делается с помощью информации о типах и как это можно сделать без нее.
Случай 1. Мы имеем некие компоненты полная информация о которых нам не доступна в компайлтайме. При наличии полноценного TypeInfo (ти), мы можем написать универсальный механизм позволяющий решить поставленную задачу. Без оного мы вынуждены изобрести не универсальный механизм (или универсальный, но это еще сложнее [по закону сохранения энергии]).
Посмотрим минусы прдхода с ти. Собственно их нет. Вернее они могли бы быть если бы метаинформация не позволяла бы нам заложить всю необходимую информацию. Но так как мы предпологаем качественную реализацию ти, то проблем нет. Заметим, что подсистема ти написанна заведомо высококвалифицированными людьми и отлажена (тысячами людей). Заметим так что что нам не потребовалось создавать собственные механизмы и мы смогли больше времени потратить на прикладные алгоритмы, а стало быть лучше их отладить.
Теперь второй случй. Так как всей информации в компайлтайме небыло, идея об генерации кода и компайлтайм-проверках отметается сразу. Нам предстоит написать как средства закладывания метаинформации, так и средства их анализа. Причем анализ производится исключительно в рантайме и использовать компилятор мы не можем. Учитывая, что на реализацию проектов обычно отводится ограниченное время нам придется делить его между рантайм-подсистемой интерпретации, системой генерации и закладывания метаданных и собственно прикладными алгоритмами. Ко всему прибавляется отсуствие человеческого рантайма и идеологии позволяющего предотвращать фатальные ошибки (типа затирания памяти).
Таким образом мы получаем:
1. Велосипедостроение, так как все равно от изобретения своих метаданных никуда не деться.
2. Менее надежный код, так как его стало намного больше, а время на написание и отладку фиксированно.
3. Надежность еще больше уменьшается в следствии того, что рантайм проверки или попросту не делаются, или их создание еще больше усложняет и затягивает написание кода.
4. Резко возврастает требования к квалификации и усилиям программиста, так как увеличивается объем работ и их сложность.
Короче, в случае 1 твои доводы являются чистейшей неправдой.
Случай 2. В условиях задачи есть четкое формальное описание структур данных и алгоритмов их обработки. Эта информация может быть описана в некой форме (например матрицы), но информация может часто меняться, объем информации очень велик, или информация еще не доконца определена в момент кодирования. Решаемая задача может быть выполна методом тупого кодирования. При этом решение задачи можно облегчтить макросами и шаблонами. Но задача так же решается путем создания интерпретатора (или кодогенератора) анализирующего ти.
Если задача легко формализуется шаблонами/макросами, то спору нет. Их применение будет лучшим выбором. Но если создаваемые алгоритмы тяжело описать статически, или просто плохо лажатся на шаблоны, то решение на базе кодогенератора (полноценного) или интерпретатора становится менее трудаемким, и более простым в реализации/откладке/поддержке.
Хорошим примеро такой задачи может являться любая динамическая система коничных автоматов. Под динамически имеется в виду, что конечный автомат неизвестен в полном объеме на момент компиляции. Примером такой машины может быть машина регулярных варжений. Хотя она имеет небольшое отношение к метаданным, но тем не менее аталогичные задачи где можно будет использовать метаданные найти не сложно. Главное, на сей момент для нас доказать, что работа в компайл-тайме может привести к меньшей надежности.
Итак, такая машина может быть описана как набор методов, атрибутов и (возможно) внешних данных. В случае кодирования без информации о типах, нам придется все алогоритмы жестко кодировать (хардкодить). Объем кода будет прямо порпрционален сложности автомата. Любой нюанс будет умножать сложность системы. Скорее всего программист отчаяшись захардкодить такую сложную систему (ведь она может и измениться!) попросту делает интерпретатор и опять же начинает клепать для него метаданные.
В случае же с генерацией кода нужно лишь написать систему которая будет анализировать метаданные и генерировать специализированный код описывающий требуемую машину.
Случай 3. Задача легко решается банальным кодированием, но зада очень тепичная и встречающаяся нарачито часто. Заранее известно, что скорость работы алгоритма основанного на ти будет намного выше требуемой. Примерами могут являються многие типичные действия хорошо поддающиеся декларативному описанию.
При решении задачи лобовым кодированием код засоряется ничего не значацими подробностями и становится плохо читаемым.
При решении задаче средствами макросов и шаблонов, получается упростить внешний вид кода, но:
1. Его количество все же больше чем при чисто декларативном методе.
2. Код получается разнесенным по разным местам программы. Иногда удается сконцентрировать код в одном месте. Но не всегда.
3. Часто в следствии проблем с реализацией (что греха таить, гибкость шаблонов и макросов в области магии не беспредельна) часть кода скрывается от глаз программиста (или усложняется и запутывается) настолько сильно, что появляются проблемы с отладкой кода созданного в следствии такого дизайна.
4. Резко усложняется динамическое добавление нужных функций (это или вообще не воможно или появляется громоздкий АПИ).
За счет проверки компилятора уменьшается вероятность сделать ошибку типа опечатки. Но соложность реализации востанавливает паритет. А меньшая декларативность даже увеличивает вероятность рантайм-ошибок.
Решение на базе ти позволяет достить реальной декларативности. Код анализируещий метаданные является обычным. Его можно легко читать и отлаживать. В виду того, что ти доступно даже внешним модулям появляется возможность добавлять такие описания динамически (из модулей о которых еще не известрно в рантайме). Причем никаких особо сложных действий со стороны программиста делать не нужно все универсально.
Следовательно в случае 3 мы имеем выигрышь в простоте и элегантности реализации. Простота позволяет более быстро написать и отладить нужную функциональность сделав меньше ошибок. Правильность работы алгоритма интерпретации проверяется на некольких экземплярах метаинформации и потом работает всю жизнь. Алгоритм анализа сложный, можно провдить анализ при загрузке и помещать информацию в более простые и защищенные от ошибок структуры. Для ускорения (если оно надо) можно применять кодогенерацию.
ГВ>>>Ну как, понятно объяснил? Или стрелочки логических связей нарисовать? VD>>Такую позицию не стоило и озвучивать. Она ровным чсетом никому ничего не дает.
ГВ>Не надо за всех расписываться.
Конструктива в ней небыло.
ГВ> Дискуссия на самом деле небезынтересная получается.
Для меня уже нет. Я снова вижу людей из последих сил защищающих свой стрый уклад жизни. Сказки про то, что рантайм — это зло не состоятельны. Их опровергает жизнь. Ну, а наезды на метоинформацию вообще смешны. И при всем при этом против постулата, что если задачу аналогичко легко решить как средствами кодирования, так и анализом метаинформации, то лучше применить кодирование, никто не спорит.
Короче, надоело.
VD>>Твои рассуждения противоречат логике. Любой дизайн тем лучше чем проще и эффективнее он решает поставленную задачу имеющимися средствами. А понятие "криво" является сугубо отнсительным. Так что если решение единственное, то кривым его называть бессмысленно.
ГВ>Почему?
Покачену. Вот у нас есть такой поц Paul Poloziouk. Он на все подряд посты лепит минусы. Ему все криво. Это из этой же серии.
ГВ> Представь, например, что некто свалился в лужу дерьма. Измазался относительно слабо (во чудо-то!). Выбираться можно только вброд, но измазаться придётся ещё больше. Единственное это решение? Скорее всего — да. Будет он материться по этому поводу? Будет, я думаю.
Оно будет единственно верным. Так как другое будет остаться в луже этого дерьма. Ты же предлагаешь именно это и дель. Оставать в луже дерьма потому, что идти в брод криво.
Заметь я тебя на аналогии не подбивал.
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>dynamic_cast<> вызывается в CreateObject? Если CreateObject возвращает общий интерфейс I_Object, то зачем в нём dynamic_cast<> ?
Есть application->CreateObject(className) и есть шаблон CreateObrejct<I_MyCoolInterface>(className) шаблон пинает application (вернее один из сервисов ака супер фабрика) и делает dynamic_cast на возвращенный обьект.
Сделано исключительно для того чтобы меньше писать.
ГВ>OK, значит dynamic_cast<> нужен только для получения частного типа из общего.
Считай что это QueryInterface
ГВ>Надеюсь, что в итоге я правильно тебя понял:
Все еще проще. ехе вобще ни чего не знает кроме того как работать с фабриками (вобще у него есть еще сервисы но это не важно).
Если в длл надо создать обьект то просто пинаем application (через CreateObject<>() для удобства) и он возвращает созданный объект или null.
Короче все проще некуда
if(Ref<I_Sensor> sensor=CreateObejct<I_Sensor>(sensorName))Это в нутри длл
CreateObejct<I_Sensor>(sensorName) пинает application->CreateObject
На результат применяю dynamic_cast после чего есть указатель на конкретный интерфейс или null.
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>>>"моей программы" — имеется ввиду та программа, которую разрабатывает и контролирует конкретный дизайнер. VD>>А компонент это тоже "твоя программа"? Или он обязан быть частью дезайрена?
ГВ>А откуда взялось это противопоставление? Компонент обязан вписываться в дизайн, а не наоборот. Если он не подходит, то нужно вводить дополнительную функциональность или посылать нахрен данный конкретный компонент и заменять его другим, более подходящим. В противном случае архитектура ограничивается используемыми средствами, что не есть good. ИМХО, разумеется
Сдается мне, что ты вообще не понимашь этого термина. Компонент (любой, можно даже сказать компонент как класс) принципиально не вяляется частью твой программы. Он — это внешняя независимая программа. Причем при компонентном подходе к проектированию, ты свой дизайн строишь на базе компонентов. Таким образом ситуация кода компонент не подходит для дизайна является ошибкой дизайна.
В общем, если понимаешь, что такое компонент, то этот твой ответ является очередным увиливанем от ответа, с целью таки не скзать: "Да я был не прав". А если не понимаешь, то мы вообще тут воду в ступе перемалываем.
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>dynamic_cast<> вызывается в CreateObject? Если CreateObject возвращает общий интерфейс I_Object, то зачем в нём dynamic_cast<> ?
За тем, что человек создает компонентную архитектуру. Он не знает, что подключает в рантайме, а dynamic_cast позволяет ему быть в большей уверенности относительно безопасности доальнейших действий.
Вообще-то это плохое решение. Но не из-за производительности, а из-за... ну, дагодались? Из-за убогости стандарта С++. Вернее из-за нежелания его авторов описмывать в нем что-либо связанное с рантаймом (акромя библиотек).
Правильное решение в КОМ-е. Оно универсально. А еще более правильное в дотнете. Оно ни только универсально, но просто и безопасно.
ГВ>
ГВ>int RunSomeOperation(I_Object*)
ГВ>
Думаю, что I_Object — это интерфейс. Так что скорее:
I_Object->RunSomeOperation()
ГВ>ИМХО, другого обобщенного случая здесь быть не может, поскольку ты утверждаешь, что exe не меняется в зависимости от набора .dll.
Скорее всего он говорит, о механизме возврата самих I_Object (ну и дальнейшей работе с ним).
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Геннадий Васильев, Вы писали:
VD>>Проблема, в том, что С++ заставляет тренеровать могзги вместо выполнения основной рабты.
ГВ>"Не умом поразить тщился, — с достоинством ответил отец Кин. — ...Умные нам ненадобны. Надобны верные." (А. и Б. Стругацкие, "Трудно быть богом").
Это ты к чему?
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Ну и что ты демонстрируешь этим?
Догадайся с трех раз.
ГВ>То, как чаще всего, вероятно, пишут. ATL — неплохая библиотека, но, ИМХО, главное её достоинство — широкая распространённость.
Ты видил более удобную? А нет, так что зря воздух сотрясать?
ГВ> Сам посуди: реализацию QueryInterface можно спАрить с наследованием от заданного интерфейса, объявления элементов — вынести в виртуальные базовые классы и т.п. Другое дело, что ATL написана для VC6, который начинал сходить с ума от сложного наследования, где чередовались шаблоны и виртуальное наследование... так то — проблемы компилятора, альтернативы которому имеются уже достаточно давно.
Во-во. Чтобы заткнуть дыру в рантайме мы готовы вылить ушат грязи на нивчем не повинный компилятор. Только зачем? Возможности писать так же просто и красиво как дотнете нет ни в одном компиляторе кроме МС++.
Не будт на С++ то же. Так как твой Requestable уже перебор, ну, а BasicCoClassImplement увеличивает отрыв. Тебе показали простоту с какой "убогий" язык без шаблонов вегко и элегантно решает проблемы, а ты в ответ "дык, мы ща по бырому десяток килобайт оберток наклепаем....".
ГВ>Если заинтересует, расскажу о реализации Requestable и т.п., но суть дела не в этом. Ты демонстрируешь одну и ту же ситуацию — проверку композиции в рантайме.
Может быть ты не заметил, что без проверки в рантайме тут необойтись? Хотя у тебя это уже в норме вещей.
Кстати, можешь на этом примере продемострировать всю кривость этого подхода.
ГВ>Не путай, пожалуйста, рантайм-проверки результатов операций управления ресурсами и рантайм-проверки типов, т.е. — верификацию композиции. Понятие "компонент", как и "модуль" вовсе не означает необходимости проверок типов.
У тебя пунктик по поводу типов. Ты так долго себя убеждал, что типы не является обычными данными, что видимо привык. Нет никакой разницы между строкой символов полученной из-вне и типм. Это ты все сам придумал.
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.