![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Обсуждаю статью
voidbent-а (он же Вова Фролов) "General policy pattern".
Она относится к class metaprogramming, на основе C++.
Идея в том, чтобы в некоей библиотеке сложить все классы compile-time policy в один и какие выгоды это даёт.
Спор в комментах.
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
Она относится к class metaprogramming, на основе C++.
Идея в том, чтобы в некоей библиотеке сложить все классы compile-time policy в один и какие выгоды это даёт.
Спор в комментах.
Tags:
(no subject)
16/5/06 03:19 (UTC)(no subject)
16/5/06 03:19 (UTC)--
void
(no subject)
16/5/06 03:20 (UTC)(no subject)
16/5/06 03:21 (UTC)Во-первых, в следующих версиях библиотеки в general policy можно будет добавить сколько угодно новых полиси, и твой старый код будет продолжать компилиться и работать с новой версией.
--
void
(no subject)
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 03:23 (UTC) - Expand(no subject)
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 03:51 (UTC) - ExpandЭто первая шутка в песне.
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 04:41 (UTC) - Expand(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 03:28 (UTC) - ExpandИ вопрос
Posted byRe: И вопрос
Posted by (Anonymous) - 16/5/06 04:49 (UTC) - ExpandRe: И вопрос
Posted by (Anonymous) - 16/5/06 04:53 (UTC) - Expand(no subject)
Posted by (Anonymous) - 16/5/06 03:33 (UTC) - Expand(no subject)
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 04:57 (UTC) - Expand(no subject)
Posted by (Anonymous) - 16/5/06 04:59 (UTC) - Expand(no subject)
Posted by (Anonymous) - 16/5/06 05:00 (UTC) - Expand(no subject)
Posted by(no subject)
16/5/06 03:22 (UTC)В-третьих, general policy задаёт структуру и взаимосвязи всех полиси.
В-четвёртых, ты поведением всей своей системы можешь управлять из одного места.
--
void
(no subject)
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 03:25 (UTC) - Expand(no subject)
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 04:30 (UTC) - Expand(no subject)
Posted by (Anonymous) - 16/5/06 03:26 (UTC) - Expand(no subject)
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 03:34 (UTC) - Expand(no subject)
Posted by (Anonymous) - 16/5/06 03:55 (UTC) - Expand(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted byНедостатки STL с колокольни пропессора
Posted byRe: Недостатки STL с колокольни пропессора
Posted byПолитика реаллокации
Posted byRe: Недостатки STL с колокольни пропессора
Posted byRe: Недостатки STL с колокольни пропессора
Posted byRe: Недостатки STL с колокольни пропессора
Posted byМногопоточность и reference counting
Posted byRe: Многопоточность и reference counting
Posted byRe: Многопоточность и reference counting
Posted byRe: Многопоточность и reference counting
Posted byRe: Многопоточность и reference counting
Posted byRe: Многопоточность и reference counting
Posted byRe: Многопоточность и reference counting
Posted by(no subject)
Posted by (Anonymous) - 16/5/06 03:26 (UTC) - ExpandВот пусть это и будет namespace.
Posted byRe: Вот пусть это и будет namespace.
Posted byRe: Вот пусть это и будет namespace.
Posted byRe: Вот пусть это и будет namespace.
Posted by(no subject)
Posted by(no subject)
Posted byБинго!
Posted byRe: Бинго!
Posted byRe: Бинго!
Posted by(no subject)
Posted by(no subject)
Posted byGeneral Policy Pattern.
16/5/06 03:41 (UTC)1. В следующих версиях библиотеки будет легко добавлять новые полиси. Пользовательский код будет компилиться без изменений. Дефалтовые параметры для этого не подходят, потому что во первых мы не можем первый параметр вызвать дефалтовым а второй нет, а во вторых template template параметры не дружат с дефалтовыми параметрами. Например если кто-то расчитывал в template template параметре что вектор получает 2 параметра то потом в такой вектор третий даже дефалтовый параметр мы добавить уже не можем.
2. Пользователь может переопределить любую из полиси не задумываясь о существовании остальных. В классическом случае это невозможно потому что дефалтовые параметры работают только если они последние в списке.
3. Полиси, особенно если их много, могут предполагать сложную взаимосвясь друг с другом. Причём взаимосвсязь может меняться в зависимости от конкретного набора полиси. У александреску все такие взаимосвязи хардкодяться, и получаються вот такие уродцы:
template
<
typename T,
template class OwnershipPolicy,
class ConversionPolicy,
template class CheckingPolicy,
template class StoragePolicy
>
class SmartPtr
: public StoragePolicy
, public OwnershipPolicy
1. В следующих версиях библиотеки будет легко добавлять новые полиси. Пользовательский код будет компилиться без изменений. Дефалтовые параметры для этого не подходят, потому что во первых мы не можем первый параметр вызвать дефалтовым а второй нет, а во вторых template template параметры не дружат с дефалтовыми параметрами. Например если кто-то расчитывал в template template параметре что вектор получает 2 параметра то потом в такой вектор третий даже дефалтовый параметр мы добавить уже не можем.
2. Пользователь может переопределить любую из полиси не задумываясь о существовании остальных. В классическом случае это невозможно потому что дефалтовые параметры работают только если они последние в списке.
3. Полиси, особенно если их много, могут предполагать сложную взаимосвясь друг с другом. Причём взаимосвсязь может меняться в зависимости от конкретного набора полиси. У александреску все такие взаимосвязи хардкодяться, и получаються вот такие уродцы:
template
<
typename T,
template <class> class OwnershipPolicy,
class ConversionPolicy,
template <class> class CheckingPolicy,
template <class> class StoragePolicy
>
class SmartPtr
: public StoragePolicy<T>
, public OwnershipPolicy<typename StoragePolicy<T>::PointerType>
, public CheckingPolicy<typename StoragePolicy<T>::StoredType>
, public ConversionPolicy
{ ... }
У меня этот пример вылядел бы вот так:
template<typename general_policy>
class SmartPtr : public general_policy::SmartPtrBase<general_policy>
{ ... }
Причём пользователь мог переопределить StoragePolicy не задумываясь о SmartPtrBase и это повлияло бы на SmartPtrBase.
4. Юзер может управлять стратегией использования всей библиотеки меняя всего одно место у себя в коде.
(no subject)
16/5/06 04:00 (UTC)C General Policy можно провести очень чёткую анологию из жизни.
У Александреску Loki напоминает государство в котором есть куча всевозможных книг. В книгах написанны разные законы. Все книги лежат в разных местах. Каждый человек знает только те законы "которые нужны только ему". Законы постоянно меняються и все давным-давно в них запутались.
General Policy выглядит как конституция в которой написаны и структурированны все законы.
---
void
(no subject)
16/5/06 04:02 (UTC)И есть пользовательский код. Который может сказать - у нас конституция будет такая-же как в библиотеке за исключением того что память все, в том числе и эта библиотека должны выделять через GlobalAlloc.
---
void
(no subject)
16/5/06 04:05 (UTC)(no subject)
16/5/06 04:33 (UTC)Как ты там говорил. " " :)
(no subject)
16/5/06 04:37 (UTC)Притва Оккама причём только тогда, когда нету основанний вводить понятие. Если основания есть, а я их написал аж 4-е, то тогда надо разбираться в самих основаниях и принимать их или отбрасывать. Если будут отброшены все 4-е то тогда Бритва Оккама будет опять причём.
(no subject)
18/5/06 00:18 (UTC)Это как раз и есть большой недостаток ГП.
В любом случае дать пользователю возможность выбирать между char и wchar это лучше чем не дать пользователю возможности вообще что либо выбирать
Согласен. Но STL таки позволяет это делать - ты волен использовать такой базовый символ для строки, какой хочешь.
Если система так построена, что в одном месте она работает с char а в другом c wchar, в одном с дефалтовыми аллокаторами, а в другом со специальными, то даже без ГП у тебя возникнет проблема что всем этим "местам" будет очень трудно друг с другом взаимодействовать
Дело в том, что в большой системе неизбежно возникает куча мест с отклонениями от "генеральной линии партии", то бишь от всесистемного ГП. То в одном месте нужно вместо Юникода пропихивать обычные char для совместимости со сторонней либой. То появляется какой-то класс, для которого выделять память стандартным образом чересчур неэффективно. То <сам придумай> :-)
Теперь попробую немного конструктива:
В случае с ГП, для каждого отклонения от всеобщей ГП некой библиотеки в нашей системе нужно создавать наследника от ГП библиотеки и в нём перекрывать то полиси, которое нас не устраивает.
А нельзя ли как-то прикрутить туда идею сборки сущности из мелких кусочков, как в одной из Бустовских библиотечек. Я сейчас не вспомню точно, но, кажется, это были именованные параметры. Если надо будет - поищу ссылки и оформлю идею менее расплывчато, но можешь покопаться сам, если знаешь где.
Если удастся заюзать идею, то мы поимеем все плюсы ГП за вычетом этого минуса с невообразимым количеством наследников от ГП библиотеки: нужные нам "отклонения" можно будет задавать без наследования.
(no subject)
18/5/06 00:22 (UTC)(no subject)
18/5/06 04:18 (UTC)Кстати у меня была ситуация на практике когда часть программы использовала std::string а часть std::wstring и это было реальной проблемой и угрозой всего проекта. И я от друга слышал что и у него в проекте была та-же самая проблема. Я представляю что-бы было если бы в этом моём проекте часть кода использовала дефалтовые аллокаторы, а часть - спецефические. Начался-бы полный ад. И это всё только к вопросу о полиси. В STL-е нету никаких ГП там есть только пара полиси и всё.
Так что я считаю что это сильная сторона ГП а не слабая. ГП будет стимулировать всех подчиняться партии и не отклоняться от её главной линии.
Проблема как-раз в том что это одна из немногих вещей которые STL позволяет, и есть ещё куча всего которое STL не позволяет и это не позволяет использовать STL во многих ситуациях. Например управлять тем будут ли строки ref-counted или будут ли итераторы безопасными или быстрыми как я уже не раз говорил.
Так что даже использовать именованные параметры я не вижу смысла. Хотя технически они осуществимы и при этом довольно легко. Технически осуществимы и type factory разные которые сами бы наследовались от ГП и подставляли то что им скажут туда куда нужно, и в итоге эти все 50 всевозможных генерал полиси даже именовать бы не пришлось.
Я уже это говорил, но повторю ещё раз. ГП - это аналог конституции в реальном мире. В ГП собраны и систематизированны законы которым должна подчиняться вся система.
Витя говорил что General - это плохо. Конституция - это general. А теперь вопросы:
1. Конституция это хорошо или плохо?
2. Насколько хорошо\плохо делать конституцию локальной для каждого города отдельно а не государства в целом?
3. Как часто каждому из нас приходиться нарушать конституцию?
4. Насколько хорошо\плохо государсту что некоторые нарушают конституцию?
5. Насколько хорошо\плохо каждому из нас что некоторые нарушают конституцию?
6. Насколько целесообразно было-бы придумать "именованные законы" которые позволяли бы делать что-то противоречащее конституции законным образом?
7. Насколько судам легко было-бы работать с "именованными законами"?
И я на всякий случай ещё раз повторю: Всё что имеет тенденцию меняться выносите в иерархии классов а не в полиси и используйте полиморфизм времени выполнения а не времени компиляции. ГП, точно так-же как и обычное полиси, точно так-же как и законы и конституция в реальном государстве не предназначенны и не могут решить проблем для которых характерна динамика.
PS.
(С) симпсоны.
(no subject)
18/5/06 04:47 (UTC)Насколько ценным был бы ГП паттерн если бы кто-то заимплеменил type factory, о котором я говорил, и ГП стал-бы ещё одним велосипедом с квадратными колёсами, предназначенным решать проблемы связанные с динамикой?
(no subject)
19/5/06 03:08 (UTC)Именно. Я не считаю вариант с одной-единственной ГП на всю систему жизнеспособной. Какая-то сферическая система в вакууме получается.
В реальной большой системе практически наверняка будет куча мест с отклонениями от ГП. Особенно с библиотекой размаха STL.
Если ГП одна на систему, это аналогично ситуации, когда у тебя есть огромное число версий библиотек, каждая из которых реализует один из возможных вариантов настроек полиси, и этот вариант в каждой версии намертво захардкожен и менять его нельзя. Абсолютно идентичная вещь - вся система использует один и тот же набор полиси, всё биндится на этапе компиляции, набор полиси легко меняется изменением одного дефайна в мэйк-файле (грубо говоря).
Удобно?
ГП - это аналог конституции в реальном мире
Скажи мне, плз, встречал ли ты идеальную конституцию и идеальные подходящие для всех и всегда законы?
П.С. Я не спорю с тем, что классно иметь механизм для прозрачного подключения новых возможостей и настроек, я против того, что ГП должна быть одна на систему.
(no subject)
19/5/06 04:57 (UTC)Угу ... это именно то о чём я говорю. Проблемы начинаются когда один класс хочет синхронизироваться а другой не хочет. Один класс хочет быть юникодовым а другой не хочет и т.д. Причём если многопоточность очень жестоко карает тех, кто синхронизироватся не хочет, то проблемы с юникодами вылазят обычно уже когда клиент начинает жаловаться что программа портит оригинальные данные.
Угу ... если система реальная и большая, и такие отклонения трудно найти то они будут наносить максимум вреда. У STL кстати размах совершенно небольшой. У TR1 размах капельку по больше, а вот у TR2 уже размах так размах.
[skipped]
Я не понял эту фразу если честно. Если можно то приведи пример. Саму ГП мы можем менять хоть каждый день. Главное что-бы от ГП не отклонялся никто.
А я и не говорил что ГП предполагает быть идеальной. Совсем даже наоборот. ГП предполагает что если стратегия оказалась не идеальной, то её можно легко поменять, и вся система окажется при этом работоспособной. При условии естественно что все соблюдают ГП.
(no subject)
Posted by(no subject)
Posted by(no subject)
19/5/06 00:36 (UTC)(no subject)
19/5/06 00:56 (UTC)(no subject)
19/5/06 02:46 (UTC)Ладно, я ещё раз повторю: Полиси паттерн не предназначен решать задач связанных с динамикой. Для этого есть куча других более эффективных методов. Соответственно генерал полиси унаследовал эту особенность от полиси паттерна. Сам генерал полиси можно менять хоть по 50 раз на день но подчиняться ему должны все. А вы говорите о том что-бы сам генерал полиси не менять никогда, но что-бы ему не подчинялся вообще никто.
Вы мне говорите о том что если не подчиняться генерал полиси то в системе начнёться полный беспредел. Да, начнёться!!! Но он так-же само начнёться и без генерал полиси паттерна если каждый класс сам для себя будет решать он мультитредовый или нет. Или он юникодовый или нет. Или каким образом он будет память выделять. И ещё куча всяких или.
Вы говорите что бывают случаи когда надо не подчиниться генерал полиси и сделать всё по своему. Ну тогда вы должны понимать какие это повлечёт за собой последствия - с вами никто из тех кто подчиняется генерал полиси не сможет взаимодействовать без риска поломать всю систему, нарушить требования к системе, нарушить стабильность системы, нарушить целосность данных и т.д. И ещё куча всяких "нарушить". Это всё касается кстати и обычных полиси а не только ГП.
Вы начинаете пытаться строить из генерал полиси метод для решения задач, связанных с динамикой, у вас получается велосипед с квадратными колёсами и из этого вы заключаете что генерал полиси или вообще не применим или применим если к его квадратным колёсам приделать именованные параметры. Да, для решения задач связанных с динамикой ГП не применим! У него совершенно другая область задач - такая-же как и у полиси паттерна.
Для того что-бы говорить о применимости\неприменимости противоречивости\непротиворечивости генерал полиси паттерна нужно понять в начале для каких задач применяется полиси паттерн, и почему в случаях с полиси паттерном не эффективно использовать полиморфизм времени выполнения. А не пытаться видеть во всём проблемы времени выполнения и рассматривать все паттерны относительно того на сколько хорошо они эти проблемы решают.
ГП не применим для проблем времени выполнения. И полиси и генерал полиси и вообще темплейты в С++ очень тяжело а иногда и вообще невозможно применять для архитектур, которые подразумевают плугины а не монолитную систему.
Я с этим вообще не спорю. Зато наследование отлично применимо для построения плугиновой архитектуры.
Кстати я не понимаю как класс вообще может меняться при компиляции. В моём понимании класс может меняеться только программистом. Я говорю о том что сам генерал полиси можно менять сколько угодно, если при этом система не начиет ему противоречить (Например какой-то класс в обход генерал полиси наотрез отказывается использовать синхронизацию для своих статических данных). И сам генерал полиси подразумевает что его могут поменять и система при этом останется целостной. Зато ГП не подразумевает что кто-то будет действовать в обход ему.
(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
22/5/06 02:05 (UTC)2. Механизм замены dll'ек - довольно точная аналогия использования библиотеки, у которой единственная возможность настройки полиси - через ГП.
3. В случае с ГП, вся система будет вынуждена использовать этот самый super-puper-mega-wide.
(no subject)
22/5/06 02:44 (UTC)Кстати ГП придумывался не сам по себе а в контексте создания TR2. Я хотел показать что старыми методами (полиси) будет очень трудно создать библиотеку такого масштаба.
2. Не понял.
3. Нет. В случае с ГП вся система может использовать что угодно. super-puper-mega-wide будет использовать вся наша библиотека. Кстати вся система у себя тоже этот аспект может не хардкодить через ГП.
(no subject)
22/5/06 23:26 (UTC)2. Что именно непонятно? Спрашивай, объясню.
3. В случае с ГП вся система может использовать что угодно.
Ну расскажи мне, каким образом. Есть у нас STL, и мы пользуем ГП, в котором сказано "использовать для строк wide char". И вот в один прекрасный момент нам понадобился тип символа "только цифра". Написали мы этот класс, написали трейты к нему и хотим теперь создать строку из наших замечательных символов. А система нам "фиг вам, я STL'ные строки умею создавать только из wide char. У меня ГП такая". И как с этим быть?
(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
Posted by(no subject)
23/5/06 01:01 (UTC)1. Для начала надо разобраться что такое полиси, зачем оно нужно и когда его нужно применять. Без этого весь наш спор становится бессмысленным. Я расказываю о полиси а вы мне о замене dll'ек.
2. Полиси и dll'ки имеют разный круг решаемых задач. В статье я расказываю о полиси и о генерал полиси. Почему это вруг я должен в статье расказывать про всё остальное? Это не КНИГА про написание БИБЛИОТЕК вообще. Это СТАТЬЯ которая расказывает про ГЕНЕРАЛ ПОЛИСИ и написание ОБОБЩЁННЫХ БИБЛИОТЕК а не динамических.
3. А что я должен был написать ещё в статье? Что-то типа такого : "Наследование, Динамические библиотеки, Полиморфизм времени выполнения, абстрактные классы, интерфейсы, указатели, макросы, это всё то к чему ГП не имеет прямого отношения, но и не отменяет всё это" Так?
Продолжать спор дальше я не вижу смысла. Мы разговариваем на разных языках про разные вещи.
(no subject)
24/5/06 01:06 (UTC)Я не вижу смысла продолжать спор не из за того что "никто не понимает мой "гениальный" ГП". А из за того, что аргументы пошли по кругу (по 4-му если я не ошибаюсь). не могу понять в каких случаях хорошо иметь много разных ГП а вы не можете понять почему плохо не придерживаться одной ГП.
Я думаю дальше наш спор могла бы решить генерик библиотека написанная с использованием ГП. И программа, написанная с использованием этой библиотеки. У меня такой библиотеки пока нет, и думаю будет она не скоро.
Когда она появиться, тогда можно будет судить уже на конкретном примере, и тогда возможно общий язык найти получиться.