Re[6]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 12:36
Оценка: +5
Здравствуйте, CaptainFlint, Вы писали:

CF>Да ради Бога, назовём END_OF_BLOCK. Слово "цикл" я использовал исключительно из-за использования "цикловых" синтаксический конструкций языка. На суть моего поста это не влияет ни в малейшей степени, чего придираться по мелочам?


Это не мелочи. Тут все называют эту штуку "циклом"! Это говорит о том, что она воспринимается НЕ ТАК, КАК НАДО, для понимания кода!!!
Кроме того, метка END_OF_BLOCK тоже плоха.
1) Похожа на макрос
2) Ничего не говорит о коде. Ты же не называешь переменные variable, почему же считаешь хорошим именем метки "END_OF_BLOCK"?..

CF>Вот я написал код. Метки понятные, расположены где надо, переменные названы вразумительно, — короче, поддерживай да радуйся. НО! Тот человек, который по каким-то причинам получил мой код для разбора и поддержки, — он-то не знает, что я располагал всё правильно, называл всё грамотно. Он видит goto на какую-то метку. Пусть даже эта метка названа так, что совершенно очевидно, что она располагается в конце текущего блока. Но очевидное название — это не гарантия. Она может располагаться и в другом месте. И тот человек, не будучи уверенным в качестве моего кода, вынужден сам, своими ручками искать метку и убеждаться, что да, она поставлена ровно там, где должна быть поставлена.


Ну тогда можно сомневаться и в том, что типы названы верно и переменные и всё остальное...
Кроме того, серебрянной пули, конечно нет, но правило "не писать функции, определение которых не помещается на ОДИН экран" на серебрянную дробину таки тянет!

CF>Оператор break лишён этого недостатка. Даже если я пишу невероятно криво (ну, не считая #define break, конечно), любой человек, читающий код, будет точно и с абсолютной гарантией знать: да, break выходит из текущего цикла. Таким образом, если я использую goto, я добавляю потенциальному "поддерживателю" моего кода неуверенностей и необходимости лишних действий для проверки неких предпосылок. Если же я использую break, поведение регулируется уже не мной, а самим языком, значит, "поддерживатель" меньше зависит от моих выкрутасов, следовательно, ему не придётся гадать, грамотно я писал или нет.


Ну, эта проблема, IMHO, сильно не самая важная. В С++ есть намного более эффективнные способы по запутыванию кода, чем goto за конец блока.
Кроме того, для понимания конструкции do{ } while( 0 ); всё равно надо искать конец блока, кроме того, внутри блока ничто не предупреждлает тебя о том, что это надо делать...

Я ещё раз намекаю тебе, что в первом обсуждении этого антипаттерна участвовали коллеги, которые при беглом взгляде поняли этот код НЕВЕРНО!!!
А код с goto неверно понять НАМНОГО СЛОЖНЕЕ!

goto сразу говорит нам, что вот ребята, авторы кода немного облажались и не смогли написать всё красиво и процедурно. Так что будьте бдительны!

А цикл планомерно вводит нас в заблуждение, причём совсем без предупреждений!

В выборе между goto и этим вот недоциклом я пользуюсь всего двумя простыми и широкоизвестными принципами
1) Принцип наименьшего удивления. Тут goto удивления мало вызывает, IMНO, а вот do{}while(false) -- много
2) Код который нелегко понять хуже кода, который легко понять НЕВЕРНО и НЕ ЗАМЕТИТЬ этого!

Интересно, какой из них ты не разделяешь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 12:47
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>
CF>BLOCK_BEGIN
CF>{
CF>    if (smth)
CF>        BLOCK_EXIT;
CF>    if (smth_else)
CF>        BLOCK_EXIT;
CF>    do_smth_useful();
CF>}
CF>BLOCK_END
CF>

CF>то я в первую очередь восприму в нём семантику (блок кода и выход из него при выполнении определённых условий). И уже потом, если будет время и желание, начну разбираться, а как это программист умудрился сделать конструкцию, которой изначально в языке нет, полезу в определения макросов, и т.д.

1) Я подумаю, что эти все макросы -- какой-то замут на тему об обработке ОШИБОК...
Соответсвенно, буду ожидать, что условия if'ов -- это какие-то исключительные ситуации...

CF>Или ты никогда сторонними библиотеками не пользовался? В MFC ты первым делом бросаешься разгребать, во что задефайнены все эти жуткие DECLARE_DYNAMIC, BEGIN_MESSAGE_MAP, END_MESSAGE_MAP, и как они работают? А в Qt не станешь изучать программу, пока досконально не разберёшься, какой промежуточный C++-код генерируется из отсутствующих в синтаксисе языка сигналов и слотов?


