2016-04-16 16 views
0

So habe ich dieses Monster von einer logischen Erklärung:Wie kann ich die Lesbarkeit in komplexen logischen Anweisungen vereinfachen oder verbessern?

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

ich immer, dass gesagt wurde, wenn Sie logische Aussagen, die eine neue Linie benötigen Sie etwas falsch zu machen könnten. Ich verstehe, dass ich es wahrscheinlich in eine neue Methode umgestalten könnte, aber es macht nicht unbedingt Sinn, dies für das zu tun, woran ich gerade arbeite. Was kann ich tun, um es lesbarer zu machen?

+0

Lesbar für wen? Du? Mich? Der Papst? Eine Zeile, zwei Zeilen, drei Zeilen, gelangweilt? Sie mögen 80 Spalten, ich mag 100 Spalten. Sie mögen wirklich kurze Namen Ich mag beschreibende Namen. Sie bevorzugen Quiche und ich nehme, was auch immer im Automaten ist. –

+0

Schreiben Sie immer Code, als ob der Betreuer ein Psychopath ist, der weiß, wo Sie leben :-P –

Antwort

2

Ich würde einfach eine temporäre Variable verwenden, um Dinge zu bereinigen:

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

Die meisten Compiler die temporäre optimieren weg sowieso.

+0

Ja, und jetzt haben Sie nur den Umfang und eine unnötige Variable verschmutzt. Dies widerspricht anderen guten Praktiken. Ist das gut oder ist das schlecht? Ist es wichtig? Warum nicht einfach Gump und uns ein '' 'sagen. '(für (auto code = 1; code> 90 && code <97 || code> 122;) {}' –

+0

Warum nicht '{... code ...}'? Ich denke nicht das Erstellen unnötiger Variablen ist eine schlechte Sache, wenn es Code lesbarer/wartbarer macht. Verschmutzung kann mit einem '{}' Block behandelt werden, und wenn Sie nicht humorvoll große Funktionen machen, spielt es keine Rolle, weil es lokal ist. Für die Leistung optimieren die meisten Compiler es Und wenn es wirklich wichtig ist, konzentriere dich auf die 10% des Programms, die 90% der Ausführungszeit beanspruchen, aber den Rest lesbar halten – Unimportant

+0

Ich zeige nur die Dinge und stelle Fragen, wenn du all das gehst Möglichkeit, eine lokale Variable hinzuzufügen, benutze eine lamba, die deinen Ausdruck auf 'if (ConditionMet (code)) reduziert}, aber nur, wenn du _really_ nach Lesbarkeit suchst .. –

0

Angenommen, die Werte in ncode und key sind beide Ganzzahlen (oder Fließkommazahlen), könnten Sie ihren summierten Wert nicht einer neuen Variablen zuweisen? Schalten Sie die Zeile in:

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

Es wird zwei Zeilen, aber es macht die Lesbarkeit meiner Meinung nach erhöhen.

0

Ich würde eine const Temperaturvariable verwenden, um die drei duplizierten (ncode[i]+key[ikey]) für die Leistung und Lesbarkeit zu ersetzen. Wiederhole dich nicht.

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

Verwenden Sie in diesem Fall auch nur <. Daher ist der erste zwei Vergleich wird „temp zwischen 90 und 97 ist eine Linie mit Stellen 90, 97 und 122 auf der Linie zeichnen, der‚gute‘temp Bereich auf der Linie in Bezug auf diese drei Punkte.

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)); 
} 

sind einige Spielzeuge

Dann:..

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

Dies kann ein bisschen mehr glatt gemacht werden, wenn wir ein Prädikat zu sein ein Funktionsobjekt Rückkehr bool definieren, die && und || und ~ ove unterstützt rloading, und haben unsere oben Spielzeug Prädikate zurückkehren, erhalten wir:

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

immer der either Präfix Lärm los.

Für mehr Effizienz in Nicht-Fällen erfassen Sie die Grenzen durch Verschieben.

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); 
} 

Mit jedem der oben toy Funktionen return predicate(lambda); statt Lambda zurück.

Dieser Code ist einfacher und shorree am Ort der Verwendung, sollte Null Laufzeit Overhead haben, ist aber eine andere Art der Codierung als herkömmliche C++.