четверг, 15 января 2009 г.

Хронический аудиал

Что касается женщин, то это чувство сугубо интимное...


Есть некоторые идеомы, считающиеся хорошими. Например считается правильным писать константную часть слева в условии, для того чтобы на операцию '=' вместо '==' ругался компилятор а не конечный пользователь.
if (MIN_ELEMENTS == i) ...
Я долго не мог понять почему мне это так не нравится, и наконец сформулировал для себя ответ на этот вопрос.

Писать так в частности рекоммендует Стив Макконел (Steve McConnell) в книге "Совершенный код". Там же рекоммендуется упорядочивании аргументы в соответствии со значениями на числовой прямой.
if (MIN_ELEMENTS <= i && i <= MAX_ELEMENTS) ...
Очень похожая ситуация, хотя меня она коробит меньше.

Есть теория, что люди делятся на визуалов, аудиалов и еще некоторых, которые в данном случае не важны. А может быть и два вышеуказанных тоже не важны, а ответ лежит совсем в другой плоскости. :)

Может быть такая запись считается удобной и правильной для тех, кто оценивает код визуально. Что же касается меня - я код предпочитаю читать. И читается примерно следующее:
Если MIN_ELENEMTS равен...
Стоп, как может быть константное значение сегодня равно, а завтра не равно? В этом выражении как будто содержится предположение, что MIN_ELEMENTS может измениться.

Кроме того в предыдущей строке мы вероятно работали с i, почему в условии во главу угла возводится совсем другая сущность? А почему собственно мне кажется что первый идентификатор в выражении возведен во главу угла?
i равно чему-то; если i равно MAX_ELEMENTS...
Все последовательно и логично. Но это если код читать... Если воспринимать код целостно, то, возможно, все воспринимается несколько иначе.

Тесты наверное врут, когда определяют меня как кинестатика-визуала. Хотя с другой стороны я люблю чтобы было красиво. Я смотрю на код и целиком. Только когда я смотрю на код - я почему-то не смотрю на идентификаторы, Свысока я разглядываю группы операторов, то есть мыслю уже на другом уровне.

С другой стороны неприятие распределения в соответствии с числовой прямой может связано со складом ума. Предполагаю, что эта запись очень близка к математической, сам то я от математики далек. Может быть людям с математическим складом ума она кажется более естественной чем мне, гуманитарию.

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

PS: Новогодние праздники сильно выбивают из колеи. Ленишься и ничего не хочется делать. Приходится себя заставлять, ну хоть сегодня напиши хоть что нибудь. :)

9 коммент.:

Анонимный комментирует...

Лично я тоже противник написания в сравнениях константы как lvalue, а переменной/выражения - как rvalue.

в качестве примера - пожалуйста:

FILE *fd;
if ((fd=fopen(...))!=NULL)
{
//...
}

В такой записи прослеживается логика (при условии, что читаешь код слева направо), когда в такой:
if (NULL != (fd=fopen(...)))
просто хочется убить творца такого кода.

Может, для тех, кто читает код справа налево, это, наоборот, понятнее, но не для меня.

З.Ы. А ещё я не гнушаюсь на скобки:

Я лучше напишу такой код:
if ((a>b) && (c<d))
Чем:
if (a>b && c<d)
Потому что, прежде всего, не надо вспоминать приоритет операции &&.

Omega комментирует...

Я уже привыкла писать сначала константу, но момент дискомфорта при чтении тоже присутствует.

PS. тоже хочу тест на репрезентативные системы.

Андрей Валяев комментирует...

ошибка... :) Неинициализированная переменная O-8E

Кроме того лично я считаю что подобная функция слишком тяжела для if. :)

Если извращаться в условиях, то легко не заметить ошибку типа '==' vs '='. В то время как в условии типа (fd != NULL) ошибиться очень трудно.