Ну я конечно понимаю, что я старомоден, но перед использованием библиотек я обычно заглядываю сначала в мануал...
Кстати, как ты планируешь понимать конструкцию BEGIN_MESSAGE_MAP или DECLARE_DYNAMIC без мануала?
Вот видтшь ты BEGIN_MESSAGE_MAP( MyWindow, CWnd )
ON_COMMAND( XXX, onXXX )
END_MESSAGE_MAP;
И как ты понимаешь что это? Хотя бы код это или данные (можно ли там бряки ставить, например)?
Про то, что какой именно код получит управление при обработке сообщения ты без мануала вообще не поймёшь, так как там обычно больше одного мэпа в процессе участвует, я вообще скромно умалчиваю пока.
При этом, обрати внимание, мы как бы про поддержку говорим да?
То есть есть два варианта.
1) Меня на самом деле вообще не интересует вся этам фигня с выбором обработчика сообщения. Ну так тогда мне вообще этот код читать не надо. Вполне достаточно глянуть на него и приянть к сведению. что он есть. при этом очень хорошо бы, чтобы первое беглое впечатление не вводило меня в заблуждение.
Например, наличие в карте сообщений сообщения, которое никогда через эту конкретную карту не роутится, например, потому, что оно обрабатывается в другом объекте, скажем во вьюшке, -- это очень, очень плохо. Так как я запомню, что обработчик лежит там-то, а он, на самом деле, совсем и в другом месте!
2) Меня волнуте именно то, что сообщение обрабатывается как-то не там и этот код мне читать НУЖНО. Как во втором случае читать без мануала (не зная что такое карта сообщений) я

При этом мне не нравится, когда библиотека не заставляет меня меня читать мануал из-за всякой ерунды.
Карта сообщений делает вполне сложную и нужную функциональность. А вот все эти пляски с do while(0) вокруг goto никакого функционала, IMHO, не добавляют, то есть вредят.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: В чем прелесть замаскированного goto?
От: A.Lokotkov Россия http://www.linkedin.com/pub/alexander-lokotkov/a/701/625
Дата: 09.09.10 12:59
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>А тебе какой-то из обсуждаемых тут вариантов (что этот цикл-не цикл, что блок с досрочным выходом по goto, что switch, который не switch) кажется красивым?


Сам по себе -- ни один из, только в сравнении. Просто когда в чужом коде встречаю goto somewhere, а somewhere не находится в пределах экрана, это кажется еще менее красивым, мягко говоря. Да еще и вперемешку с десятком return-ов из функции на 5-6 экранов.

Кстати, расстановку фигурных скобок в стиле Кернигана-Ритчи тоже не переношу -- бывает, хрен поймешь, где начало, а где кончало . Может, поговорим об этом?
bloß it hudla
Re[6]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 13:12
Оценка:
Здравствуйте, A.Lokotkov, Вы писали:

AL>Сам по себе -- ни один из, только в сравнении. Просто когда в чужом коде встречаю goto somewhere, а somewhere не находится в пределах экрана, это кажется еще менее красивым, мягко говоря. Да еще и вперемешку с десятком return-ов из функции на 5-6 экранов.


Тут есть два всего варианта.
2) (редкий) Эти все навороты строго по делу. Например это результат нереальной оптимизации в сочетании с редкой убогостью компилятора. Так бывает, но очень редко. И в таком коде, обычно, есть вообще много особеностей всяких, кроме goto. Соответсвенно, при поддержке, надо всё это понять досконально, зачем тут так, а там сяк извернулись и всё это ЗАДОКУМЕНТИРОВАТЬ, если ещё не. Лучше всего прямо в комментах к коду. Ну и править аккуратно очень. Но это редкий, да и всё равно тяжкий для поддержки случай. Хорошо всё-таки, что редкий!
1) (частый, обычный, встречающийся на практике, в отличии от (2), повсеместно)
Это просто говонокод, написанный говнокодерами. Его надо срочно отрефакторить, а того, кто допустил коммит этого г. депримировать!
Скорее всего там и goto не нужен и недоцикл не нужен и вообшще всё можно написать НОРМАЛЬНО!!!

Не согласен?


AL>Кстати, расстановку фигурных скобок в стиле Кернигана-Ритчи тоже не переношу -- бывает, хрен поймешь, где начало, а где кончало . Может, поговорим об этом?

1) Прости, но программировать на С/С++, и при этом не мочь приспособиться к одной из общеприянтых схем расстановки скобок -- это подвиг. Примерно на уровне полётов Мересьва...
Но Мересьев, вернее его прототип, бил фашистских гадов и сражался за Родину. Да и ноги у него, сначала всё-таки были. За что страдаешь ты, коллега?

2) Могу посоветовать разориться на нормальную IDE, которая умеет автоматом форматировать код так, как тебе удобно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: В чем прелесть замаскированного goto?
От: A.Lokotkov Россия http://www.linkedin.com/pub/alexander-lokotkov/a/701/625
Дата: 09.09.10 13:39
Оценка: +1 :)
Здравствуйте, Erop, Вы писали:

E>Тут есть два всего варианта. (редкий)...(частый)


