Я беру курс по промежуточным структурам данных в качестве предварительного условия для поступления в программу CS MS в университете, о котором все в Америке слышали. Одна строчка кода, написанная в классе, привлекла мое внимание:
if (a > 33 | b++ < 54) {...}
Это не пройдет проверку кода на моем рабочем месте. Если вы напишете такой код в интервью, это будет серьезным ударом по вам. (В дополнение к условности с побочными эффектами, это умный за счет ясности.)
На самом деле, я никогда не видел условия с побочными эффектами, и Googling тоже мало что показывает. Еще один студент остался после урока, чтобы спросить об этом тоже, так что я не единственный, кто думал, что это странно. Но профессор был непреклонен в том, что это приемлемый код, и что он напишет что-то подобное на работе. (Его работа в FT в качестве руководителя SWE в компании, о которой вы все слышали.)
Я не могу представить себе мир, в котором эта строка кода была бы приемлемой, не говоря уже о желательности. Я ошибаюсь? Это нормально? Как насчет более общего случая: условия с побочными эффектами? Это когда-нибудь нормально?
источник
Ответы:
Есть один полуобусловленный побочный эффект, который я могу считать вполне приемлемым:
while(iter.MoveNext())
Тем не менее, я думаю, что это в основном относится к категории " никогда не является действительно большим отборочным". Я могу вспомнить несколько редких случаев, когда я видел это приемлемым, но в целом это мерзко и его следует избегать.
Я также не могу придумать сценарий, в котором эта конкретная линия была бы приемлемой, но я также не могу придумать сценарий, в котором эта конкретная линия была бы полезна , поэтому трудно представить контекст, в котором она находится.
источник
while(v = *p++)
сканирование в стиле C / C ++ через массив с нулевым символом в конце (например, строка C) довольно распространено и широко распространено.while(c = input.read() != '\n')
достаточно идиоматичными.В моем мире чтение из памяти может рассматриваться как побочный эффект (например, отображение ввода-вывода в память).
Теперь рассмотрим следующее:
И сравните с:
Избегал ли побочный эффект (чтение) в условиях читабельности условия; или он просто дублирует код и добавляет беспорядок?
Недопустимо, чтобы условие имело побочные эффекты (если это делает код менее читабельным), и также нормально, чтобы условие имело побочные эффекты (если это делает код более читабельным). Ключевым фактором является «читабельность». Все остальное - это правила, созданные дураками в ошибочной попытке улучшить читаемость (хотя часто имеют обратный эффект).
источник
Как всегда с такими вопросами, это вопрос степени. Если бы существовало однозначное доказательство того, что какой-либо побочный эффект в
if
выражении всегда приводил к ухудшению кода, создание этих выражений было бы недопустимым. Разработчики языка могут быть ideosyncratic, люди склонные ошибаться, но они не что глупо.Тем не менее, каковы примеры оправданных побочных эффектов в
if
? Например, предположим, что вы обязаны по закону регистрировать все и любой доступ к свойствуP
объектаE
для целей аудита. (Представьте, что вы работаете на заводе по обогащению урана, и существует очень строгий юридический контроль над тем, что вашему коду разрешено делать и как он должен это делать.) Тогда любой,if
который проверяет это свойство, вызовет побочный эффект журнал аудита расширяется.Это довольно четкая сквозная проблема, она не влияет на ваши рассуждения о состоянии программы (очень сильно), и вы можете реализовать ее так, чтобы она была полностью невидимой и не отвлекала при просмотре строки с помощью
if
(скрытый прочь в аксессоре, а еще лучше через АОП). Я бы сказал, что это довольно очевидный случай побочного эффекта, который не является проблемой. Подобные ситуации можно представить, когда вы просто хотите подсчитать количество выполнений ветвлений в целях профилирования и т. Д.Чем больше эти смягчающие обстоятельства исчезают, тем более странной становится конструкция. Если конкретный тип цикла (например
if((c = getc()) == 'x') { quit(); }
, хорошо известен и принят языковым сообществом, то это гораздо меньше проблем, чем когда вы его изобретаете самопроизвольно и т. Д. Ваша примерная строка не соответствует этому стандарту, но я могу себе представить, очень, очень более ужасные, которые я даже не буду печатать, они такие ужасные.источник
Хотя это действительно вонючий код, его преимущество в том, что он проще (и, возможно, быстрее, если у вас нет хорошего оптимизирующего компилятора), чем его эквивалент
if (a > 33 | b < 54) {b++; ...} else b++;
но, конечно, можно оптимизировать его следующим образом (но будьте осторожны! в случае переполнения это поведение будет другим):
b++; if (a > 33 | b < 53) {...}
источник