2013-03-24 3 views
8

ich einigen alten Code Refactoring, wenn ich auf ein Konstrukt ähnlich wie diese gestolpert:Ersetzen IF mit einem logischen Ausdruck in PHP

// function bar() returns a value 
// if the value is an instance of customException class, terminate with error code 
// else process the regular data 

$foo = bar(); 
checkForException($foo) && exit($foo->errorCode()); 
process($foo); 

Jetzt seltsam es scheinen mag, ist dies viel kürzer als

$foo=bar(); 
if(checkForException($foo)) { 
    exit($foo->errorCode(); 
} 
else { 
    process($foo); 
} 

Und etwas besser lesbar (zumindest nach der ersten Überraschung) dann

$foo=bar(); 
(checkForException($foo)) ? exit($foo->errorCode()) : process($foo); 

Während kürzerer Code bedeutet nicht unbedingt mehr lesbaren Code, ich finde dies irgendwo in der Mitte der beiden "Standard" -Wege oben.

Mit anderen Worten, statt

if($foo) { 
    bar(); 
} 
else { 
    // there is no real reason for this to exist, since 
    // I have nothing to write here, but I want to conform 
    // to the general coding practices and my coding OCD 
} 

Man könnte einfach

$foo && bar(); 

So schreiben, was ist der Grund für diese nicht viel zu sehen? Kann es so einfach sein wie: "Erfinde das Rad nicht neu, schreibe das besser lesbare if/else, und wenn du es wirklich verkürzen willst, dafür ist der ternäre Operator da"?

EDIT: Bitte beachten Sie, dass der obige Code wurde schnell aus dem ursprünglichen Code abgeleitet und war nur ein Beispiel für die Verwendung von "Kurzschluss" -Code. Wenn Sie können, dann zögern Sie nicht, Codeverbesserungen vorzuschlagen, da dies nicht das gewünschte Ergebnis der Frage war.

Beispiel No.2

userCheckedTheBox($user) && displayAppropriateInfo(); 
+1

In einem strukturierten Framework verwenden Sie 'exit' nicht so viel. Außerdem können Sie mit einem vollständigen 'if/else 'mehrere Anweisungen im' else'-Zweig verwenden - manchmal ist ein Kurzschluss sehr nützlich, aber missbrauchen Sie das nicht. – moonwave99

+0

Warum sollte es "seltsam" sein (wie in "seltsam wie es scheinen könnte"), dass weniger Zeichen kürzer sind als mehr Zeichen? Du musst ein behütetes Leben führen. –

+0

"Was ist der Grund dafür, dass wir nicht viel Nutzen sehen?" --- weil es verschiedene Arten von Programmierern gibt: einige schreiben "cool" Code, andere - einfach, einen zu unterstützen. – zerkms

Antwort

3

Es gibt eine alte Technik, von der ich glaube, dass sie in gehackten Perl-Skripten beliebt war, um Fehler anzuzeigen. Pseudo-Code:

myFunction() || exitWithError("Uh-oh") 

Bei der Codierung-to-a-Frist, und wenn die Benutzeroberfläche muss nicht stellar sein, es ist ein schneller Weg, um Fehler zu vermeiden.

Der Stil ist auch sehr beliebt in Javascript für Standardparameter:

function myfunction(foo) { 
    foo = foo || 0; 
    // note that a non-zero default won't work so well, 
    // because the user could call the function with 0 
} 

und für null-Kontrollen:

var bar = foo && foo.property; 

Ich finde, dass, wenn Sie es gewohnt sind, es ist sehr gut lesbar und oft intuitiver als if/else oder ?:. Aber du solltest es nur benutzen, wenn es Sinn macht. Es überall zu benutzen wird sehr verwirrend werden. In Ihrem Beispiel sollten Sie beispielsweise nicht verwenden. Persönlich verwende ich es für die einfache Fehlerprüfung und einige Standardwerte. In großen Projekten möchten Sie fast immer viel mehr tun, wenn ein Fehler auftritt. In solchen Fällen sollten Sie dies nicht verwenden.

Auch Sie sollten vorsichtig sein; dies funktioniert nur in Sprachen mit Kurzschlussauswertung (http://en.wikipedia.org/wiki/Short-circuit_evaluation). Und manchmal and und or sind Kurzschluss, während && und || nicht sind.

myfunction() or die("I'm melting!"); ist auch sehr befriedigend zu schreiben.

Schließlich leere else Blöcke in der Regel ist etwas, das ich noch nie zuvor gesehen habe, oder hörte jemand empfehlen. Es scheint mir sehr sinnlos. Die am besten lesbare Option für Ihr Beispiel ist ganz einfach:

if($foo) { 
    bar(); 
} 
6

Während $foo && bar(); weniger Codezeilen sind ist es viel weniger lesbar. Es ist in der Regel wichtiger, den Code leicht verständlich zu machen, als den gesamten LoC zu reduzieren. Selbst wenn Sie nicht in einer Umgebung mit mehreren Programmierern arbeiten, werden Sie irgendwann in der Zukunft wieder Ihren Code lesen müssen, und Sie werden wahrscheinlich nicht in der Lage sein sich zu erinnern, was hinter jeder Zeile steht Code (Eagleson's Law).

Im Allgemeinen sollten Sie die Verwendung dieser Art von Anweisungen auf Fälle beschränken, in denen die Absicht des Programmierers absolut klar ist. Meiner Meinung nach ist es sehr schlecht, einen Code zu haben, der eine Bedingung und einen Code prüft, der den aktuellen Zustand des Programms auf derselben Anweisung aktiv verändert.

Hier ist eine akzeptable Nutzung für diese Art von Code:

$isValidUser = $userName && usernameIsValid(); 

hier beide Seiten des && Betreiber sind eine Bedingung zu testen, die Tatsache, dass die rechte Seite eine Funktion aufruft, das zu tun nicht schadet die Lesbarkeit des Codes.

1

Für Fehler sollten Sie echte Ausnahmen verwenden:

try { 
    $foo = bar(); 
} catch(FooException $e) { 
    exit($e->errorCode); 
} 
process($foo); 

the documentation for errorhandling See.

+1

OP _is_ mit echten Ausnahmen ('customException'), sie werden einfach nicht geworfen, sondern als Rückgabe verwendet Wert ... –

1

Was immer dieser Code macht, die Rückgabe einer Instanz von CustomException addiert sich nicht.Warum die Funktionsdefinition nicht ein wenig ändern:

function bar() 
{ 
    $stuff = true; 
    if ($stuff === true) 
    { 
     return 'Value on success'; 
    } 
    //something went wrong: 
    throw new CustomException('You messed up'); 
} 
try 
{//here's the outlandish try-catch block 
    $foo = bar(); 
} 
catch (CustomException $e) 
{ 
    exit($e->message());//fugly exit call, work on this, too 
} 
//carry on here, no exception was thrown 

Auch fordern, dass die zweite Funktion (checkForException($foo)) nur absurd ist. Funktionsaufrufe sind billig, aber nicht kostenlos. Sie möchten wissen, ob die Funktion eine Instanz von CustomException zurückgegeben hat? Machen Sie das nicht zu einer Funktion, aber verwenden Sie instanceof. Kurzschlüsse zu verwenden, um die Anzahl der Zeichen (also die Parse-Zeit) niedrig zu halten, während gleichzeitig Ressourcen auf allen anderen Ebenen verschwendet werden, ist ungefähr so ​​albern wie das Auftauchen in einem V8-Mustang auf einem Hyper-Miling-Kurs.

+0

Ich habe meine Frage bearbeitet, um das gewünschte Ergebnis besser widerzuspiegeln. Ausnahmen werden geworfen und behandelt, die Namen sind nur ein bisschen unglücklich. – user1853181

+0

@ user1853181: Entschuldigen Sie, dass Sie so weitermachen, aber Sie geben natürlich keine Ausnahme. Wenn Sie dies täten, würde die Kurzschlussauswertung fehlschlagen und Sie würden nur eine Meldung sehen, die sagt: "Fehler: Uncaught Exception" –

+0

Soweit ich es verstanden habe, protokolliert der Ausnahmebehandler in bar() die Ausnahmeinfo und gibt den Fehler zurück benutzerdefiniertes Objekt (mit einem Fehlercode unter den anderen Informationen) an den Aufrufer. Ich bin mir sicher, dahinter steckte eine gute Absicht, die versuchte, es jetzt herauszufinden ... Aber das ist wirklich ein Thema für eine andere Frage, wenn es nötig ist. – user1853181

0

Eine weitere mögliche Lösung für Ihr Problem:

$foo = bar(); 
!checkForException($foo) or exit($foo->errorCode); 
process($foo); 

Aber besser Änderung !checkForException für isNoException oder etwas in diese Richtung.

Verwandte Themen