Только у меня, к примеру, как-то все ровно наоборот -- в этом году уже три случая, когда нужно было оживлять сторонний (говно)код, писаный в подобном стиле: atapi-драйвер и драйвер серийного порта в Windows CE, а про третий не скажу (пусть сами догадаются и им будет стыдно) .

AL>>... Может, поговорим об этом?

E>Но Мересьев, вернее его прототип, бил фашистских гадов и сражался за Родину. Да и ноги у него, сначала всё-таки были. За что страдаешь ты, коллега?

Это было шутка юмора, ага Хотя совет про IDE приму с премногими благодарностями.
bloß it hudla
Re[8]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 13:51
Оценка:
Здравствуйте, A.Lokotkov, Вы писали:

E>>Тут есть два всего варианта. (редкий)...(частый)

AL>Только у меня, к примеру, как-то все ровно наоборот -- в этом году уже три случая, когда нужно было оживлять сторонний (говно)код, писаный в подобном стиле: atapi-драйвер и драйвер серийного порта в Windows CE, а про третий не скажу (пусть сами догадаются и им будет стыдно) .

Ну так если так всё по делу, то куда деваться? И вряд ли трбк с циклом может что-то улучшить в такой ситуации


E>>Но Мересьев, вернее его прототип, бил фашистских гадов и сражался за Родину. Да и ноги у него, сначала всё-таки были. За что страдаешь ты, коллега?

AL>Это было шутка юмора, ага

Ну про Мересьева тоже
Ну а про IDE не шутка.
AL>Хотя совет про IDE приму с премногими благодарностями.
Пожалуйста!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: В чем прелесть замаскированного goto?
От: Pavel Dvorkin Россия  
Дата: 09.09.10 13:57
Оценка: 6 (1) :))) :))
Здравствуйте, enji, Вы писали:

В возможности устроить незамаскированный флейм.
With best regards
Pavel Dvorkin
Re[6]: В чем прелесть замаскированного goto?
От: RomikT Германия  
Дата: 09.09.10 14:09
Оценка: +3
Здравствуйте, CaptainFlint, Вы писали:

CF>Здравствуйте, Erop, Вы писали:


E>>Здравствуйте, CaptainFlint, Вы писали:


CF>>>Кроме того, если не нравится цикл, можно его замаскировать под блок какими-нибудь дефайнами типа BLOCK_BEGIN (do), BLOCK_END (while(0)), BLOCK_EXIT (break). Это скорее вопрос привычки и личного восприятия.


E>>Это ЕЩЁ ХУЖЕ для поддержки. Так тебе надо въехать в то, что цикл -- это на самом деле не цикл. А так сначала надо будет найти и понять эти макросы, а потом въехать, что цикл -- это не цикл


CF>Гм… Возможно, у нас разные способы чтения кода, но если я увижу код

CF>
CF>BLOCK_BEGIN
CF>{
CF>    if (smth)
CF>        BLOCK_EXIT;
CF>    if (smth_else)
CF>        BLOCK_EXIT;
CF>    do_smth_useful();
CF>}
CF>BLOCK_END
CF>

CF>то я в первую очередь восприму в нём семантику (блок кода и выход из него при выполнении определённых условий). И уже потом, если будет время и желание, начну разбираться, а как это программист умудрился сделать конструкцию, которой изначально в языке нет, полезу в определения макросов, и т.д.

Да, и ни капли не сомневаюсь напишу похожий код:
BLOCK_BEGIN
{
    while (condition)
        if (smth)
            BLOCK_EXIT;
    while (another_condition)
        if (smth_else)
            BLOCK_EXIT;
}
BLOCK_END

Который, естественно, работать не будет.
Re[9]: В чем прелесть замаскированного goto?
От: A.Lokotkov Россия http://www.linkedin.com/pub/alexander-lokotkov/a/701/625
Дата: 09.09.10 14:11
Оценка:
Здравствуйте, Erop, Вы писали:

E>Ну так если так всё по делу, то куда деваться? И вряд ли трбк с циклом может что-то улучшить в такой ситуации


Ну, скажем, до разгребания (говно)кода, превращения его в do {} while(0) и разбиения на мелкие подфункции, при инициализации ide-канала драйвер категорически отказывался находить secondary master-а, являющегося единственным диском в системе. Ибо в многостадийной инициализации в случае облома на фоне return-ов и goto легко забыть что-нибудь убрать за собой, освободить какой-нибудь ресурс и пр., что и произошло в данном случае. MS-овцы этот баг, кстати, скопипастили в следующую версию Win CE.
bloß it hudla
Re[10]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 14:45
Оценка: :)
Здравствуйте, A.Lokotkov, Вы писали:

AL>Здравствуйте, Erop, Вы писали:


AL>Ну, скажем, до разгребания (говно)кода, превращения его в do {} while(0) и разбиения на мелкие подфункции, при инициализации ide-канала драйвер категорически отказывался находить secondary master-а,


Ну таки не по делу значит говнокод-то был?
Всё понимаю, но при чём тут do{ } while( 0 ); -- не понимаю
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 15:11
Оценка:
Здравствуйте, RomikT, Вы писали:

