При рефакторинге некоторого кода я часто сталкиваюсь с этим:
bool highLevelFunc foo()
{
// ...
bool result = LesserLevelFunc();
if (!result) return false;
// ... Keep having fun if we didn't return
}
Есть ли способ сделать это немного более сексуальным и менее многословным? Без каких-либо накладных расходов или ошибок, конечно.
Я могу думать о макросе
#define FORWARD_IF_FALSE(r) if (!r) return r;
bool highLevelFunc foo()
{
// ...
FORWARD_IF_FALSE(LesserLevelFunc());
// ...
}
Что-нибудь лучше, т.е. без макроса препроцессора?
Для меня «читаемый» код сексуален. Я нахожу исходный код более читабельным, чем ваше предложение, поскольку в оригинале используется стандартный синтаксис C ++, а в последнем используется макрос, который мне нужно было бы найти и найти.
Если вы хотите быть более явным, вы можете сказать, if (result == false)
(или еще лучше, if (false == result)
чтобы предотвратить возможную ошибку присваивания как сравнения), но понимание !
Оператор вполне разумное ожидание, на мой взгляд.
Тем не менее, нет причин присваивать возвращаемое значение временной переменной; Вы могли бы так же легко сказать:
if (!LesserLevelFunc()) return false;
Это вполне читабельно для меня.
РЕДАКТИРОВАТЬМожно также рассмотреть возможность использования исключений вместо возвращаемых значений для сообщения о сбое. Если LesserLevelFunc()
бросил исключение, вам не нужно было бы писать какой-либо специальный код в highLevelFunc()
проверить на успех. Исключение будет распространяться через вызывающего абонента до ближайшего соответствия catch
блок.
Потому что вы можете продолжать, если LesserLevelFunc
возвращает true, я предлагаю держать его довольно близко к тому, как оно есть сейчас:
if (!LesserLevelFunc())
return false;
Прежде всего, вводя макрос, вы делаете код небезопасным. Кроме того, ваш макрос недействителен.
Выражение после оператора отрицания должно быть заключено в скобки.
#define FORWARD_IF_FALSE(r) if (!( r ) ) return r;
Во-вторых, макрос вызывает r дважды. Иногда два вызова функции не эквивалентны одному вызову одной и той же функции. Например, функция может иметь некоторые побочные эффекты или внутренние флаги, которые включаются / выключаются при каждом вызове функции.
Поэтому я хотел бы сохранить код как есть, не вводя макрос, потому что макрос не эквивалентен семантике исходного кода.