tag:blogger.com,1999:blog-3208941668630248550.post4379471673665247290..comments2024-03-13T10:43:06.615+02:00Comments on 18-ть лет с Delphi: Пример использования шаблонов генерацииAlex W. Lulinhttp://www.blogger.com/profile/08400475846894229767noreply@blogger.comBlogger60125tag:blogger.com,1999:blog-3208941668630248550.post-71112443772269043252013-10-04T01:07:05.841+03:002013-10-04T01:07:05.841+03:00И ещё оттуда же:
"Since the compiler generate...И ещё оттуда же:<br />"Since the compiler generates additional code for each template type, indiscriminate use of templates can lead to code bloat, resulting in larger executables.<br />Because a template by its nature exposes its implementation, injudicious use in large systems can lead to longer build times."Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-33295901911890249602013-10-04T01:05:46.151+03:002013-10-04T01:05:46.151+03:00Английская версия wiki говорить опять же о ФИЗИЧЕС...Английская версия wiki говорить опять же о ФИЗИЧЕСКОМ дублировании кода:<br />"Both macros and templates are expanded at compile time. Macros are always expanded inline, while templates are only expanded inline when the compiler deems it appropriate. When expanded inline, macro functions and function templates have no extraneous runtime overhead. Template functions with many lines of code will incur runtime overhead when they are not expanded inline, but the reduction in code size may help the code to load from disk more quickly or fit within RAM caches."<br /><br />http://en.wikipedia.org/wiki/Template_(C%2B%2B)<br /><br />Т.е. - опять же получаем, что "наши" шаблоны для "UML" - в этом плане - ничуть не хуже и не лучше - СУЩЕСТВУЮЩИХ общепринятых практик.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-3201996980167776532013-10-03T23:39:49.025+03:002013-10-03T23:39:49.025+03:00Ну и ещё - модель многое ВАЛИДИРУЕТ. Она не даёт н...Ну и ещё - модель многое ВАЛИДИРУЕТ. Она не даёт нарисовать такую модель, которая не укладывается в рамки "мета-модели". А руками это написать - ЗАПРОСТО. Но тут вот как раз модель выступает в роли "тьютора", она - "советует" ПРИНЯТЫЕ на данный момент проектные решения и ОТВЕРГАЕТ - "заведомо неправильные". На ДАННЫЙ МОМЕНТ. Если такое решение ВСЁ-ТАКИ нужно - варианта - ДВА, либо писать РУКАМИ, либо ПЕРЕСМАТРИВАТЬ мета-модель.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-74447905409242986112013-10-03T23:36:05.701+03:002013-10-03T23:36:05.701+03:00О!
Вот пример:
MyClass = class
MyInterface = in...О!<br /><br />Вот пример:<br /><br />MyClass = class<br /><br />MyInterface = interface<br /><br />ведь эквивалентно:<br /><br />MyClass = class(TObject)<br /><br />MyInterface = interface(IUnknown)<br /><br />а почему? потому, что компилятор "подставляет" нужные значения.<br /><br />Так и у нас. Модель и кодогенератор - многое "подставляют".<br /><br />Написали:<br /><br />MyDocumentForm = VCMFrom<br /><br />получили:<br /><br />MyDocumentForm = clas(TvcmForm)<br /><br />Написали:<br /><br />MySpecialDocumentForm = VCMForm(MyDocumentForm)<br /><br />получили:<br /><br />MySpecialDocumentForm = class(MyDocumentForm)<br /><br />-- ну и далее - по аналогии.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-79276463505469151522013-10-03T23:31:41.212+03:002013-10-03T23:31:41.212+03:00"И на самом деле НА ПРАКТИКЕ - нами использую..."И на самом деле НА ПРАКТИКЕ - нами используются ОБА подхода."<br />-- "магии" нет никакой. Всё в конечном итоге приходит к КОДУ. Пусть и не написанному руками. Но "как-будто" руками написанному. Он точно так же компилируется и точно так же выполняется. И вполне может быть написан РУКАМИ.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-21774025122742484852013-10-03T23:24:00.762+03:002013-10-03T23:24:00.762+03:00Например - можно просто ДЕКЛАРИРОВАТЬ на модели, ч...Например - можно просто ДЕКЛАРИРОВАТЬ на модели, что "контрол данного класса реализует вот такие пользовательские операции GUI (Cut, Copy, Paste к примеру)" и посредством кодогенератора будет создана соответствующая "обвязка" для РЕАЛИЗАЦИИ контролом нужных интерфейсов и регистрации их в нужных "точках подключения". А можно ВСЁ то же самое - написать РУКАМИ. Фреймфорк -в этом плане - ни к чему НЕ ПРИНУЖДАЕТ. И на самом деле НА ПРАКТИКЕ - нами используются ОБА подхода. Исходя из соображений эффективности. Жаль вот Виктор Морозов не комментирует всё это. Он бы мог рассказать - как он РУКАМИ писал многие вещи, которые можно было бы сделать при помощи модели, просто потому, что он чего-то "не знал" или "так было быстрее".Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-51382333785232457892013-10-03T23:15:36.947+03:002013-10-03T23:15:36.947+03:00"У меня нет сомнений в том, что он ориентиров..."У меня нет сомнений в том, что он ориентирован на применение в контексте диаграмм."<br />-- это кстати - НЕ ТАК. Фреймворк для "конечного" программиста - прекрасно живёт и БЕЗ диаграмм. ВЕСЬ код, основанный на фреймворке - можно писать РУКАМИ. И есть проекты, в которых ТАК И СДЕЛАНО. Другое дело, что модель "помогает" писать этот код. С моделью - проще. Но можно и РУКАМИ.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-9330223041527766822013-10-03T23:12:40.396+03:002013-10-03T23:12:40.396+03:00"компилятор создаёт отдельный экземпляр функц..."компилятор создаёт отдельный экземпляр функции или класса"<br />-- никакой МАГИИ...Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-6058801120106293852013-10-03T23:10:43.937+03:002013-10-03T23:10:43.937+03:00Про C++
http://ru.wikipedia.org/wiki/%D8%E0%E1%EB%...Про C++<br />http://ru.wikipedia.org/wiki/%D8%E0%E1%EB%EE%ED%FB_C++<br /><br />"Хотя шаблоны предоставляют краткую форму записи участка кода, на самом деле их использование не сокращает исполнимый код, так как для каждого набора параметров компилятор создаёт отдельный экземпляр функции или класса."<br /><br />-- ОПЯТЬ ЖЕ - имеем ФИЗИЧЕСКОЕ дублирование КОДА, но ЛОГИЧЕСКИ - он один.<br /><br />Собственно "наши" шаблоны - в ЭТОМ ПЛАНЕ - не лучше и не хуже.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-66202442999471364602013-10-03T23:07:16.763+03:002013-10-03T23:07:16.763+03:00Собственно это же подтверждают и исследования ассе...Собственно это же подтверждают и исследования ассемблерного кода сгенерированного из Generic'ов. Адреса методов - для РАЗНЫХ "экземпляров инстанцирования Generic'ов" - РАЗНЫЕ.<br /><br />Что собственно - понятно. По-другому - не сделаешь. Разные типы имеют РАЗНЫЙ набор базисных операций. По-разному на УРОВНЕ физического кода реализованные.<br /><br />Никакой магии.<br /><br />Считайте - всё та же "перегрузка операторов". На уровне компилятора.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-55257485762826277262013-10-03T23:02:43.164+03:002013-10-03T23:02:43.164+03:00Вот и цитата про Generic'и в Delphi:
"Ins...Вот и цитата про Generic'и в Delphi:<br />"Instantiation <br /> The compiler generates real instruction code for methods defined in generics and real virtual method table for a closed constructed type. This process is required before emitting a Delphi compiled unit file (.dcu) or object file (.obj) for Win32.<br /> "<br /><br />ms-help://embarcadero.rs_xe3/rad/Terminology_for_Generics.htmlAlex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-83181362582750746052013-10-03T23:01:01.274+03:002013-10-03T23:01:01.274+03:00"При кодогенерации нам автоматически сформиру..."При кодогенерации нам автоматически сформируют заготовку для обработчика событий и настоят этот обработчик."<br /><br />-- не совсем так. При кодогенерации нам добавят НАСЛЕДОВАНИЕ от класса описанного на той де модели. Возможно - примесное. Subscriber'у своё, Publisher'у - своё. А возможно нам сделают "утилитный" приватный класс. С правильным наследованием (читайте - аспект), который выполняет роль либо publisher'а, либо subscriber'а. Реализующий часть "шаблона проектирования" publisher/subscriber. И транслирующий "клиентские" вызовы в породивший его класс.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-26860659000879823022013-10-03T22:56:16.024+03:002013-10-03T22:56:16.024+03:00Вот пока нашёл цитату про FreePascal:
"Techni...Вот пока нашёл цитату про FreePascal:<br />"Technical details<br /><br />1. The compiler parses a generic, but instead of generating code it stores all tokens in a token buffer inside the PPU file.<br />2. The compiler parses a specialization; for this it loads the token buffer from the PPU file and parses that again, but replaces the generic parameters (in most examples "T") by the particular given type (e.g. LongInt, TObject). The code basically appears as if the same class had been written as the generic but with T replaced by the given type.<br />Therefore in theory there should be no speed differences between a "normal" class and a generic one."<br /><br />http://wiki.freepascal.org/GenericsAlex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-14613311000318942532013-10-03T22:51:07.037+03:002013-10-03T22:51:07.037+03:00И Generic'и Delphi - это ТОЖЕ - ДУБЛИРОВАНИЕ к...И Generic'и Delphi - это ТОЖЕ - ДУБЛИРОВАНИЕ кода. Физическое. О чём ЯВНО в документации и написано. Есть "предкомпиляция" Generic'ов в код Unit'а в котором он содержится и есть "инстанцирующая компиляция" по месту использования.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-10733370064416344902013-10-03T22:42:25.295+03:002013-10-03T22:42:25.295+03:00Речь КОНЕЧНО о КОНКРЕТНЫХ прецедентах, а не об абс...Речь КОНЕЧНО о КОНКРЕТНЫХ прецедентах, а не об абстрактных.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-73878135684666257472013-10-03T22:41:37.040+03:002013-10-03T22:41:37.040+03:00"А если publisher и subscriber расположены в ..."А если publisher и subscriber расположены в *разных* прецедентах? "<br />-- насколько я "трактую" - РАЗНЫЕ прецеденты - не могут "взаимодействовать", они лишь могут СМЕНЯТЬ друг друга. Ну это Я ТАК понял RUP. И так применяю на практике.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-48126802788454400622013-10-03T22:38:27.352+03:002013-10-03T22:38:27.352+03:00"Возвращаюсь к экзистенциальности. Смотрите: ..."Возвращаюсь к экзистенциальности. Смотрите: кодогенерация, шаблоны вообще — это, в сущности, автоматизация некоторого дублирования. Это ставит в тупик, поскольку парадигмой современного программирования является всяческий уход от дублирования."<br /><br />-- понимаете какая штука. Дублирование может быть физическим, а может быть логическим. Конечно идеально, чтобы ни того, ни другого не было бы. Но! Вот скажем std::vector(int) и std::vector(std::string) это один код?<br /><br />Ведь нет конечно. Ведь шаблоны C++ это же тоже ПО СУТИ - "макроподстановки". Соответственно - физическое дублирование - присутствует, а вот логическое - нет. Так и с нашими шаблонами кодогенерации.<br /><br />Логика сосредоточена в ОДНОМ МЕСТЕ, а вариантов инстанцирования - да - несколько.<br /><br />Но от этого - никуда не деться. Нет ну можно конечно делать "полиморфные" контейнеры. Но в ущерб производительности. Ну или посредством "хоккея" на уровне компилятора. Типа boxing в C#.<br /><br />Это не следует читать, как то, что я ПРИЗЫВАЮ к дублированию. Нет! Не призываю. И всеми силами стараюсь от него избавляться. Но! Просто надо ЧЁТКО осознавать, что в выборе эффективность/простота использования/дублирование - дублированию - ТОЖЕ место находится. И хорошо, если это дублирование лишь физическое, а не логическое.Alex W. Lulinhttps://www.blogger.com/profile/08400475846894229767noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-81347816016339984352013-10-03T15:32:50.087+03:002013-10-03T15:32:50.087+03:00Спасибо за ответы по-существу.Спасибо за ответы по-существу.NameRechttps://www.blogger.com/profile/00070033877714975718noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-30356783694461252932013-10-03T15:28:14.746+03:002013-10-03T15:28:14.746+03:00конструктивных смыслов было несколько но все они, ...конструктивных смыслов было несколько но все они, увы, были в не технологичнской плоскости.<br />1) программистов на с++ было больше чем на Дельфи<br />2) покупать визиБрокер руквовдство не хотело <br />3) программисты на дельфи не хотели возиться с корбой<br /><br />А в идеале, да конечно. Сервер на с++ <--- КОРБА ---> Клиент на Дельфи. <br /><br />>чуть ли не сложнее, чем с сервером приложений через<br />ну вот в итоге, благодаря шаблонам, стало не то что "не сложнее", а ЗНАЧИТЕЛЬНО легче.Максим Крыловhttps://www.blogger.com/profile/17443805180550384967noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-37780737152129799452013-10-03T15:18:21.516+03:002013-10-03T15:18:21.516+03:00«Меня немного смутило обилие и разнообразие интерф...«Меня немного смутило обилие и разнообразие интерфейсов,<br /><br />шутка в том что в дельфи мы отдавали уже не CORBA а свои интерфейсы, те клиентская длл была не просто переходником-трансформатором, а скорее контроллером (с тз MVC), на ней куча бизнесс-логики жило. Поэтому обилее и разнообразие было довольно большим. Очень большим.»<br />-- Тут, признаться, заинтриговали... :-)<br />А какой вообще смысл был в этой DLL? Почему всю бизнес-логику не реализовать на Delphi, если клиет всё равно становится толстым: Delphi-клиент + DLL с которым он работает, и в котором содержится бизнес-логика, пусть и не вся, есть ведь ещё сервер приложений, для взаимодействия с которым, как я понимаю, использовалась CORBA. Ну и пусть бы Delphi-клиент взаимодействовал с сервером приложений напрямую, через ту же CORBA.<br />Какой был конструктивный смысл в лице этого DLL на C++, если управляться с ним из Delphi чуть ли не сложнее, чем с сервером приложений через CORBA?NameRechttps://www.blogger.com/profile/00070033877714975718noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-80426719923365056872013-10-03T15:06:08.852+03:002013-10-03T15:06:08.852+03:00Этот комментарий был удален автором.NameRechttps://www.blogger.com/profile/00070033877714975718noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-66697017334109832082013-10-03T14:53:47.366+03:002013-10-03T14:53:47.366+03:00> Меня немного смутило обилие и разнообразие ин...> Меня немного смутило обилие и разнообразие интерфейсов,<br /><br />шутка в том что в дельфи мы отдавали уже не CORBA а свои интерфейсы, те клиентская длл была не просто переходником-трансформатором, а скорее контроллером (с тз MVC), на ней куча бизнесс-логики жило. Поэтому обилее и разнообразие было довольно большим. Очень большим.Максим Крыловhttps://www.blogger.com/profile/17443805180550384967noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-64508605855776784692013-10-03T14:50:55.142+03:002013-10-03T14:50:55.142+03:00> Ведь в сущности, для того, что нашло отражени...> Ведь в сущности, для того, что нашло отражение у Вас с коллегами в диаграммах, в VisiBrocker предназначен IDL. Если я правильно понял Вас, конечно...<br />да ОЧЕНЬ похоже, IDL мы правда тоже с диаграмм генерировали )) это и было САМЫМ началом, но тогда именно хотелось всю наменкулаитуоур увидеть, те на самсом первом шаге, это да, именно способ проектирования + докуменация были. Именно на первом. Дык вот когда мы захотели "рисовать" IDL, выяснилось что РешаналРозе рисует еще ни чего но вот генерирует выходной IDL - пряимо скажем кое-как. Тогда собственно и возник свой генертор, который уже использовал шаблон (совсем-совсем примитивный, по сути это было аналогично XSLT преобразованию). А вот на втором шаге, когда возникла необходимости связать все это с Дельфи, мы это хозяйство и использовали, уже немного расширив возможности и метаописания и генератора.Максим Крыловhttps://www.blogger.com/profile/17443805180550384967noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-55571873886297288082013-10-03T14:35:00.501+03:002013-10-03T14:35:00.501+03:00«чем не устроил VisiBrocker
руководство покупать...«чем не устроил VisiBrocker <br /><br />руководство покупать отказалось + у разработчиков на Дельфях тогда почему-то была устойчивая идиосинкразия к КОРБЕ (без причн, имхо)»<br />-- Как-то странно выходит... Хотя понятно, что от руководства можно ждать чего угодно, но отказаться от приобретения VisiBrocker и, вместо этого, реализовать часть его функциональности самостоятельно...<br />Ведь в сущности, для того, что нашло отражение у Вас с коллегами в диаграммах, в VisiBrocker предназначен IDL. Если я правильно понял Вас, конечно...<br /><br />«можно создать за 24 +/- 8 <br />ну я тоже не знаю что было у вас, но могу догатываться что вы описывали интерфейс на XMLа потом преобразовывали его в компланарные интерфейсы для с++ и дельфей.»<br />-- Нет, у нас совершенно не так, мы взаимодействуем с Java, и совсем иначе. Но как у нас - несущественно.<br />Меня немного смутило обилие и разнообразие интерфейсов, используемых в DLL. В принципе, в CORBA их не так уж и много, в части маршаллинга, по крайней мере. То, что можно (допустимо) использовать, определяет IDL, которым и можно было бы и вдохновляться. В частности, маршаллинг std::string там не предусмотрен, т.е. сам DSL такое запрещает. Ну и на XML IDL ложится достаточно хорошо. Так что, думаю, подход через XML масштабируется в плане сложности в той же мере, что и IDL.<br /><br />«Но при чём здесь диаграммы? <br />ну генерировать код нужно же было из чего-то? да можно было придумать что-то рядом в качестве метаописания, хоть XML хоть свой DSL, и натравливать на него ТОТ ЖЕ САМЫЙ наш шаблон с ТЕМ ЖЕ САМЫМ генератором и получать на выходе тоже самое. На зачем? Если уже есть инструмент который позволяет это же НАРИСОВАТЬ а не писать кучей каракулей.»<br />-- Т.е. инструмент для создания диаграмм и кодогенерация по шаблонам уже были :-)<br />Чтож, в таком случае, грех было не воспользоваться этими инструментами.<br /><br />«Два в одном. И быстрее и нагляднее. Хотя спустя годы мы уже и сами пришли к выводу что иногда хочется модель не рисовать а записать, но это уже другая тема )) и причины другие (типа мерджа моделей при асинхрнной работе)»<br />-- Да-да... IMHO подобные вопросы возникают в отношении любой графической нотации...<br /><br />БОЛЬШОЕ СПАСИБО за Ваши разъяснения. Многое становится понятным.NameRechttps://www.blogger.com/profile/00070033877714975718noreply@blogger.comtag:blogger.com,1999:blog-3208941668630248550.post-53039701086302869312013-10-03T13:30:13.663+03:002013-10-03T13:30:13.663+03:00> Но при чём здесь диаграммы?
ну генерировать к...> Но при чём здесь диаграммы?<br />ну генерировать код нужно же было из чего-то? да можно было придумать что-то рядом в качестве метаописания, хоть XML хоть свой DSL, и натравливать на него ТОТ ЖЕ САМЫЙ наш шаблон с ТЕМ ЖЕ САМЫМ генератором и получать на выходе тоже самое. На зачем? Если уже есть инструмент который позволяет это же НАРИСОВАТЬ а не писать кучей каракулей. Два в одном. И быстрее и нагляднее. Хотя спустя годы мы уже и сами пришли к выводу что иногда хочется модель не рисовать а записать, но это уже другая тема )) и причины другие (типа мерджа моделей при асинхрнной работе)Максим Крыловhttps://www.blogger.com/profile/17443805180550384967noreply@blogger.com