RT>Да, и ни капли не сомневаюсь напишу похожий код:

RT>
RT>BLOCK_BEGIN
RT>{
RT>    while (condition)
RT>        if (smth)
RT>            BLOCK_EXIT;
RT>    while (another_condition)
RT>        if (smth_else)
RT>            BLOCK_EXIT;
RT>}
RT>BLOCK_END
RT>

RT>Который, естественно, работать не будет.

Можно, кстати, доработать напильником:

BLOCK_BEGIN(BlockName)
{
    while (condition)
        if (smth)
            BLOCK_EXIT(BlockName);
    while (another_condition)
        if (smth_else)
            BLOCK_EXIT(BlockName);
}
BLOCK_END(BlockName)
только с явными вызовами goto лично мне всё равно понятнее
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: В чем прелесть замаскированного goto?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 09.09.10 15:18
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Это не мелочи. Тут все называют эту штуку "циклом"! Это говорит о том, что она воспринимается НЕ ТАК, КАК НАДО, для понимания кода!!!

E>Кроме того, метка END_OF_BLOCK тоже плоха.
E>1) Похожа на макрос
E>2) Ничего не говорит о коде. Ты же не называешь переменные variable, почему же считаешь хорошим именем метки "END_OF_BLOCK"?..

Хорошо, назови, как твоей душе угодно. Или вообще замени всю фразу "Да, её можно назвать END_OF_CYCLE" на что-нибудь вроде "Да, её можно назвать интуитивно понятным именем". Суть поста-то от этого совершенно не меняется. Нафига демагогию разводить на пустом месте?

CF>>Вот я написал код. Метки понятные, расположены где надо, переменные названы вразумительно, — короче, поддерживай да радуйся. НО! Тот человек, который по каким-то причинам получил мой код для разбора и поддержки, — он-то не знает, что я располагал всё правильно, называл всё грамотно. Он видит goto на какую-то метку. Пусть даже эта метка названа так, что совершенно очевидно, что она располагается в конце текущего блока. Но очевидное название — это не гарантия. Она может располагаться и в другом месте. И тот человек, не будучи уверенным в качестве моего кода, вынужден сам, своими ручками искать метку и убеждаться, что да, она поставлена ровно там, где должна быть поставлена.


E>Ну тогда можно сомневаться и в том, что типы названы верно и переменные и всё остальное...

E>Кроме того, серебрянной пули, конечно нет, но правило "не писать функции, определение которых не помещается на ОДИН экран" на серебрянную дробину таки тянет!

Во-первых, на нетбуке и на 26" мониторе понятия "один экран" чуточку разнятся. Во-вторых, даже если весь код уместился на один экран, всё, что я говорил об очевидности поведения кода, здесь тоже применимо с тем лишь отличием, что придётся не текст прокручивать, а глазами по коду прыгать. Согласен, это не та проблема, чтобы бить в барабаны, но всё же, согласись, найти текстовый идентификатор и проверить его идентичность метке в goto занимает больше времени и усилий, чем просто найти конец текущего блока.

Я нигде не утверждал, что сабжевая конструкция — это серебряная пуля. Изначально был задан вопрос: в чём преимущества этого подхода перед goto? Я описал те преимущества, которые усмотрел в таком подходе. Я нигде не утверждал, что недостатки отсутствуют, что это идеальный код, что его обязательно надо использовать везде, что можно забыть про coding conventions, и так далее. Просто есть определённые приятности, которых другими средствами достичь невозможно. Насколько велики эти приятности, окупят ли они присущие данному подходу недостатки, — это всё решается индивидуально, в зависимости от потребностей текущего проекта и коллектива разработчиков.

