GOOGLE ADS

Mittwoch, 13. April 2022

Wie verwalte ich eine komplexe Flusssteuerung in Java?

Ich habe hier eine Weile über Java-Flusskontrolle und Ausnahmebehandlung recherchiert und habe diese allgemein anerkannten Regeln:

  • Verwenden Sie keine Ausnahmebehandlung für die Flusssteuerung

  • Vermeiden Sie geprüfte Ausnahmen, es sei denn, der Client erwartet eine Wiederherstellung (was eine nette Art zu sagen ist, dass Sie den Client zwingen, die Ausnahme zu behandeln, damit er genauso gut versuchen kann, sich davon zu erholen?)

  • Zusammen mit allgemeinen Regeln versuche ich zu folgen:

  • wenn doSomething() "etwas nicht tut", sollte der Aufrufer darauf aufmerksam gemacht werden

  • Methoden sollten sich darauf konzentrieren, eine Sache zu tun

  • Dies führt in einigen Fällen zu einer schlechten Mischung. Ich stelle fest, dass ich geprüfte Ausnahmen innerhalb von Methoden abfange und überall boolean zurückgebe und ständig aufeinanderfolgende Aufrufe überprüfen muss, indem ich so etwas mache:

    if(doA()){
    if(doB()){
    if(doC()){
    // only here do I know it's good
    }else{
    // I know C failed
    }
    }else{
    // I know B failed
    }
    }else{
    // I know A failed
    }

    Ich bekomme 5-6 verschachtelte if-else's tief in einigen Teilen und es ist ziemlich hässlich. Ganz zu schweigen von der Verwaltung einer Reihe von booleschen Variablen, um zu verfolgen, was funktioniert hat und was nicht.

    Irgendein Rat? Wäre dies ein Ort, an dem "goto" akzeptabel ist?


    Lösung des Problems

    doA()Sie sollten in die, doB(), und schauen doC(). Wenn es ziemlich unwahrscheinlich ist, dass sie fehlschlagen, lösen Sie eine Ausnahme aus, wenn sie fehlschlagen.

    try {
    doA();
    doB();
    doC();
    } catch (FailureException e) {
    // handle failure
    }

    Beispiele für unvernünftige Ausfälle gibt es zuhauf, IOException, IllegalParameterException, etc.

    Wenn sie vernünftigerweise wahrscheinlich scheitern

    if (!doA()) {
    // handle A's failure
    return;
    }
    if (!doB()) {
    // handle B's failure
    return;
    }
    if (!doC()) {
    // handle C's failure
    return;
    }

    Beispiele für vernünftige Fehler werden in Java etwas weniger betont. Einige Beispiele umfassen die read()Rückgabe von -1, wenn nichts mehr zu lesen ist. Wenn Ihr doA()tatsächlich näher benannt ist, attemptA()dann ist vielleicht die Rücksendung eines booleanHinweises auf den Erfolg des Versuchs angebracht. Denken Sie an add(...)und addAll(...)in der CollectionsSchnittstelle, sie kehren zurück, truewenn das Ergebnis Collectiongeändert wurde.

    Ein traditionelles gotoist in den meisten Sprachen keine gute Wahl, da es beim Überprüfen des Codes praktisch unmöglich ist zu wissen, woher der Code „kommt". Dieser Mangel an Kenntnis des Zustands vor dem Betreten des Blocks gotomacht es unmöglich, eine konsistente Umgebung vor dem Betreten des gotoBlocks zu garantieren. Aus diesem Grund gotogibt es in Java übrigens kein Traditional, sondern nur eine eingeschränkte Fortsetzung goto.

    Um von einer schlecht verschachtelten Struktur zu einer weniger verschachtelten Struktur zu wechseln, verwenden Sie einige Refactoring-Techniken:

    if(doA()){
    if (doB()) {
    if (doC()) {
    // only here do I know it's good
    } else {
    // I know C failed
    }
    } else {
    // I know B failed
    }
    } else {
    // I know A failed
    }
    return;

    ist äquivalent zu

    if (doA()) {
    if (doB()) {
    if (doC()) {
    // only here do I know it's good
    } else {
    // I know C failed
    }
    } else {
    // I know B failed
    }
    return;
    } else {
    // I know A failed
    return;
    }

    was äquivalent ist

    if (!doA()) {
    // I know A failed
    return;
    } else {
    if (doB()) {
    if (doC()) {
    // only here do I know it's good
    } else {
    // I know C failed
    }
    } else {
    // I know B failed
    }
    return;
    }

    Wenn der Code in „Ich weiß, dass A fehlgeschlagen ist" eine Rückgabe enthält, brauchen Sie sich keine Sorgen zu machen, dass Code unter der Bedingung doA()wahr ist, dass er in den folgenden Code fällt; So können Sie den unteren Block wie folgt fördern:

    if (!doA()) {
    // I know A failed
    return;
    }
    if (doB()) {
    if (doC()) {
    // only here do I know it's good
    } else {
    // I know C failed
    }
    } else {
    // I know B failed
    }
    return;

    Keine Kommentare:

    Kommentar veröffentlichen

    Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

    Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...