Comments 15
Вот самый первый минус в итоге и отвадил меня от идеи писать свою систему плагинов на c++.
Плагины подразумевают бинарную независимость хоста от модуля расширения. Чтобы можно было писать на разных компиляторах. У вас, правильней назвать, не плагины, а модульный дизайн.
Имею несчастье пользоваться неудачно-разработанной плагинной системой, где тоже С++. Хуже решения не придумать. Только один компилятор и трудности изменения API. Если хочется хорошую плагинную систему и оставить C++, лучше сделать прослойку: C++ на хосте оборачивается в C вызовы. А в хидере для плагина C вызовы оборачиваются снова в C++. В итоге можно пользоваться и С и C++. И не забывать важную идею: в плагине и хосте разные менеджеры памяти: где память выделили, там ее и надо освобождать.
Насколько я понял, вас интересует обратная связь. Вот мои размышления:
А про код сказать мало что могу, потому что не вникал. Я предпочитаю, чтобы код был как можно более проще, чтобы видя несколко десяток строк одновременно, было сразу ясно, что это и как это работает. А у вас слишком много модного C++, слишком многословно, слишком расточительно и от std:: рябит в глазах. Т.е. прямая противоположность того, что я считаю красивым и удобным кодом.
Как я понимаю, вы это писали, видимо, для резюме, чтобы показать свои знания модного C++. Ход может быть неплохом, чтобы найти работу. Но обычно в коммерческом программировании важно не знание самого модного, а умение писать просто и элегантно по принципу KISS.
Простота обеспечивается как техническими решениями, так и простотой с точки зрения того, кто будет пользоваться вашим кодом. Обилие всевозможных фич C++ в вашем решении говорит об обратном. Это означает, что ваше решение завязано на эти фичи, что дает меньше гибкости для пользователей вашего кода.
Если хочется применить что-то техническое (типа специфичных фич языка или библиотек), то лучше сначала подумать, можно ли обойтись без этого, есть ли другие более элегантные методы достижения технической задачи? По-возмжности, лучше выбирать те решения, какие не ограничивают пользователя, не замедляют программу, не приводят к простыням кода, какой требуется еще написать, чтобы сделать что-то минимально-полезное.
Еще внимательней относитесь к именам. У вас я вижу get и get_plugin, has и другие слишком общие слова. Одинаковые и похожие имена, а также слишком общие названия могут затруднять чтение кода и усложнить понимание того, для чего они нужны.
По поводу шаблонов в API. Старайтесь применять шаблоны, только если они дают элегантное и простое решение технических задач. Использовать шаблоны для создания сахара может быть неудобным решением, поскольку параметры шаблона не очевидны для понимания пользователем кода, что именно туда передается и почему. Всякие <2>, ::_3 и прочее — это коряво и выглядит как хак. К сожалению, в стандартной библиотеке такого полно. Там это делалось для ухищрений. В своем коде ухищряться подобным образом — не лучшее решение для подражания.
Имею несчастье пользоваться неудачно-разработанной плагинной системой, где тоже С++. Хуже решения не придумать. Только один компилятор и трудности изменения API. Если хочется хорошую плагинную систему и оставить C++, лучше сделать прослойку: C++ на хосте оборачивается в C вызовы. А в хидере для плагина C вызовы оборачиваются снова в C++. В итоге можно пользоваться и С и C++. И не забывать важную идею: в плагине и хосте разные менеджеры памяти: где память выделили, там ее и надо освобождать.
Насколько я понял, вас интересует обратная связь. Вот мои размышления:
А про код сказать мало что могу, потому что не вникал. Я предпочитаю, чтобы код был как можно более проще, чтобы видя несколко десяток строк одновременно, было сразу ясно, что это и как это работает. А у вас слишком много модного C++, слишком многословно, слишком расточительно и от std:: рябит в глазах. Т.е. прямая противоположность того, что я считаю красивым и удобным кодом.
Как я понимаю, вы это писали, видимо, для резюме, чтобы показать свои знания модного C++. Ход может быть неплохом, чтобы найти работу. Но обычно в коммерческом программировании важно не знание самого модного, а умение писать просто и элегантно по принципу KISS.
Простота обеспечивается как техническими решениями, так и простотой с точки зрения того, кто будет пользоваться вашим кодом. Обилие всевозможных фич C++ в вашем решении говорит об обратном. Это означает, что ваше решение завязано на эти фичи, что дает меньше гибкости для пользователей вашего кода.
Если хочется применить что-то техническое (типа специфичных фич языка или библиотек), то лучше сначала подумать, можно ли обойтись без этого, есть ли другие более элегантные методы достижения технической задачи? По-возмжности, лучше выбирать те решения, какие не ограничивают пользователя, не замедляют программу, не приводят к простыням кода, какой требуется еще написать, чтобы сделать что-то минимально-полезное.
Еще внимательней относитесь к именам. У вас я вижу get и get_plugin, has и другие слишком общие слова. Одинаковые и похожие имена, а также слишком общие названия могут затруднять чтение кода и усложнить понимание того, для чего они нужны.
По поводу шаблонов в API. Старайтесь применять шаблоны, только если они дают элегантное и простое решение технических задач. Использовать шаблоны для создания сахара может быть неудобным решением, поскольку параметры шаблона не очевидны для понимания пользователем кода, что именно туда передается и почему. Всякие <2>, ::_3 и прочее — это коряво и выглядит как хак. К сожалению, в стандартной библиотеке такого полно. Там это делалось для ухищрений. В своем коде ухищряться подобным образом — не лучшее решение для подражания.
Уважаемый sojuznik спасибо вам за развёрнутые пояснения!
> У вас, правильней назвать, не плагины, а модульный дизайн.
Ок, учту.
> слишком многословно, слишком расточительно и от std:: рябит в глазах.
Я часто пользую и boost, во избежании конфликтов и неоднозначности — всегда нэймспэйсы оставляю не раскрытыми. Как-то нормально на это смотрю.
> Как я понимаю, вы это писали, видимо, для резюме, чтобы показать свои знания модного C++. Ход может быть неплохом, чтобы найти работу. Но обычно в коммерческом программировании важно не знание самого модного, а умение писать просто и элегантно по принципу KISS.
Нет )) я не ищу работу ))
Опыт у меня не очень большой, но в коммерческом программировании, как мне кажется важнее быстро выдавать рабочий код, что и позволяет нам делать новый стандарт.
Тут порог вхождения чуть выше чем в обычных случаях (в мета программировании), но в итоге позволяет писать код лаконично и быстро.
У меня нет каких-то конкретных сейчас примеров (читал где-то), но современный компилятор компонующий код с новым стандартом выдаёт бинарник по скорости исполнения ни намного медленнее чем без, но взамен новый стандарт предоставляет гибкость и удобство.
Тут всегда будет За и Против…
> Простота обеспечивается как техническими решениями, так и простотой с точки зрения того, кто будет пользоваться вашим кодом. Обилие всевозможных фич C++ в вашем решении говорит об обратном. Это означает, что ваше решение завязано на эти фичи, что дает меньше гибкости для пользователей вашего кода.
Если фичи новые, это не значит что они сложные, сложность скрыта под капотом (стандарт в нашем случае).
Мой код завязан на эти фичи потому что они уже здесь, грядут, идут и используются (ну или готовы чтобы их использовали).
> Еще внимательней относитесь к именам. У вас я вижу get и get_plugin, has и другие слишком общие слова. Одинаковые и похожие имена, а также слишком общие названия могут затруднять чтение кода и усложнить понимание того, для чего они нужны.
Ок.
> По поводу шаблонов в API. Старайтесь применять шаблоны, только если они дают элегантное и простое решение технических задач. Использовать шаблоны для создания сахара может быть неудобным решением, поскольку параметры шаблона не очевидны для понимания пользователем кода, что именно туда передается и почему. Всякие <2>, ::_3 и прочее — это коряво и выглядит как хак. К сожалению, в стандартной библиотеке такого полно. Там это делалось для ухищрений. В своем коде ухищряться подобным образом — не лучшее решение для подражания.
<2> — Этот как раз имело своей задачей упростить взаимодействие с интерфейсом: означает количество аргументов для задачи, вычисляется в compile time.
::_3 — Используется только в примере, для биндинга члена функции передаваемой в плагин.
Для подражания может не лучшее, но так легко и удобно пользовать.
Я имел опыт пользовать <2> в классах для полей значений, которые по сути являлись динамическими, вот там да, был гемор. А тут у нас возможные значения от 0 до 6…
> У вас, правильней назвать, не плагины, а модульный дизайн.
Ок, учту.
> слишком многословно, слишком расточительно и от std:: рябит в глазах.
Я часто пользую и boost, во избежании конфликтов и неоднозначности — всегда нэймспэйсы оставляю не раскрытыми. Как-то нормально на это смотрю.
> Как я понимаю, вы это писали, видимо, для резюме, чтобы показать свои знания модного C++. Ход может быть неплохом, чтобы найти работу. Но обычно в коммерческом программировании важно не знание самого модного, а умение писать просто и элегантно по принципу KISS.
Нет )) я не ищу работу ))
Опыт у меня не очень большой, но в коммерческом программировании, как мне кажется важнее быстро выдавать рабочий код, что и позволяет нам делать новый стандарт.
Тут порог вхождения чуть выше чем в обычных случаях (в мета программировании), но в итоге позволяет писать код лаконично и быстро.
У меня нет каких-то конкретных сейчас примеров (читал где-то), но современный компилятор компонующий код с новым стандартом выдаёт бинарник по скорости исполнения ни намного медленнее чем без, но взамен новый стандарт предоставляет гибкость и удобство.
Тут всегда будет За и Против…
> Простота обеспечивается как техническими решениями, так и простотой с точки зрения того, кто будет пользоваться вашим кодом. Обилие всевозможных фич C++ в вашем решении говорит об обратном. Это означает, что ваше решение завязано на эти фичи, что дает меньше гибкости для пользователей вашего кода.
Если фичи новые, это не значит что они сложные, сложность скрыта под капотом (стандарт в нашем случае).
Мой код завязан на эти фичи потому что они уже здесь, грядут, идут и используются (ну или готовы чтобы их использовали).
> Еще внимательней относитесь к именам. У вас я вижу get и get_plugin, has и другие слишком общие слова. Одинаковые и похожие имена, а также слишком общие названия могут затруднять чтение кода и усложнить понимание того, для чего они нужны.
Ок.
> По поводу шаблонов в API. Старайтесь применять шаблоны, только если они дают элегантное и простое решение технических задач. Использовать шаблоны для создания сахара может быть неудобным решением, поскольку параметры шаблона не очевидны для понимания пользователем кода, что именно туда передается и почему. Всякие <2>, ::_3 и прочее — это коряво и выглядит как хак. К сожалению, в стандартной библиотеке такого полно. Там это делалось для ухищрений. В своем коде ухищряться подобным образом — не лучшее решение для подражания.
<2> — Этот как раз имело своей задачей упростить взаимодействие с интерфейсом: означает количество аргументов для задачи, вычисляется в compile time.
::_3 — Используется только в примере, для биндинга члена функции передаваемой в плагин.
Для подражания может не лучшее, но так легко и удобно пользовать.
Я имел опыт пользовать <2> в классах для полей значений, которые по сути являлись динамическими, вот там да, был гемор. А тут у нас возможные значения от 0 до 6…
Мои замечания про std: связаны с наглядностью примеров, поясняющих возможности вашего кода для потенциальных потребителей. Примеры пишутся для того, чтобы быстро ввести в курс дела новичка дать ему базовое понимание о том, для чего нужен ваш код и подходит ли он ему. Обилие std: и новых фич языка (в том числе очень спорных, о каких уже высказались в других комментариях) говорит о том, что вы показываете не возможности самого плагина, а свое знание новых фич C++. Поэтому я еще писал про поиск работы.
>Мой код завязан на эти фичи потому что они уже здесь, грядут, идут и используются (ну или готовы чтобы их использовали).
Рекомендую изменить свой взгляд в сторону понимания бизнес-задач ваших пользователей. Это вам интересно использовать новые фичи стандартной библиотеки или языка. А пользователю интересно другое: решает ли ваш код его задачи, насколько применение вашего кода упростит его разработку, как внедрение вашего кода повлияет на его цели.
И даже если вы разрабатываете плагинную архитектуру для внутренних целей, следует учитывать вопросы бизнеса, в структуре которого вы находитесь как наемный работник. Порог входа, о каком вы говорите — это дополнительные затраты бизнеса на программистов. Чрезмерное усложнение кода самым последним, самым модным — это большая нагрузка на junior программистов, что повлияет на устойчивость бизнеса и повышение затратов на персонал, повышение затрат на кодирование, поиск ошибок и сопровождение вашего кода.
Также стремление ко всему самому новому может обернуться неожиданными ограничениями, о которых пока не известно. Вы же пишите плагинную архитектуру. Представляете, какие сложности по ее изменению возникнут потом, когда вдруг ваши технические решения окажутся неудачными и придется или мириться с этими сложностями и ограничениями или полностью все переделывать? Уже коллеги вам сказали про проверку типов. Мало того, что это небезопасно, это еще усложняет понимание кода, раздувает его, что обязательно приведет в дальнейшим проблемам: разработчики будут тратить больше мысленных усилий на чтение и понимание кода и будут делать в итоге больше ошибок, удерживая значительную часть памяти ненужными усложнениями.
Надеюсь, мои комментарии были полезны для вас и развития других читателей. Пишу больше для аудитории, а не только для автора статьи. Поэтому не воспринимайте их как критику именно вас или вашего опыта.
>Мой код завязан на эти фичи потому что они уже здесь, грядут, идут и используются (ну или готовы чтобы их использовали).
Рекомендую изменить свой взгляд в сторону понимания бизнес-задач ваших пользователей. Это вам интересно использовать новые фичи стандартной библиотеки или языка. А пользователю интересно другое: решает ли ваш код его задачи, насколько применение вашего кода упростит его разработку, как внедрение вашего кода повлияет на его цели.
И даже если вы разрабатываете плагинную архитектуру для внутренних целей, следует учитывать вопросы бизнеса, в структуре которого вы находитесь как наемный работник. Порог входа, о каком вы говорите — это дополнительные затраты бизнеса на программистов. Чрезмерное усложнение кода самым последним, самым модным — это большая нагрузка на junior программистов, что повлияет на устойчивость бизнеса и повышение затратов на персонал, повышение затрат на кодирование, поиск ошибок и сопровождение вашего кода.
Также стремление ко всему самому новому может обернуться неожиданными ограничениями, о которых пока не известно. Вы же пишите плагинную архитектуру. Представляете, какие сложности по ее изменению возникнут потом, когда вдруг ваши технические решения окажутся неудачными и придется или мириться с этими сложностями и ограничениями или полностью все переделывать? Уже коллеги вам сказали про проверку типов. Мало того, что это небезопасно, это еще усложняет понимание кода, раздувает его, что обязательно приведет в дальнейшим проблемам: разработчики будут тратить больше мысленных усилий на чтение и понимание кода и будут делать в итоге больше ошибок, удерживая значительную часть памяти ненужными усложнениями.
Надеюсь, мои комментарии были полезны для вас и развития других читателей. Пишу больше для аудитории, а не только для автора статьи. Поэтому не воспринимайте их как критику именно вас или вашего опыта.
С чего это вдруг плагины прям вот должны иметь возможность писаться на разных языках? При такой формулировке особо ничего и не сделаешь. Плагин зачастую должен иметь общаться с сервисами основной программы, как это в вашем варианте?
Вопросы «зачем нужен плагин» и последующий «зачем нужна возможность писать плагин на разных языках» возникает из бизнес целей архитектуры Хост ⇄ Плагин.
Плагины помогает программу делать более популярной и более привлекательной для пользователей. Также это помогает независимым разработчикам реализовать возможность построить бизнес на разработке плагинов. Некоторые инди-разработчики и даже целые команды живут исключительно с этого дохода.
Некоторые программы специально разрабатываются как хосты для совместной работы плагинов независимых разработчиков, имея только базовый, ограниченный функционал, но большую экосистему плагинов. Большинство хостов для обработки видео, аудио, изображений, текста немыслимы сейчас без возможности установки сторонних плагинов.
Для конечных пользователей это возможность кастомизировать применение программы в своей области. Пользователем может быть и крупный и мелкий бизнес, где есть свой штат программистов.
Чем проще написать плагин, чем популярней программа, — тем больше шанса, что плагинная архитектура будет задействована. И для этой задачи задача разработчика хоста — сделать эту архитектуру доступной, простой, ясной и привлекательной для разработки.
Стандартный подход для обеспечения возможности писать на разных языках обеспечивается средствами операционной системы делить программы на независимые бинарные модули (dll, so, dylib). Можно вызывать как код из бинарного модуля и наоборот.
Возможно написание плагинов, используя другие средства, например IPC, named pipes, вызов через потоки ввода-вывода консольного интерфейса. Если бинарная возможность ограничена, сторонний плагин может быть загружен и задействован исключительно средствами самой хост программы в виде конфигурационных файлов, скриптовых файлов на разных языках, в том числе специфичных для хоста.
Рекомендую прибегнуть к поисковикам, чтобы рассмотреть эту тему шире.
Плагины помогает программу делать более популярной и более привлекательной для пользователей. Также это помогает независимым разработчикам реализовать возможность построить бизнес на разработке плагинов. Некоторые инди-разработчики и даже целые команды живут исключительно с этого дохода.
Некоторые программы специально разрабатываются как хосты для совместной работы плагинов независимых разработчиков, имея только базовый, ограниченный функционал, но большую экосистему плагинов. Большинство хостов для обработки видео, аудио, изображений, текста немыслимы сейчас без возможности установки сторонних плагинов.
Для конечных пользователей это возможность кастомизировать применение программы в своей области. Пользователем может быть и крупный и мелкий бизнес, где есть свой штат программистов.
Чем проще написать плагин, чем популярней программа, — тем больше шанса, что плагинная архитектура будет задействована. И для этой задачи задача разработчика хоста — сделать эту архитектуру доступной, простой, ясной и привлекательной для разработки.
Стандартный подход для обеспечения возможности писать на разных языках обеспечивается средствами операционной системы делить программы на независимые бинарные модули (dll, so, dylib). Можно вызывать как код из бинарного модуля и наоборот.
Возможно написание плагинов, используя другие средства, например IPC, named pipes, вызов через потоки ввода-вывода консольного интерфейса. Если бинарная возможность ограничена, сторонний плагин может быть загружен и задействован исключительно средствами самой хост программы в виде конфигурационных файлов, скриптовых файлов на разных языках, в том числе специфичных для хоста.
Рекомендую прибегнуть к поисковикам, чтобы рассмотреть эту тему шире.
Чем проще написать плагин, чем популярней программа
Как бы независимость от API и простота написания в основном противоположны, потому что придётся изобретать велосипеды раз за разом.
например IPC, named pipes, вызов через потоки ввода-вывода консольного интерфейса
и система плагинов? оО, это вообще как. Плагин бинарник, я понимаю, но с какого перепуга он должен запускаться самостоятельно в своём выделенном процессе.
Для примера посмотрите именно на существующий софт. Берём браузеры, в каком вы напишете плагины на C++, Delphi или Python, не думаю, что разработчики современных браузеров такие же «недалёкие» как и «я».
Берем Microsoft Office, вот не пахнет вашими идеями. Берём FarManager, аналогичная ситуация.
Если вы для себя выбрали какое-то определение отличное от используемого остальными, это ещё не означает, что ваше определение правильно.
У вас, вероятно, мало опыта в данных вопросах. Лично я писал плагины к разным программам на VC++, GCC, C и Delphi на профессиональной основе. Также использовал плагины, написанные на разных языках.
А вопросы ABI-совместимости C++ в плагинной архитектуре — широко известная проблема.
А вопросы ABI-совместимости C++ в плагинной архитектуре — широко известная проблема.
Примерами плагинов, так или иначе использующих различные варианты IPC, являются:
Можно, конечно, поспорить, что ycmd и LSP-серверы не являются плагинами и т.п., но, на мой взгляд, они отражают идею по-настоящему универсальных плагинов, которые можно интегрировать буквально куда угодно. Подобные возможности интеграции обеспечиваются в первую очередь тем, что взаимодействие построено на основе IPC.
- ycmd, предоставляющий сервис автодополнения, и интегрируемый в текстовые редакторы через плагины, общающиеся с ycmd-сервером через http;
- языковые серверы, предоставляющие сервисы работы с проектами на различных языках программирования, ингенрируемые в редакторы через плагины, общаяющиеся с сервером через LSP;
- NeoVim, в котором даже интерфейс работает через IPC;
- удалённые плагины NeoVim, взаимодействующие с ядром редактора через IPC.
Можно, конечно, поспорить, что ycmd и LSP-серверы не являются плагинами и т.п., но, на мой взгляд, они отражают идею по-настоящему универсальных плагинов, которые можно интегрировать буквально куда угодно. Подобные возможности интеграции обеспечиваются в первую очередь тем, что взаимодействие построено на основе IPC.
Не могу согласиться с тем, что плагины должны быть бинарно независимы.
Для этих целей больше подходит парадигма COM.
Плагинная парадигма построения приложения даёт чуть больше гибкости, в отличии от обычных подгружаемых модулей, как к примеру — dll.
Для этих целей больше подходит парадигма COM.
Плагинная парадигма построения приложения даёт чуть больше гибкости, в отличии от обычных подгружаемых модулей, как к примеру — dll.
Бинарная независимость — это основная идея плагинной архитектуры. Разработчик пишет хост и предоставляет возможность расширения функционала без перекомпиляции хоста.
COM не всегда подходит. Есть плагинные архитектуры, напоминающие COM, например, VST. Есть плагинные архитектуры на основе виртуальных функций (AviSynth), на основе посылки сообщений (OpenFX), как в бинарной форме, так и в текстовой. Есть разные подходы к тому, как регистрировать плагины, через доступ к структуре памяти со списком функций, через отдельные функции по типу dll, через бинарные ресурсы (Photoshop SDK).
В некоторых случаях выбор плагинной архитектуры затрагивает вопросы законности, например, связывание GNU GPL кода с проприетарным кодом. Иногда это обходится плагинной архитектурой с вызовов плагина как отдельный процесс и общение с ним через пайпы консоли.
COM не всегда подходит. Есть плагинные архитектуры, напоминающие COM, например, VST. Есть плагинные архитектуры на основе виртуальных функций (AviSynth), на основе посылки сообщений (OpenFX), как в бинарной форме, так и в текстовой. Есть разные подходы к тому, как регистрировать плагины, через доступ к структуре памяти со списком функций, через отдельные функции по типу dll, через бинарные ресурсы (Photoshop SDK).
В некоторых случаях выбор плагинной архитектуры затрагивает вопросы законности, например, связывание GNU GPL кода с проприетарным кодом. Иногда это обходится плагинной архитектурой с вызовов плагина как отдельный процесс и общение с ним через пайпы консоли.
Кошмар, ужас. Зачем так делать? Зачем переносить проверку типов из compile-time в run-time? Почему бы не использовать специализированные интерфейсы? Шаблоны нормально позволяют это сделать. Делал работу с плагинами, при этом не просто так, а с IoC контейнером в добавок. Всё работает, всё строго типизировано, проверка ошибок в compile-time.
Sign up to leave a comment.
Ещё один С++ plugin framework