CF>>Оператор break лишён этого недостатка. Даже если я пишу невероятно криво (ну, не считая #define break, конечно), любой человек, читающий код, будет точно и с абсолютной гарантией знать: да, break выходит из текущего цикла. Таким образом, если я использую goto, я добавляю потенциальному "поддерживателю" моего кода неуверенностей и необходимости лишних действий для проверки неких предпосылок. Если же я использую break, поведение регулируется уже не мной, а самим языком, значит, "поддерживатель" меньше зависит от моих выкрутасов, следовательно, ему не придётся гадать, грамотно я писал или нет.


E>Ну, эта проблема, IMHO, сильно не самая важная. В С++ есть намного более эффективнные способы по запутыванию кода, чем goto за конец блока.


Речь не о том, как запутать код, а о том, как объяснить читателю, что код не запутан.

E>Кроме того, для понимания конструкции do{ } while( 0 ); всё равно надо искать конец блока, кроме того, внутри блока ничто не предупреждлает тебя о том, что это надо делать...


Согласен, есть такой аспект. Но я ведь с самого начала сказал об этом: да, информация, которую мы получаем, видя break, неполна.

E>Я ещё раз намекаю тебе, что в первом обсуждении этого антипаттерна участвовали коллеги, которые при беглом взгляде поняли этот код НЕВЕРНО!!!

E>А код с goto неверно понять НАМНОГО СЛОЖНЕЕ!

Во-первых, это субъективно. Во-вторых, ты как-то слишком легко судишь о том, кто чего и как понял. Вот взять меня: я тоже называл эту конструкцию циклом. Значит ли это, что я не понял, что это не цикл а однопроходовый блок? Да нифига! Прекрасно я всё понял (тем более, что уже прочитал до этого тему Не такой уж и WTF
Автор: andrey_nado
Дата: 28.08.10
и знал, о чём идёт речь). Я использовал слово "цикл" просто потому что привык называть for и do/while циклами, а также потому, что для подобной конструкции банально нет устоявшегося термина (ну или мне он неизвестен), только и всего.

E>goto сразу говорит нам, что вот ребята, авторы кода немного облажались и не смогли написать всё красиво и процедурно. Так что будьте бдительны!


E>А цикл планомерно вводит нас в заблуждение, причём совсем без предупреждений!


Да, неочевидность кода — это один из недостатков данного подхода, совершенно верно.



E>В выборе между goto и этим вот недоциклом я пользуюсь всего двумя простыми и широкоизвестными принципами
E>1) Принцип наименьшего удивления. Тут goto удивления мало вызывает, IMНO, а вот do{}while(false) -- много
E>2) Код который нелегко понять хуже кода, который легко понять НЕВЕРНО и НЕ ЗАМЕТИТЬ этого!

E>Интересно, какой из них ты не разделяешь?


Оба пункта, которые ты привёл, опять-таки, субъективны. Тебя некий код удивит, а кого-нибудь другого — нет. А другой код — наоборот. И какой из них считать "наименее удивляющим"?
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[7]: В чем прелесть замаскированного goto?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 09.09.10 15:18
Оценка:
Здравствуйте, Erop, Вы писали:

E>1) Я подумаю, что эти все макросы -- какой-то замут на тему об обработке ОШИБОК...

E>Соответсвенно, буду ожидать, что условия if'ов -- это какие-то исключительные ситуации...

Во, так я именно такую ситуацию и имел в виду, когда писал пример кода. Значит, код-то понятный получился.

CF>>Или ты никогда сторонними библиотеками не пользовался? В MFC ты первым делом бросаешься разгребать, во что задефайнены все эти жуткие DECLARE_DYNAMIC, BEGIN_MESSAGE_MAP, END_MESSAGE_MAP, и как они работают? А в Qt не станешь изучать программу, пока досконально не разберёшься, какой промежуточный C++-код генерируется из отсутствующих в синтаксисе языка сигналов и слотов?


E>Ну я конечно понимаю, что я старомоден, но перед использованием библиотек я обычно заглядываю сначала в мануал...


В мануал и я заглядываю. Но мануал описывает высокоуровневое поведение. Если провести аналогию с приведёнными мной макросами, то в мануале напишут, что BLOCK_BEGIN и BLOCK_END ограничивают однопроходный блок, а BLOCK_EXIT позволяет выйти в конец блока. А что эти макросы разворачиваются конкретно в do/while/break там описываться не должно, это уже низкоуровневые детали реализации.

E>Кстати, как ты планируешь понимать конструкцию BEGIN_MESSAGE_MAP или DECLARE_DYNAMIC без мануала?

E>Вот видтшь ты BEGIN_MESSAGE_MAP( MyWindow, CWnd )
E> ON_COMMAND( XXX, onXXX )
E>END_MESSAGE_MAP;
E>И как ты понимаешь что это? Хотя бы код это или данные (можно ли там бряки ставить, например)?

Я это понимаю как некую абстракцию, как эдакое расширение синтаксиса языка. Изначально вопрос о том, что кроется внутри этих макросов просто не возникает. Бряки там ставить не требуется, т.к. логика кода сидит не в объявлениях обработчиков событий, а в самих обработчиках. Это фреймворк, я просто принимаю его таким, какой он есть.

И только если вдруг что-то не работает, или если я подозреваю баги в MFC, или просто делать нечего, а любопытство гложет, я начинаю смотреть, а что же такое на самом деле прячется под этими макросами, как они выполняют привязку, каким синтаксическим языковым конструкциям соответствуют, ну и так далее.

E>Про то, что какой именно код получит управление при обработке сообщения ты без мануала вообще не поймёшь, так как там обычно больше одного мэпа в процессе участвует, я вообще скромно умалчиваю пока.