Насчет скобок полностью согласен. Вообще надо стремиться всеми силами сделать программу интуитивно понятнее. Если приходиться задумываться, значит мы зря тратим свои умственные силы. Предпочитаю тратить их с большей пользой. Вообще я очень примитивно пишу.

2omega: Кроме того все компиляторы сейчас прекрасно ругаются на (fd = NULL), так что помоему ты зря мучаешься.

Про тест уже не помню, давно тестировался. Где-то в интернете был.

barss комментирует...

А еще дело в компиляторе. if (NULL == a) ... даст меньше инструкций.

Андрей Валяев комментирует...

2barss: Это что за компилятор такой? эксперименты с gcc не выявили подобного поведения.

при -O0 сравнение в обоих случаях делается так:
cmpl $0, -8(%ebp)
Мнемоника ассемблера сама по себе не допускает вариаций. только один r/m32 и один imm32 то бишь константа.

При -O>0 gcc во всех случаях сгенерировал:
testl %eax, %eax
Тут вообще ноль не фигурирует.

Кроме того сдается мне, что задумывание о таких вещах сродни преждевременной оптимизации, которая есть зло! :)

Unknown комментирует...

Вообще-то, операция сранения дистрибутивна, в отличие от некоторых других.

Так что, может вам стоит просто подругому читать? ;)

Не "если i равно чему-то там", а "если i и что-то там равны"...

Андрей Валяев комментирует...

Не, это не наш путь.

Наш путь - это делать так, чтобы нам было легче жить, а не так чтобы привыкнуть и нормально.

Давайте без пробелов писать, cперва будет трудно, но потом привыкнем?

Анонимный комментирует...

2 [b]Андрей Валяев[/b]
Хорошая статья. Наконец я понял, почему не люблю писать if (NULL == ptr) :-)) И есть люди, которым тоже так писать некомфортно.

2 [b]SadKo[/b]
Потому что, прежде всего, не надо вспоминать приоритет операции &&.
Ну знаете... Приоритет операций все-таки нужно помнить, как никак базовая вещь. Лишние скобки загромождают код. Некоторые вообще пишут
#define AND &&
#define BITAND &
if ((r BITAND 0x1f) AND (a BITAND 0x1f)) ...
Крайний случай, но все же... иногда может быть полезно.

Я, например, не задумываюсь уже давно над такой конструкцией. Дело привычки. Код видишь целостно, не разбираясь в деталях. Моск напрягают алгоритмы.

Еще нравится код типа
if ( a && b && c ||
d && e && f)
но я так все-таки не пишу, другим может быть сложно понять. Хотя конструкция ясна - код if исполняется, если одно из двух условий верно.

2 [b]barss[/b]
А еще дело в компиляторе. if (NULL == a) ... даст меньше инструкций.
Ого! Пример в студию! Какой компилятор так может ступить?

Эксперименты с MSVC 2003 тоже не выявили подобных проблем.

Нормальный компилятор, на этапе высокоуровневой оптимизации, сам все делает, т.к. понимает, что для программера разницы нет, a==b или b==a.


2 [b]Андрей Валяев[/b]
Кроме того сдается мне, что задумывание о таких вещах сродни преждевременной оптимизации, которая есть зло! :)
Преждевременная низкоуровневая оптимизация есть зло, это 100% (ну 99%). А о высокоуровневой надо задумываться с самого начала.

Андрей Валяев комментирует...

2SadKo: в качестве примера - пожалуйста:

FILE *fd;
if ((fd=fopen(...))!=NULL)
{
//...
}


Еще один момент вспомнил...
Страустрап, если не ошибаюсь, рекомендует писать так:

if (FILE fd = fopen(...)) {
//...
}

Это типа локализует переменную fd в блоке if. Но я так никогда не пишу, потому что одиночный знак '=' сильно режет глаза. Я знаю что в условии должно стоять сравнение а не присваивание. :)

Хотя может быть это и хороший ход. Приучиться чтоль?