2016-04-16 2 views
0

Так что я этот монстр логики утверждения:Как я могу упростить или улучшить читаемость в сложных логических операторах?

(((ncode[i]+key[ikey])>90 && (ncode[i]+key[ikey])<97) || (ncode[i] + key[ikey])>122) 

Я всегда говорил, что если у вас есть логические операторы, которые требуют новой линии, которую вы могли бы делать что-то неправильно. Я понимаю, что я мог бы, вероятно, преобразовать его в новый метод, но не обязательно иметь смысл делать это для того, над чем я работаю. Что я могу сделать, чтобы сделать его более читаемым?

+0

Считываемый для кого? Вы? Меня? Папа? Одна строка, две строки, три строки, скучно? Вам нравится 80 столбцов, мне нравится 100 столбцов. Вам нравятся действительно короткие имена, мне нравятся описательные имена. Вы предпочитаете quiche, и я возьму все, что в торговом автомате. –

+0

Всегда пишите код, как если бы сопровождающий был психопатом, который знает, где вы живете :-P –

ответ

2

Я бы просто использовать временную переменную для очистки вещи:

auto code = ncode[i] + key[ikey]; 
if ((code > 90 && code < 97) || (code > 122)) 

Большинство компиляторов оптимизировать временные далеко в любом случае.

+0

Да, и теперь вы только что загрязнили область действия и ненужную переменную. Это противоречит другим хорошим практикам. Это хорошо или плохо? Это имеет значение? Почему бы просто не пойти с полным Gump и us ea 'for'. '(for (auto code = 1; code> 90 && code <97 || code> 122;) {}' –

+0

Почему бы не '{... code ...}'? Я не думаю, что создание ненужных переменных плохое, если код делает его более удобочитаемым/поддерживаемым. Загрязнение может быть обработано блоком '{}', и если вы не сделаете очень сложные функции, это не так важно, потому что оно локально. Для производительности большинство компиляторов оптимизируют его в любом случае, и если это имеет значение, сосредоточьтесь на 10% программы, которая занимает 90% времени выполнения, но сохранит остальную читаемость. – Unimportant

+0

Я просто указываю вещи и задаю вопросы. Если вы собираетесь пройти все путь к добавлению локальной переменной использует lamba, который уменьшает ваше выражение до 'if (ConditionMet (code)) [}'. Но только если вы _really_ ищете удобочитаемость. –

0

Предполагая, что значения в ncode и key являются целыми числами (или числами с плавающей запятой), не могли бы вы присвоить их суммируемое значение новой переменной? Поверните линию на:

int result = ncode[i] + key[iKey]; 
if((result > 90 && result < 97) || result > 122) 
    //Logic 

Это две линии, но, на мой взгляд, это повышает читаемость.

0

Я бы использовал переменную const temp для замены трех дублированных (ncode[i]+key[ikey]) для производительности и удобочитаемости. Не повторяйте себя.

const auto temp = ncode[i] + key[ikey]; 
if (((90<temp) && (temp<97)) || (122<temp)) 

Кроме того, используйте только < в этом случае. Таким образом, первые два сравнения становится «температура находится между 90 и 97. Представьте нарисовать линию с 90, 97 и 122 на линии,„хороший“диапазон температуры на линии, относящиеся к этим трем точкам.

0
template<class Lower> 
auto is_gt(Lower&&l){ 
    return [=](auto&&x){ return l<x; }; 
} 
template<class Higher> 
auto is_lt(Higher&&l){ 
    return [=](auto&&x){ return x<l; }; 
} 
template<class L, class R> 
auto also(L&& l, R&& r){ 
    return [=](auto&&x){return l(x)&&r(x); }; 
} 
template<class L, class R> 
auto either(L&& l, R&& r){ 
    return [=](auto&&x){return l(x)||r(x); }; 
} 
template<class Lower, class Upper> 
auto between(Lower&& l, Upper&& u){ 
    return also(is_gt(l), is_lt(u)); 
} 

некоторые игрушки

. Тогда:.

if (either(between(90,97), is_gt(122))(ncode[i]+key[ikey])) { 

Это может быть немного более гладким Если мы определим предикат является функцией объекта возвращения bool, который поддерживает && и || и ~ Ove rloading, и есть наши выше игрушки возвращают предикаты, мы получим:

if ((between(90,97) || is_gt(122))(ncode[i]+key[ikey])) { 

избавившись от either приставки шума.

Для большей эффективности в случаях, не связанных с int, снимать границы путем перемещения.

template<class F> 
struct predicate_t:F{ 
    predicate_t(F const& f):F(f){} 
    template<class F2> 
    friend auto operator&&(predicate const& f1,predicate<F2> const& f2){ 
    auto r=[=](auto&&...args){ 
     return f1(args...)&&f2(args...); 
    }; 
    return predicate_t<decltype(r)>(r); 
    } 
    template<class F2> 
    friend auto operator||(predicate const& f1,predicate<F2> const& f2){ 
    auto r=[=](auto&&...args){ 
     return f1(args...)||f2(args...); 
    }; 
    return predicate_t<decltype(r)>(r); 
    } 

    template<class F2> 
    friend auto operator!(predicate const& f1){ 
    auto r=[=](auto&&...args){ 
     return !f1(args...); 
    }; 
    return predicate_t<decltype(r)>(r); 
    } 
}; 
template<class F> 
predicate_t<std::decay_t<F>> 
predicate(F&&f){ 
    return std::forward<F>(f); 
} 

С каждым из перечисленных выше функций, возвращающих toyreturn predicate(lambda); вместо лямбда.

Этот код более простой и shorree в точке использования, должен иметь нулевое рабочее время, но это другой стиль кодирования, чем обычный C++.