Про мануал я и не говорю ничего, он необходим. Но ты-то говорил совсем о другом. Ещё раз процитирую твоё сообщение:
E>А так сначала надо будет найти и понять эти макросы
Так вот, моё утверждение заключается в том, что для понимания сути происходящего совершенно необязательно находить определения макросов. Достаточно общего понимания того, что эти макросы делают. Я читаю в мануале: BEGIN_MESSAGE_MAP используется для начала такого-то блока, имеет такие-то параметры. Всё. И меня совершенно не колебёт, что на самом деле этот BEGIN_MESSAGE_MAP разворачивается в жутковатую хренотень вида
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
    PTM_WARNING_DISABLE \
    const AFX_MSGMAP* theClass::GetMessageMap() const \
        { return GetThisMessageMap(); } \
    const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
    { \
        typedef theClass ThisClass;                           \
        typedef baseClass TheBaseClass;                       \
        static const AFX_MSGMAP_ENTRY _messageEntries[] =  \
        {

Даже более того, если бы мне мануал вместо человеческого описания начал предлагать вот такие вот конструкции — да я бы послал этот мануал в пешее эротическое путешествие. Вместе с самим фреймворком.

Соответственно, в моём примере достаточно лишь сказать, что макросы BLOCK_* выполняют такие-то и сякие-то действия. А что BEGIN — это именно do, а END — это именно while(0), — на данном этапе это совершенно ненужная, засоряющая информация. Вот если в дефайнах окажутся баги, тогда да, придётся лезть в них, разбираться, почему они именно такие.

E>При этом, обрати внимание, мы как бы про поддержку говорим да?

E>То есть есть два варианта.
E>1) Меня на самом деле вообще не интересует вся этам фигня с выбором обработчика сообщения. Ну так тогда мне вообще этот код читать не надо. Вполне достаточно глянуть на него и приянть к сведению. что он есть. при этом очень хорошо бы, чтобы первое беглое впечатление не вводило меня в заблуждение.
E>Например, наличие в карте сообщений сообщения, которое никогда через эту конкретную карту не роутится, например, потому, что оно обрабатывается в другом объекте, скажем во вьюшке, -- это очень, очень плохо. Так как я запомню, что обработчик лежит там-то, а он, на самом деле, совсем и в другом месте!
E>2) Меня волнуте именно то, что сообщение обрабатывается как-то не там и этот код мне читать НУЖНО. Как во втором случае читать без мануала (не зная что такое карта сообщений) я

E>При этом мне не нравится, когда библиотека не заставляет меня меня читать мануал из-за всякой ерунды.


Похоже, мы под мануалом понимаем разные вещи… Для меня мануал — это то, что описывает функциональность библиотеки и методику её использования, а не сугубо внутренние детали реализации.

E>Карта сообщений делает вполне сложную и нужную функциональность. А вот все эти пляски с do while(0) вокруг goto никакого функционала, IMHO, не добавляют, то есть вредят.


Рассматривай это как паттерн. Есть определённые ситуации, в которых требуется конструкция вида "однопроходный блок с выходом из него по условиям". Роль такой конструкции может играть try/catch, может функция с return'ами, может обычный блок с goto, а может и псевдо-цикл do/while(0). Есть люди, которым последний подход показался интересным и достаточно вразумительным. Тебе он таковым не показался — что ж, это твоё личное мнение. Но это не означает, что этот подход никому в мире не должен казаться понятным и полезным.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[3]: В чем прелесть замаскированного goto?
От: Nik_1 Россия  
Дата: 09.09.10 17:33
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Nik_1, Вы писали:


N_>>Приэтом логика кода будет сильней запутана, если начнут встречаться переходы из внутренностей одного блока в другой.


E>А вот и не надо использовать goto из внутренностей одного блока ВО ВНУТРЕННОСТИ другого. И goto назада не надо.

E>Надо goto наружу блока, непосредственно за его конец!
А зачем? Чтоб сделать гоуту за блок в языке введен оператор брейк, и не надо никаких меток плодить в коде, придумывать им имена и заботиться об их уникальности. Гоуту — это очень низкоуровневый инструмент, как и асемблерные вставки. Он был введен в язык для использования в крайней необходимости — когда высокоуровневыми средствами нельзя достич требуемого результата. Так где можно обойтись высокоуровневым средством нет смысла прибигать к низкоуровневым.
E>>>Я в курсе, что goto стоит избегать и согласен с этим, но зачем его маскировать циклами или switch? Все же goto встроен в С/С++, а идиома "цикл, который выполняется 1 раз" — какая-то искусственная...

Яж написал, что это не маскировка. Наоборот, гоуту — это будет маскировка брейка( здесь суть действия — досрочное прерывание блока из последовательности операторов, спецально для этого в языке есть ключивые слова брейк и континью).

N_>>Он здесь не маскируется. Это принципиально другой подход, который лучше чем использование гоуту. Брейк — это досрочное прерывание текущей последовательности действий. Гоуту — это некоторый посыл фигзнает куда.


E>Вот объясни мне, почему тебе конструкция
do { // Обработка команд сервера
E>   if( обычный_случай ) {
E>       // ...
E>       break;
E>   }
E>} while( 0 );

E>кажется понятнее, чем
{ // Обработка команд сервера 
E>   if( обычный_случай ) {
E>       // ...
E>       goto endOfServerCommansProcess;
E>   }
E>}
E>endOfServerCommansProcess:;


