Здравствуйте, alexeiz, Вы писали:
A>А вообще, книга описывает основные паттерны проектирования, которые нужно уже давно знать и использовать самому. Нельзя изучать паттерны по книге Александреску. Нужно прочитать Gang of Four и попробовать делать так как там написано. А потом, когда надоест писать горы однотипного кода и появиться желание как-то автоматизировать этот процесс, то тут приходят на помощь идеи Александреску.
A>Если ты не используешь паттерны. Александреску тебе ничего не даёт, а просто сотрясает воздух в пустую.
Я бы так сказал, что про паттерны можно поговорить особо.
Вообще есть некоторое кол-во паттернов, действительно полезных и попадающихся в реальности.
Но большинство из них -- ИМХО вещь в себе, возникшая от необходимости двишать науку, а не из практических соображений.
Ну а Александреску -- это уже пожалуй вторая производная.
А вообще интересно, почему тебе кажется, что скорее LISP, а не Prolog?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, alexeiz, Вы писали:
A>>А вообще, книга описывает основные паттерны проектирования, которые нужно уже давно знать и использовать самому. Нельзя изучать паттерны по книге Александреску. Нужно прочитать Gang of Four и попробовать делать так как там написано. А потом, когда надоест писать горы однотипного кода и появиться желание как-то автоматизировать этот процесс, то тут приходят на помощь идеи Александреску.
A>>Если ты не используешь паттерны. Александреску тебе ничего не даёт, а просто сотрясает воздух в пустую.
E>Я бы так сказал, что про паттерны можно поговорить особо. E>Вообще есть некоторое кол-во паттернов, действительно полезных и попадающихся в реальности. E>Но большинство из них -- ИМХО вещь в себе, возникшая от необходимости двишать науку, а не из практических соображений.
Без конкретных примеров твоё утверждение не имеет большой силы. Что ты имеешь ввиду под большинством? Откуда ты берешь паттерны, из которых большинство является вещью в себе? Вот я для примера взлянул на паттерны из Gang of Four. Больше половины (т.е. большинство) паттернов я могу описать только глядя на название. Соответственно я их характеризую как действительно полезные и попадающиеся в реальности.
E>Ну а Александреску -- это уже пожалуй вторая производная.
Т.е. ты хочешь сказать, что так как паттерны по большей части вещь бесполезная, то описанные в Александреску будут бесполезными в той же пропорции. Давай возьмём паттерны описанные в Александреску, и ты скажешь, что из них вторая производная:
Я бы сказал, что всё кроме мультиметодов из этого списка является действительно полезным и часто применяемым.
E>А вообще интересно, почему тебе кажется, что скорее LISP, а не Prolog?
Typelists, head, tail, рекурсивные обработки списков — это Lisp чистой воды.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>"Навёрнутые" или не "навёрнутые" — это субъективное мнение. Мне сейчас это не кажется навёрнутым. Просто другая форма записи тем же самых вещей. Не вижу никакой принципиальной разницы между включением нескольких указателей на динамические интерфейсы или включением нескольких указателей на статические интерффейсы. Синтаксис немного другой. Да, у шаблонов синтаксис порядочно сложнее, с этим согласен. Вначале снепривычки было сложно, но сейчас практически одинаково.
E>У шаблонов есть много "преимуществ" E>1) Намного хуже, чем в случае интерфейсов заданы правила использования. В результате грамотный шаблон написать труднее (больше надо всегопредусмотреть), и воспользоваться труднее (надо выбрать из большего числа мыслемыз альтернативных способов использования)
Ничто не мешает задать их так же явно. Например так:
//Класс TLog должен быть copy-constructable и иметь следующий интерфейс:struct TLog
{
void log(const std::string&);
int fff();
};
В следующей версии стандарта языка эту проблему возможно решат более элегантно.
Зато и возможностей больше. Гораздо больше. Причём принципиально новых. Вспомни хотя бы std::vector<>! Как ты его предлагаешь реализовывать без шаблонов? Или ты его не используешь?
E>2) Намного более сложный синтаксис и семантика. Вот, например, что тут написано: E>
E>template<typename TLog>
E>class Base {
E>protected
E> void exit( int );
E>};
E>template<typename TLog>
E>class MyExitProicessor : public Base<TLog> {
E>public:
E> void OnExit( TLog& log, int code )
E> {
E> LogExit( log, code ); // это какой-то метод MyExitProicessor, описанный ниже
E> exit( code );
E> }
E>};
E>
Имхо. Всё понятно. Кстати, лучше писать "this->LogExit()" и "this->exit()", тогда и понятнее будет.
E>3) Очень неудобные сообщения об ошибках в пользовательском коде.
В большинстве случаев точно такие же как и без шаблонов. Надо просто их внимательно прочитать, а не говорить сразу "ух ты #$%, я это даже читать не буду". Вот ещё здесь.
E>А вот реальные приимущества всех этих трюков Александреску они в чём?
Меньше дублирования. Лучше понятны намерения программиста. Аспекты лучше выделены, а не замешаны в один клубок. Но это всё достигается за счёт наличия более сложного (интеллектуального) кода.
Я так считаю: можно иметь или много "тупого" кода (я его называю "raw"), это когда много накопипастеных функций, или меньше кода, но более "интеллектуального".
Кстати, можно узнать про твоё отношение к исключениям. Ты их используешь в с++?
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Аноним, Вы писали:
E>1) Мне нравится книжка Александреску (которая современное проектировнаие на C++). Но странною любовью нравится.
[порезана инструкция по применению книжки Александреску]
Александреску сам месяц тому назад писал в clcm что скажет "До свидания" любому кто на интервью начнет писать громадные классы вместо for из двух строчек для того что-бы показать как работает for_each.
В этом то и состоит опыт программирования, когда ты изучаешь STL ты вставляешь его везде где не попадя и он вызубрен наизусть. Но когда уже есть опыт работы с STL ты понимаешь что вот здесь лучше забыть про него вообще а использовать (нервным попрошу удалиться из зала) ААААА!!!! указатели не защищенные shared_ptr
Всему надо знать меру, хорошая еда получаеться при правильных пропорциях а не когда "всего много".
Здравствуйте, qqqqq, Вы писали:
Q>Книжка Александреску хороша, нет слов, да только не всегда все это все в пользу. Если програмируешь в основном один и очень хорошо в этом сам разобрался то конечно, да... А если работаешь в большой разнородной команде с текучкой где не все С++ программисты про итераторы слышали, то применение изощренных приемов из этой книги может заметно мешать. Только "избранные" смогут этот код понимать даже в приципе а поддерживать все "это" придется самому.
Когда слышу такие тезисы, у меня сразу возникает желание ответить следуещее:
Ну хорошо шаблонное программирование на полную силу не используем, т.к. могут придти программисты не знакомые с этим.
Так же не используем исключения, т.к. много неопытных программистов или программистов старой закалки с ними тоже не в ладах.
Ещё не используем контейнеры и алгоритмы стандартной библиотеки, т.к. многие так её и не освоили или вообще считают ересью.
Ни о каком boost и loki речи вообще не идёт.
Не используем паттерны проектирования и сложную архитектуру, т.к. могут придти программисты не разбирающиеся в этом.
Ну хорошо, назовите же уже те 20 функций из С, которые можно использовать в проекте! (больше 20 нельзя, вдруг у программиста будет плохая память)
Т.е. ты предлагаешь взять пересечение множеств умений всех программистов, которые работают и могут работать в будущем над проектом.
Существуют более прогрессивные методы управления процессом разработки, которые позволяют использовать не пересечение, а объединение возможностей программистов. think about it.
Q>Если поручат исправить простую ошибку менее квалифицированному кадру то он запросто там таких дров наломает, что все равно потом к тебе прибегут за помощью, когда гром грянет.
Ну и при чём тут шаблонное проектирование???
Если "менее квалифицированный кадр" будет работать один, то он где угодно сможет дров наломать.
Вообще это любого языка касается, но с++ особенно. Если менеджер посадил "менее квалифицированный кадр" писать код на с++, то чего он собственно ожидает?
Q>Но если тайная цель все под себя подмять в такой разнородной команаде то да, надо напихать в программу побольше патернов, темплейтов из этой и других подобных книг, замешать с STL, Loki, boost и АСЕ, и еще написать описание соответствено — цены тебе не будет. Видел я и проекты написанные на "обычном" C++ и исключительно advanced код, так вот те простые чаще были более удачные.
Здравствуйте, Chipsеt, Вы писали:
C>Здравствуйте, Erop, Вы писали:
E>>Здравствуйте, Аноним, Вы писали:
E>>1) Мне нравится книжка Александреску (которая современное проектировнаие на C++). Но странною любовью нравится.
C>[порезана инструкция по применению книжки Александреску]
C>Александреску сам месяц тому назад писал в clcm что скажет "До свидания" любому кто на интервью начнет писать громадные классы вместо for из двух строчек для того что-бы показать как работает for_each. C>В этом то и состоит опыт программирования, когда ты изучаешь STL ты вставляешь его везде где не попадя и он вызубрен наизусть. Но когда уже есть опыт работы с STL ты понимаешь что вот здесь лучше забыть про него вообще а использовать (нервным попрошу удалиться из зала) ААААА!!!! указатели не защищенные shared_ptr C>Всему надо знать меру, хорошая еда получаеться при правильных пропорциях а не когда "всего много".
Да, но читать-то и знать всё это надо.
Энание и опыт не придёт никак иначе, кроме как через использование.
Вначале я не знал про for_each. Потом я знал про for_each, но не умел его применять. Потом я научился его применять и начал юзать везде где только можно и нельзя. Потом я понял, что это сакс и понял какие у него проблемы.
Зато теперь я знаю его вдоль и поперёк, я знаю, где его можно применить, а где нельзя. Я понимаю, зачем появился BOOST_FOREACH и т.д.
Может менеджеру или другому программисту конечно и не нравиться, что в промышленном коде появились for_each там, где не надо. Но пусть в конце концов отрефакторят или я сам это сделаю рано или поздно.
А есть программисты, которые сразу считают for_each — сакс, я его ни разу не применял, но всё равно это сакс.
Всё это перекликается ещё с такой мыслью, что все эти библиотеки, паттерны и приёмы — это готовые решения типовых проблем. И если программист ещё не сталкнулся с этой проблемой, или скорее сталкнулся, но для него ещё не стало очевидно, что это проблема, и что хорошо бы иметь готовое решение для неё, у этого программиста такие вещи, конечно, не будут вызывать ничего кроме недоумения. Конечно он будет говорить, что это ненужное усложнение.
Здравствуйте, alexeiz, Вы писали:
A> Соответственно я их характеризую как действительно полезные и попадающиеся в реальности.
Абсолютно согласен. Паттерны вообще это обобщение реального опыта проектирования приложений. Т.е. паттерны это не некие синтетические конструкции, а некие часто встречающиеся и возникающие вполне естественным путем(в результате грамотного или неграмотного проектирования) идиомы проектирования.
И естественно, как и любой другой опыт со стороны применение паттернов не всегда дает хороший результат. Любой инструмент и идиому нужно выбирать и применять с умом. Понимание и знание паттернов иногда позволяет выбрать подходящее архитектурное решение, но это не значит что применять их нужно направо и налево. Кстати зачастую паттерны применяются неосознанно и всплывают в дизайне людей совершенно незнакомых с таким понятием как таковым. Да и вообще паттерн он на то и шаблон/образец, теоретически можно обобщить в паттерн самый разный дизайн. Проблема только в том, что зачастую такой паттерн будет кривым и некрасивым(как и дизайн ). А вот паттерны вроде паттернов GoF это попытка обобщить именно положительный опыт.
Вообще архитектура и дизайн это далеко не только паттерны, это сложная и практически всеобъемлющая тема. Об этом можно говорить и спорить практически бесконечно. Есть люди которые прекрасно живут, и реализуют проекты и без паттернов, да и вообще практически без архитектуры(т.е. без осознанной архитектуры). Есть люди которые занимаются проектированием в первую очередь(не говоря уже о такой загадочной профессии как архитектор). В конце концов есть подходы вроде XP(которые мне лично наиболее симпатичны в данный момент времени). И конечно так сразу не скажешь кто здесь абсолютно прав, а кто совершенно нет.
A>Я бы сказал, что всё кроме мультиметодов из этого списка является действительно полезным и часто применяемым.
Нельзя не согласиться. Не говоря уже о более приземленных вещах, которые очень хорошо описанны в книге.
E>>А вообще интересно, почему тебе кажется, что скорее LISP, а не Prolog? A>Typelists, head, tail, рекурсивные обработки списков — это Lisp чистой воды.
А вот здесь не совсем согласен. Списки, рекурсивная обработка, head, tail свойственны и для Пролога. Да и мне лично показалось, что реализация всего этого в Loki действительно больше напоминает Пролог, чем Lisp(на момент первого прочтения книги я был знаком и с тем, и с другим).
Почему?
1. Если-бы это был Lisp чистой воды, то вместо head и tail были бы car и cdr.
2. Параметры шаблонов и "переменные" пролога роднит общепринятая практика писать первые заглавными буквами(вторые иначе просто и нельзя записать).
3. Паттерн-мэтчинг(которого кстати нет в Лиспе) Пролога удивительным образом по духу напоминает специализацию в C++.
Но на самом деле конечно ни Prolog, ни Lisp здесь совершенно не причем(тем более что Александреску скорее всего имеет поверхностное знакомство и с тем, и с другим). Typelists из Loki это скорее результат "синтеза" знаний о нескольких функциональных языках, в которых списки являются основной структурой данных, в первую очередь ML и Haskell(оба языка кстати вскользь упоминаются в книге). Конечно речь идет о чисто внешних деталях реализации, так сказать эстетике, поскольку насколько мне известно Александреску вроде бы не пионер в данном направлении программирования на C++. Первые опыты на эту тему скорее всего были "вдохновленны" именно Лиспом.
Здравствуйте, Erop, Вы писали:
E>3) Ещё Александреску конечно очень хорошо показал, что шаблоны C++ можно использовать как очень плохую и неудобную и практически неолаживаемую версию языка Prolog. Но совсем не раскрыл тему "зачем так извращаться?" Может лучше пролог заботать да и писать макеты на нём, ну а в реализации это всё скорее всего не нужно будет
Ээ, простите, а где там пролог?
Ленивый, чисто функциональный язык есть, но вот пролог
Здравствуйте, Аноним, Вы писали:
E>>3) Ещё Александреску конечно очень хорошо показал, что шаблоны C++ можно использовать как очень плохую и неудобную и практически неолаживаемую версию языка Prolog. Но совсем не раскрыл тему "зачем так извращаться?" Может лучше пролог заботать да и писать макеты на нём, ну а в реализации это всё скорее всего не нужно будет
А>Ээ, простите, а где там пролог?
Там же где и эпилог А>Ленивый, чисто функциональный язык есть, но вот пролог
Ну как бы , если тебе кажется, что там больше похоже на другой "не C++" язык, то заради Бога. Какое это имеет влияние на практическую ценность книжки?
Ну а на пролог похоже, потому что правила сопоставления предикатов пролога очень похожи на правила вывода аргументов шаблона и применения частичных специализаций. В частности, очень похожая техника работы со списками, например
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, remark, Вы писали:
R>Всё это перекликается ещё с такой мыслью, что все эти библиотеки, паттерны и приёмы — это готовые решения типовых проблем. И если программист ещё не сталкнулся с этой проблемой, или скорее сталкнулся, но для него ещё не стало очевидно, что это проблема, и что хорошо бы иметь готовое решение для неё, у этого программиста такие вещи, конечно, не будут вызывать ничего кроме недоумения. Конечно он будет говорить, что это ненужное усложнение.
Я в целом согласен, что во всей теории есть и полезное. Я, например, зачем-то книжку таки почитал и Loki посмотрел
Но на практичке я постоянно встречаю людей, которые применяют налево и направо навороты, и совсем не встречаю, таких, которые пишут плохо, потому что наворотов от Александреску не применили
Ну на самом деле задачи просто проще методов Александреску. Увы, такая вот жизнь вокруг меня. Хотя программы в целом непростые, так скажем. И программисты квалифицированные.
Ещё могу поделиться такой историей. У нас тут был недавно сотрудник, который очень хоршо знает и паттерны и STL и вообще всё. Настолько хорошо, что препадаёт это всё в одном уважаемом очень ВУЗе
НУ так вот этот достойный мужчниа нарожал за пол-года море кода, которые потом весь таки извели,заменив радикально более простым и удобным. Но довольно простую прикладную задачу так и не решил
Мало того, то что за последующий год весь его код похерели, это не результат какой-то целенаправленой деятельности по "выжиганию калёным железом", а просто так получилось, потому что так было удобнее. В каждом месте оказалось удобнее не пользоваться наукой
Я это к тому, что до этого случая я думал, что такая, довольно стандартная для не шибкоопытных программистов ситуация, повторилась и у человека довольно знающего и опытного и хорошего. Мне он всегда был симпатичен, но он реально не смог.
Хотя у нас тут задача, которая стояла перед ним, не кажется сложной. Я бы её решил за месяц наверное. Может даже быстрее.
Мало того, потом, с нуля, очень похожую задачу, под руководством довольно мудрого руководителя, решил стажёр. Решил за три с половиной месяца. Правда и стажёр был умный, но он был ориентирован как раз на результат и код "попроще"
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, remark, Вы писали:
R>Кстати, можно узнать про твоё отношение к исключениям. Ты их используешь в с++?
R>
Исключеня и использую, как и шаблоны и паттерны и много чего ещё. Но я прдерживаюсь парадигмы, что сложное средство нужно использовать только тогда, когда это неизбежно и необходимо. То есть стараюсь писать максимальноп росто.
А вот встречаемые мной в жизни последователи А. стремяться писать так сложно, как только возможно.
Ну а конкртено для исключений я придерживаюсь таких ограничений:
1) Использую для обработки ошибок, но при этом обработчики располагаю в строго регламентированных местах.
2) Использую для обработки запроса пользователя прервать длительную процедуру
3) Использую в некоторой хитрой алгоритмической конструкции. Общее описание давать долго. Дам пример.
Строим сложный объект, содержащий много частей, ссылающихся друг на друга. Объект строим в буфере. С самого начала задаём размер буфера, которого обычно хватает с небольшим запасом. Когда его не хватает -- бросаю исключение, которое ловится в функции создания объекта. Тогда буфер переаллокируется в полтора раза больше и процесс построения объекта повторяется с начала.
Отдельная тема -- что должно происходить с кодом при возникновении исключений. Могу рассказть и про это.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, remark, Вы писали:
R>Ничто не мешает задать их так же явно. Например так: R>
R>//Класс TLog должен быть copy-constructable и иметь следующий интерфейс:
R>struct TLog
R>{
R> void log(const std::string&);
R> int fff();
R>};
R>
R>В следующей версии стандарта языка эту проблему возможно решат более элегантно.
Возможно решат, возможно не решат. Я так думаю, что решат, но не ту.
Но в текущем полложении дел есть несколько пробоем.
1а) Никто не гарантирует тебе, что этот твой комментарий соответсвует действительности. Вдруг *на самом деле* ты требуешь от TLog чего-то ещё. Или, наоборот, чего-то пока что не требуешь?
1б) НИкто не гарантирует, что твой комментарий будет правильно понят пользователем. Вдруг он напишет метод int& fff()? И в текущей версии шаблона всё будет хорошо, а потом ты что-то захочешь поправить? А формальной проверки не выполняется.
1в) Не понятно что делать, когда этот коментарий устаревает. Формальных проверок или нет или они чудовищны и ненадёжны. Вот понадобилось тебе, чтобы, скажем, сделать fff возвращал const MyInt&? Что вот делать? Вычитывать весь клиентский код во всех сделвнных на этом шаблоне проектах?
Кроме того, есть у меня такое практическое наблюдение, что когда кто-то пишет шаблон и он при этом не супер спец этого дела, то получается изделие с неясной семантикой. Обычно я не придираясь, а просто стараясь понять что и как там втыкается, задаю вопросы, которые ставят авторов в тупик
Общий смысл такой, что править шаблоны обычно дико дорого, поэтому их можно использовать либо в виде каких-то библиотечных очень хорошо отлаженных примитивов, скажем контейнеров. Либо в каких-то герметичных участках кода, где от чего-то надо несколько раз сдублировать код. Но только второе надо делать уже очень с опаской. Опять же про переиспользование таких шаблонов лучше всего забыть как правило сразу
R>Зато и возможностей больше. Гораздо больше. Причём принципиально новых. Вспомни хотя бы std::vector<>! Как ты его предлагаешь реализовывать без шаблонов? Или ты его не используешь?
Конечно я не возражаю, против шаблонного массива. Но std::vector те не менее не использую. У нас в конторе есть своя, более древняя библиотечка, которая конечно хуже STL, но предсказуемее. Например там более очевидны временные сложности операуий
Ну а если ты о тех новых возможностях, про которые пишет Александреску, то, ИМХО, они лишние
E>>2) Намного более сложный синтаксис и семантика. Вот, например, что тут написано: E>>
E>>template<typename TLog>
E>>class Base {
E>>protected
E>> void exit( int );
E>>};
E>>template<typename TLog>
E>>class MyExitProicessor : public Base<TLog> {
E>>public:
E>> void OnExit( TLog& log, int code )
E>> {
E>> LogExit( log, code ); // это какой-то метод MyExitProicessor, описанный ниже
E>> exit( code );
E>> }
E>>};
E>>
R>Имхо. Всё понятно. Кстати, лучше писать "this->LogExit()" и "this->exit()", тогда и понятнее будет.
Может и лучше, но значит будет другое. Вообще-то в выделенной строке зовут функцию сишную exit . E>>3) Очень неудобные сообщения об ошибках в пользовательском коде.
R>В большинстве случаев точно такие же как и без шаблонов. Надо просто их внимательно прочитать, а не говорить сразу "ух ты #$%, я это даже читать не буду". Вот ещё здесь.
К несчастью мне приходится это читать регулярно. Я так тебе скажу, что до изобретения STL я не встречал сообщений об ошибках, которые не помещаются в окно консоли E>>А вот реальные преимущества всех этих трюков Александреску они в чём? R>Меньше дублирования. Лучше понятны намерения программиста. Аспекты лучше выделены, а не замешаны в один клубок. Но это всё достигается за счёт наличия более сложного (интеллектуального) кода. R>Я так считаю: можно иметь или много "тупого" кода (я его называю "raw"), это когда много накопипастеных функций, или меньше кода, но более "интеллектуального".
Прости, но мне кажется, что все преимущества, кроме "Лучше понятны намерения программиста" достигаются хорошим проектированием и реализацией кода задачи, а вовсе не применением головоломных конструкций из шаблонов
Что же касается намерений, то я согласен, что они понятны. Они обычно (явно или просто по факту) состоят в том, чтобы удорожить разарботку и сопровождение.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>Кстати, можно узнать про твоё отношение к исключениям. Ты их используешь в с++?
R>>
E>Исключеня и использую, как и шаблоны и паттерны и много чего ещё. Но я прдерживаюсь парадигмы, что сложное средство нужно использовать только тогда, когда это неизбежно и необходимо. То есть стараюсь писать максимальноп росто. E>А вот встречаемые мной в жизни последователи А. стремяться писать так сложно, как только возможно.
Ну я так понял, что используешь. К чему я это.
Допустим есть достаточно крупное приложение.
Раньше были коды ошибок, которые возвращались из каждой функции. Соответственно после вызова каждой функции код ошибки проверяется, и если ошибка, то код передаётся выше.
Решение максимально простое, понятное, явное (при просмотре кода и дебаге всё видно, всю логику). для использования не надо знать ничего сложного (надо просто знать, как возвращается результат из функции, ну я думаю это знает каждый программист).
Я лично считаю такой подход устаревшим и не подходящим для больших поддерживаемых проектов. Я считаю, что обработка ошибок с помощью исключений гораздо более адекватна задаче. Судя по тому, что ты написал (
"Использую для обработки ошибок, но при этом обработчики располагаю в строго регламентированных местах"
), ты тоже так считаешь.
В крации приемущества: единая система ошибок и политика обработки, не надо "протаскивать" код ошибки через все функции, нет возможности игнорировать ошибку и "забыть" проверить код ошибки и т.д.
Но этот подход гораздо более сложней и главное для его реализации надо знать гораздо больше: механизм распространения и перехвата исключений, политики обработки исключений, границы распространения исключений и т.д.
Некотрые знакомые программисты, которые когда-то давно один раз научились программировать и больше ничего нового не изучают, говорят про исключения примерно следующее: "ну это сложнее" (полностью согласен), "от этого программа падает — забыл в одном месте поймать и всё" (тоже полностью согласен), "это не понятно, это не явно — смотришь на код функции — а обработки ошибок в нём нет" (тоже согласен).
Они тоже называют использование исключений усложнением и непонятной вещью.
Вобщем, что я хочу сказать. Есть вещи более простые, но с мменьшими возможностями (например, возьмёт логарифмическую линейку), а есть вещи более сложные, но с большими возможностями (например, возьмём компьютер). Конечно, человек, который 20 лет проработал с логарифмической линейкой, скажет про использование компьютера, что это сложно, что это не нужно, что это непонятно, что я так привык.
Всё всегда идёт к усложнению и к большим возможностям. Это неизбежно. Но тут надо не отставать от жизни.
Всегда существуют двигатели прогресса, которые исследуют новые возможности, потом облачают их более простую, понятную и пригодную для использованию форму. И после этого новые возможности становятся достоянием народа. Взять, например, современный автомобиль, штука офигеть какая сложная, зато возможностей сколько и использовать как просто. Всё. Мне пора в философию или о жизни
boost.mpl — штука сложная. внутри. но облечённая в удобную для использования форму. и документированная хорошо. Я не вижу ничего плохого в использовании её в промышленном проекте. Я даже надеюсь на то, что когда придёт новый программист, он скажет "о, вы тут mpl используете. конечно я работал с ним. я понимаю этот код".
E>Отдельная тема -- что должно происходить с кодом при возникновении исключений. Могу рассказть и про это.
Занятно. Это как? В обработчике исключения логика, которая ищет исходные коды программы (наверное по pdb) и модифицирует код?
Что может происходить с кодом при возникновении исключения?
Здравствуйте, Erop, Вы писали:
E>Возможно решат, возможно не решат. Я так думаю, что решат, но не ту. E>Но в текущем полложении дел есть несколько пробоем. E>1а) Никто не гарантирует тебе, что этот твой комментарий соответсвует действительности. Вдруг *на самом деле* ты требуешь от TLog чего-то ещё. Или, наоборот, чего-то пока что не требуешь?
Об этом ниже
E>1б) НИкто не гарантирует, что твой комментарий будет правильно понят пользователем. Вдруг он напишет метод int& fff()? И в текущей версии шаблона всё будет хорошо, а потом ты что-то захочешь поправить? А формальной проверки не выполняется.
Это относится и к явным интерфейсам. Они хорошо описывают лишь сигнатуры функций. Не больше и не меньше.
Они не описывают ни семантику функций, ни требования к многопоточности и др. гораздо более сложные и тонкие моменты.
Вот ты говоришь о шаблонных функциях, что может быть int& fff(), а может быть int fff() и шаблон может это не различить.
Представь тебе дали реализовать интерфейс:
/** Интерфейс такой-то такой-то */struct Interface
{
/** Функция, которая создаёт экземпляр SomeClass
*/virtual SomeClass* fff() = 0;
};
Ты думаешь — элементарно. Явный интерфейс есть. Что ещё надо? Реализовал.
Потом тебе говорят "у тебя утечка, ты сам ответственнен за удаление экземплятор SomeClass, а ты их не удаляешь!"
Через день "из-за твоего кода у нас всё падает! Метод fff() должен быть потокобезопасен! Ты что не знал, это все уже знают"
Через неделю "Блин, ну ты и накосячил! Из fff() нельзя кидать исключения! Делай с ними что хочешь, но выпускать из fff() их нельзя!"
Потом "если ты не можешь создать экземпляр, ты должен возвращать -1, а не 0! ну ты блин даёшь!"
Сигнатура функции — это лишь вершина айсберга. Это самая тривиальная часть.
Забывают комментировать и проверять (или скорее просто не думают об этом) как раз самые тонкие моменты
E>1в) Не понятно что делать, когда этот коментарий устаревает. Формальных проверок или нет или они чудовищны и ненадёжны. Вот понадобилось тебе, чтобы, скажем, сделать fff возвращал const MyInt&? Что вот делать? Вычитывать весь клиентский код во всех сделвнных на этом шаблоне проектах?
см. выше. Проблема неактуальности документации не имеет ничего общего к шаблонам.
А если например функция virtual SomeClass* fff() = 0; раньше была сама ответственна за удаление созданных экземпляров, а тебе понадобилось, что бы она пересала быть ответственна и не удаляла их. Что ты будешь делать? Вычитывать весь клиентский код во всех сделанный на этом интерфейсе проектах?
Решение: реализовать прототип класса, которым можно инстанциировать шаблон не в комментарии а в коде. И в каком-то месте инстанциировать им шаблон, что бы он компилировался, но не выполнялся. Проблема устаревания и полноты решена.
Я согласен, это сложнее, чем явный интерфейс, для этого надо обладать знаниями, что бы так сделать.
Далее — static_assert — с их помощью можно проверять уже классы, которыми пользователь специализирует твой шаблон. Проверить можно много. И даже больше, чем ты можешь проверить с помощью явного интерфейса!
Согласен, это опять же сложнее. Опять же надо обладать некими знаниями.
Далее — решение уже не только для шаблонов. Оно и явным интерфейсам костыли прикрутит. Модульные тесты. Проверяем горааааздо больше, чем явный интерфейс. Проверяем, кстати, и то, что virtual SomeClass* fff() = 0; сама удаляет память, и что она потокобезопасна, и что она не уидает исключения, и что в случае ошибки она возвращает именно -1.
E>Кроме того, есть у меня такое практическое наблюдение, что когда кто-то пишет шаблон и он при этом не супер спец этого дела, то получается изделие с неясной семантикой. Обычно я не придираясь, а просто стараясь понять что и как там втыкается, задаю вопросы, которые ставят авторов в тупик
При чём здесь шаблоны?
Я видел и обычные функции из 10 строк с неясной семантикой.
E>Общий смысл такой, что править шаблоны обычно дико дорого, поэтому их можно использовать либо в виде каких-то библиотечных очень хорошо отлаженных примитивов, скажем контейнеров. Либо в каких-то герметичных участках кода, где от чего-то надо несколько раз сдублировать код. Но только второе надо делать уже очень с опаской. Опять же про переиспользование таких шаблонов лучше всего забыть как правило сразу
Согласен, в некоторых местах явные интерфейсы более предпочтительны, а шаблоны неумесны.
R>>Зато и возможностей больше. Гораздо больше. Причём принципиально новых. Вспомни хотя бы std::vector<>! Как ты его предлагаешь реализовывать без шаблонов? Или ты его не используешь?
E>Конечно я не возражаю, против шаблонного массива. Но std::vector те не менее не использую. У нас в конторе есть своя, более древняя библиотечка, которая конечно хуже STL, но предсказуемее. Например там более очевидны временные сложности операуий
Ну я надеюсь, что он хотя бы типобезопасный, а не на void* работает
И ещё надеюсь, что мне, что бы захранить в таком контейнере какой-то класс, не надо вначале реализовывать интерфейс IStorable
E> E>>>2) Намного более сложный синтаксис и семантика. Вот, например, что тут написано: E>>>
E>>>template<typename TLog>
E>>>class Base {
E>>>protected
E>>> void exit( int );
E>>>};
E>>>template<typename TLog>
E>>>class MyExitProicessor : public Base<TLog> {
E>>>public:
E>>> void OnExit( TLog& log, int code )
E>>> {
E>>> LogExit( log, code ); // это какой-то метод MyExitProicessor, описанный ниже
E>>> exit( code );
E>>> }
E>>>};
E>>>
R>>Имхо. Всё понятно. Кстати, лучше писать "this->LogExit()" и "this->exit()", тогда и понятнее будет.
E>Может и лучше, но значит будет другое. Вообще-то в выделенной строке зовут функцию сишную exit .
А вот ещё кусок кода:
int* p = 0;
*p = 0;
И без шаблонов. Вывод какой: ламеров надо либо обучать, либо увольнять
E> E>>>3) Очень неудобные сообщения об ошибках в пользовательском коде.
R>>В большинстве случаев точно такие же как и без шаблонов. Надо просто их внимательно прочитать, а не говорить сразу "ух ты #$%, я это даже читать не буду". Вот ещё здесь.
E>К несчастью мне приходится это читать регулярно. Я так тебе скажу, что до изобретения STL я не встречал сообщений об ошибках, которые не помещаются в окно консоли
Меня лично это не пугает.
Я сообщения об ошибках на принтере не печатаю, и за место в консоли арендную плату не плачу
E> E>>>А вот реальные преимущества всех этих трюков Александреску они в чём? R>>Меньше дублирования. Лучше понятны намерения программиста. Аспекты лучше выделены, а не замешаны в один клубок. Но это всё достигается за счёт наличия более сложного (интеллектуального) кода. R>>Я так считаю: можно иметь или много "тупого" кода (я его называю "raw"), это когда много накопипастеных функций, или меньше кода, но более "интеллектуального".
E>Прости, но мне кажется, что все преимущества, кроме "Лучше понятны намерения программиста" достигаются хорошим проектированием и реализацией кода задачи, а вовсе не применением головоломных конструкций из шаблонов
К сожалению, некоторые задачи и некоторые виды дублирования не подвласны в С++ никому кроме шаблонов. Ни явным интерфейсам, ни хорошему проектированию.
К ещё больщему сожалению, некоторые виды дублирования не подвласны даже шаблоным, а подвласны только макросам...
E>Что же касается намерений, то я согласен, что они понятны. Они обычно (явно или просто по факту) состоят в том, чтобы удорожить разарботку и сопровождение.
Те, что используют исключения, паттерны, готовые библиотеки да и вообще С++ по-твоему те же намерения имеют? Вообще надо на asm'е писать. Всё до примитивного просто и явно.
Согласен практически со всем написанным в этом посте и выше , того же автора. Толкьо вот использование самодельных векторов меня как то покоробило , пора с этим заканчивать!
Здравствуйте, minorlogic, Вы писали:
M>Согласен практически со всем написанным в этом посте и выше , того же автора. Толкьо вот использование самодельных векторов меня как то покоробило , пора с этим заканчивать!