Re[36]: Будущее C#
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.07.03 06:51
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>"А баба Яга — против!" (c) Мультик. Извини, просто ты так эмоционально реагируешь.


С чего ты взял?

ГВ>>>А что ты будешь делать, если для некоего нового типа данных ещё нет обработчика среди дополнительных сборок?

AVK>>Напишу и скомпиляю в отдельную сборку.

ГВ>И что? Где же помощь reflection?


Помощь рефлекшена в том что мне не надо пересобирать старый проект. Более того — если источник данных и их потребитель это отдельные продукты, то мне достаточно только обновить источник данных и предоставить необходимые конверторы, не трогая потребителя совершенно.

ГВ>Только в том, что ты выполнишь вместо подстановки средствами механизма виртуальных функций подстановку средствам атрибутов? Т.е., грубо говоря, слоты размещаются не в VMT, а в атрибутах.


Рефлекшен гибче полиморфизма и предоставляет больше возможностей меньшими усилиями. Кроме того рефлекшен не требует наследования от какого то класса, а иногда это заметно удобнее.

ГВ>Обязанность по поддержанию адекватного набора конвертеров по прежнему лежит на программисте. С той лишь разницей, что для .Net он будет делать сборки, а на C++ скорее всего, — .dll или Shared Objects.


Разница только в одном — в отсутствие рефлекшена все это ты можешь осуществить только внутри своего продукта. Как только часть цепочки оказывается ввиде бинарного модуля без исходников то сразу все становится много печальнее.

ГВ>>>OK, я тебя понял. И то, к чему ты упомянул про дополнительные сборки в каталогах программы — тоже. И сразу хочу задать встречный вопрос. А кто напишет для моей программы нужные именно ей конвертеры? Предположим, что речь идёт не о банльной конвертации в строковое представление, а например, в хливких шорьков, метОда использования которых известна только мне. Я позволю себе задать этот вопрос, поскольку спор начинался с общих фраз.


AVK>>Это уже совсем другой вопрос.


ГВ>Да нет, в том-то и дело, что это две стороны одно и того же вопроса.


Не надо перескакивать на другие темы, если нет больше аргументов так и скажи что был не прав.

AVK>>Главное что при добавлении новых типов старый код менять не нужно. Это уменьшает количество работы и гарантирует от глюков, связанных с тем что ты поменял тип, но забыл поменять его мап.


ГВ>При такой ситуации (необрабатываемые данные во внешнем источнике данных) — всегда возможны глюки, а вернее — runtime-ошибки.


Если все поведение системы определяется в одном месте их вероятность значительно меньше. Как например ты напишешь на плюсах систему конфигурирования, так чтобы для внесения новой переменной в конфигурацию нужно было бы всего лишь добавить поле в класс, ее содержащий, так чтобы все остальное — механика сохранения/загрузки, пользовательский интерфейс и прочая адаптировались под изменения автоматически? А при помощим рефлекшена это возможно, и оно, помимо снижения объема работы срахует от ошибок, в том числе и в рантайме просто потому что их негде сделать, изменения требуют от тебя чисто декларативных действий и никакой правки алгоритмов.

ГВ>И где я говорил, что новые конвертеры, обрабатывающие сигнатуры новых типов данных источника не могут подгружаться? В default-ветке switch-а вполне может стоять что-то вроде:


ГВ>
ГВ>default: locate_custom_datatype_converter(...);
ГВ>


ГВ>где и будет выполняться поиск по 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 изначально не фигурировал, твоя попытка перевести все на обсуждение терминологий выглядит нелепой отмазкой.
... << RSDN@Home 1.1 beta 1 (np: тихо) >>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.