Как говориться, дьвол кроится в деталях, а в данном случаи за этим многоточием. На практике код там обычно бывает длянным и куда нас послали придется искать через поиск.

E>При ответе учти, пожалуйста, что конструкция с goto стандартная, а стандартная конструкция с циклом выглядит так:
do { // Обработка команд сервера
E>   if( необычный_случай ) {
E>       // ...
E>       break;
E>   }
E>} while( условие_продолжения );

Это лишь изза того, что в языке не ввели возможность создния блоков без цикла. Поэтому это обходят через вайл(фолс).
E>При этом нестандартное использование цикла происходит без объявления войны.
E>Вот мы читаем код какой-то функции, видим цикл, и пока до while не дочитаем, про то, что это нифига не цикл так и не узнаем
Аналогично, в случаи брейка зато мы точно знаем куда идет посыл — в конец текущего блока. А в случаи с гоуту пока не дочитаем до метки, не поймем что имелось ввиду под этим посылом.
Re[5]: В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
От: Nik_1 Россия  
Дата: 09.09.10 17:39
Оценка: :)
Здравствуйте, Erop, Вы писали:
E>>>В ЭТОЙ ПРОГРАММЕ НЕТ НИКАКОГО ЦИКЛА!!!
MC>>Если ты про break, я имел в виду, еснно if() break; или if() continue; break.
E>Я про то, что эта ваша "конструкция" вводит всех в заблуждение, показывая тут цикл, хотя цикла никакого как раз и нет...

Это уже издержки того что в языке нет конструкции на этот случай. Но тут уже предлагали использать дефайны которые решают эту проблему, и все сразу становится наглядно
Re[7]: Во! Во как надо!!! ;)
От: Erop Россия  
Дата: 09.09.10 17:59
Оценка:
Здравствуйте, RomikT, Вы писали:

RT>Да, и ни капли не сомневаюсь напишу похожий код:

RT>
RT>BLOCK_BEGIN
RT>{
RT>    while (condition)
RT>        if (smth)
RT>            BLOCK_EXIT;
RT>    while (another_condition)
RT>        if (smth_else)
RT>            BLOCK_EXIT;
RT>}
RT>BLOCK_END
RT>

RT>Который, естественно, работать не будет.

Во! Во как надо!!!
namespace ScopeDatails {
    struct Guard { bool False() { return false; } };
}//ScopeDatails
#define SCOPE_GUARD_NAME_( SCOPE_NAME ) guardOf##SCOPE_NAME
#define SCOPE_END_NAME_( SCOPE_NAME ) endOf##SCOPE_NAME
#define SCOPE_BEGIN_NAME_( SCOPE_NAME ) beginOf##SCOPE_NAME

#define SCOPE_START( SCOPE_NAME ) { \ SCOPE_BEGIN_NAME_( SCOPE_NAME ):
    ScopeDatails::Guard SCOPE_GUARD_NAME_( SCOPE_NAME );
#define SCOPE_END( SCOPE_NAME ) SCOPE_GUARD_NAME_( SCOPE_NAME ).False(); } \
    SCOPE_END_NAME_( SCOPE_NAME ):;
#define SCOPE_LEAVE( SCOPE_NAME ) if( SCOPE_GUARD_NAME_( SCOPE_NAME ).False() ) else goto SCOPE_END_NAME_( SCOPE_NAME )

void foo()
{
    SCOPE_START( DetectProcessor )
    {
        if( isProcXXX() ) {
            doXXX();
            SCOPE_LEAVE( DetectProcessor );
        }
        if( isProcYYY() ) {
            doYYY();
            SCOPE_LEAVE( DetectProcessor );
        }
        doCommonCase();
    }
    SCOPE_END( DetectProcessor )

}
на компе не проверял, если что...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: В чем прелесть замаскированного goto?
От: Nik_1 Россия  
Дата: 09.09.10 18:13
Оценка: :)
Здравствуйте, Erop, Вы писали:
E>Что касается конкретно использования goto, макросов и прочих спорных конструкций, то мой опыт говорит мне, что хорошо работает такое правило, что их использование нужно согласовать с начальником. Обычно этого достаточно, чтобы природная лень подвигала людей на поиск нормальных решений...
Хосподи, а макросы то тебе чем не угодили?
Re[8]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 18:20
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>Во-первых, на нетбуке и на 26" мониторе понятия "один экран" чуточку разнятся. Во-вторых, даже если весь код уместился на один экран, всё, что я говорил об очевидности поведения кода, здесь тоже применимо с тем лишь отличием, что придётся не текст прокручивать, а глазами по коду прыгать. Согласен, это не та проблема, чтобы бить в барабаны, но всё же, согласись, найти текстовый идентификатор и проверить его идентичность метке в goto занимает больше времени и усилий, чем просто найти конец текущего блока.


Дык он должен быть как раз в конце блока...

CF>Я нигде не утверждал, что сабжевая конструкция — это серебряная пуля.

Либо я тебя не понял, либо твои приятности становятся актуальны, когда меток в функции много, блоков много и вообще всего много. IMHO, такие сложные функции лучше не писать

CF>Речь не о том, как запутать код, а о том, как объяснить читателю, что код не запутан.

Ну вот мне в конструкции с псевдоциклом больше всего не нравится то, что код запутан, но это замаскировано.

CF>Согласен, есть такой аспект. Но я ведь с самого начала сказал об этом: да, информация, которую мы получаем, видя break, неполна.

Хуж! Она не та! пока не дойдём до конца, так и не узнаем к чему всё это было.

CF>Во-первых, это субъективно.

Что субъективно? Что такой "цикл" может и не насторожить или что goto не может не насторожить?

CF>Во-вторых, ты как-то слишком легко судишь о том, кто чего и как понял.

Да нет, не ты. Ты юы наверное понял бы, что ты не понял и изменил бы мнение о конструкции.
Но были посты типа "и что вам тут не нравится, обычный цикл получения данных"

CF>Да, неочевидность кода — это один из недостатков данного подхода, совершенно верно.

Ну да. IMHO, это очень боьлшой недостаток. Так как код с goto только гипотетически может оказаться неочевидным, и то, если автор допустит в нём ошибку, использовав не ту метку, или поставив метку не сразу после конца, а где-то ещё. А код с псевдоциклом СРАЗУ неочевидный...

CF>

E>>В выборе между goto и этим вот недоциклом я пользуюсь всего двумя простыми и широкоизвестными принципами
E>>1) Принцип наименьшего удивления. Тут goto удивления мало вызывает, IMНO, а вот do{}while(false) -- много
E>>2) Код который нелегко понять хуже кода, который легко понять НЕВЕРНО и НЕ ЗАМЕТИТЬ этого!

E>>Интересно, какой из них ты не разделяешь?


CF>Оба пункта, которые ты привёл, опять-таки, субъективны. Тебя некий код удивит, а кого-нибудь другого — нет. А другой код — наоборот. И какой из них считать "наименее удивляющим"?

Прикольно! Ты не знаешь принципа наименьшего удивления? Это очень хороший и широкоупотребляемый принцип. Очень ценен при работе в команде. Правда я не готов сейчас углубляться в обсуждение самого принципа. Это тут офтоп несколько.
Так что вернусь к goto vs псевдоцикл. Оно конечно немного субъектитвно, но всё равно всё просто и понятно. Вот смотри, ты тут выше, когда писал про то, что я неверно сужу кто там что понял или не понял, писал, что тут-то ты всё понял, потому что читал перед этим тему про WTF? А вот про код с goto ты от чего-то таких разъяснений делать не стал. Не подскажешь почему?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: В чем прелесть замаскированного goto?
От: Nik_1 Россия  
Дата: 09.09.10 18:25
Оценка: :)
Здравствуйте, Erop, Вы писали:
E>Ну а про IDE не шутка.
AL>>Хотя совет про IDE приму с премногими благодарностями.
E>Пожалуйста!

Ну так привнимательно слушаем
Какая ИДЕ умеет отоброжать брекиты написанные в дуратском стиле:
do{
};


в нормальный стиль?
Re[8]: В чем прелесть замаскированного goto?
От: Erop Россия  
Дата: 09.09.10 18:31
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

E>>А так сначала надо будет найти и понять эти макросы

CF>Так вот, моё утверждение заключается в том, что для понимания сути происходящего совершенно необязательно находить определения макросов. Достаточно общего понимания того, что эти макросы делают.
...
CF>Соответственно, в моём примере достаточно лишь сказать, что макросы BLOCK_* выполняют такие-то и сякие-то действия. А что BEGIN — это именно do, а END — это именно while(0), — на данном этапе это совершенно ненужная, засоряющая информация. Вот если в дефайнах окажутся баги, тогда да, придётся лезть в них, разбираться, почему они именно такие.

Ну, да, но при поддержке надо будет держать в голове этот мануал. Зачем это?
IMHO, без макросов лучше чем с ними, при любом раскладе. Не в смысле вообще и всегда, а в данном конкретном случае.

CF>Рассматривай это как паттерн. Есть определённые ситуации, в которых требуется конструкция вида "однопроходный блок с выходом из него по условиям". Роль такой конструкции может играть try/catch, может функция с return'ами, может обычный блок с goto, а может и псевдо-цикл do/while(0). Есть люди, которым последний подход показался интересным и достаточно вразумительным. Тебе он таковым не показался — что ж, это твоё личное мнение. Но это не означает, что этот подход никому в мире не должен казаться понятным и полезным.


Ужос! try-то с catch'ем-то за что? Я верно понял, что речь идёт о конструкции вида:
try {
    if( XXX ) {
        throw 666;
    } 
} catch( int rootOfEvil ) {
        // process XXX
}
Это уж совсем ни в какие ворота не того. Чего толкьо люди из-за религиозного страха перед goto не делают!!!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.