GOTO (aus Digitaluhr, Hilfe !)

Diese ganzen ifs machen mich ganz wuschig. :) Mit Hilfe von Java 9 VarHandles und Lambdas kann man das noch etwas abstrahieren. Naja... nur, dass man hierfür Instanzvariablen benötigt... aber egal:
Nette Variante mit Nachteilen:
a) Unübersichtlicher Code.
b) Abhängigkeit von Java 9

Die vielen Ifs kann man auch mittels einer Schleife kaschieren.
Java:
public class TimeTicker {
    private int[] max = { 10, 60, 60, 24 };
    private int[] time = { 0, 0, 0, 0 };
    public final static int PART_OF_SECOND = 0;
    public final static int SECOND = 1;
    public final static int MINUTE = 2;
    public final static int HOUR = 3;

    private int countUpValue(int value, int max) {
        value++;
        return (value >= max) ? 0 : value;
    }

    public long getExpectedDelayInMilliSeconds() {
        return 1000l / max[PART_OF_SECOND];
    }

    public void tick() {
        for (int i = 0; i < time.length; i++) {
            time[i] = countUpValue(time[i], max[i]);
            if (time[i] != 0)
                break;
        }
    }

    @Override
    public String toString() {
        return String.format("%d:%02d:%02d,%d", time[HOUR], time[MINUTE], time[SECOND], time[PART_OF_SECOND]);
    }

}
Java:
public class start {
    public static void main(String[] args) {
        TimeTicker time = new TimeTicker();
        while (true) {
            time.tick();
            try {
                Thread.sleep(time.getExpectedDelayInMilliSeconds());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(time);
        }
    }
}
 
@Blender3D Etwas unschön:
1. break
2. magische Konstanten
3. nicht an der aktuellen Zeit angelegt
4. feste Wartezeit von 100ms, dadurch ist der TimeTicker ungenau
5. final vergessen
6. final an unüblicher Stelle
7. Logik in der main
8. zu klein gewählter try-catch
9. nach 24 Stunden fliegt Dir alles um die Ohren :oops:

Java:
public class Uhr extends Thread {
    private final int[] max = { 10, 60, 60, 24 };
    private final int[] time = { 0, 0, 0, 0 };
    private static final int expectedDelayInMilliSeconds = 100;
    public static final int PART_OF_SECOND = 0;
    public static final int SECOND = 1;
    public static final int MINUTE = 2;
    public static final int HOUR = 3;

    private int countUpValue(int value, int max) {
        value++;
        return (value >= max) ? 0 : value;
    }

    public long getExpectedDelayInMilliSeconds() {
        return expectedDelayInMilliSeconds;
    }

    public void tick() {
        int time;
        int i = 0;
        do {
            time = (this.time[i] = countUpValue(this.time[i], max[i]));
            i++;
        } while (time == 0 && i < max.length);
    }

    @Override
    public String toString() {
        return String.format("%d:%02d:%02d,%d", time[HOUR], time[MINUTE], time[SECOND], time[PART_OF_SECOND]);
    }

    public static void main(String[] args) {
        try {
            Uhr time = new Uhr();
            while (true) {
                time.tick();
                Thread.sleep(time.getExpectedDelayInMilliSeconds());
                System.out.println(time);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
 
1. break
2. magische Konstanten
3. nicht an der aktuellen Zeit angelegt
4. feste Wartezeit von 100ms, dadurch ist der TimeTicker ungenau
5. final vergessen
6. final an unüblicher Stelle
7. Logik in der main
8. zu klein gewählter try-catch
9. nach 24 Stunden fliegt Dir alles um die Ohren :oops:
1.
Java:
public void tick() {
        for (int i = 0; i < time.length; i++) {
            time[i] = countUpValue(time[i], max[i]);
            if (time[i] != 0)
                break;
        }
    }
Durch break wird hier jedes 10 mal eine 2te, jedes 600 mal eine 3te und jedes 36000te mal eine if Bedingung abgefragt
Die Funktion hat die Aufgabe den Zeit Zähler zu erhöhen. Die Abbruchbedingung der Schleife ist hier gut lesbar in dem 4zeiligen Code formuliert. Deine "verbesserte Variante" mit der while Schleife reduziert die Lesbarkeit anstatt sie zu verbessern.
2) Die Konstanten sind nicht magisch sie dienen der Lesbarkeit und können später für eine Getterfunktion der einzelnen Zählerstände benutzt werden. Genauso macht es die Klasse Calendar, die Du in Deiner, nicht der Aufgabenstellung entsprechenden Lösung, verwendest.
3) 4) Das ist nicht die Aufgabe des Timetickers.
5) 6) ein private Array final zu machen hat keinen Effekt in diesem Zusammenhang. Konstant ist da nur die Referenz des auf das Array selbst. Die Konstanten sind natürlich static ,final und public. Sie werden z.B. bei einer zukünftigen getter Funktion von außen benutzt.
7) Die Logik von Timeticker ist nicht in der main. Was Du meinst ist die Testklasse, um den Timeticker zu testen. Wenn es später einmal um Genauigkeit geht wird das von einer Klasse z.B. Uhr gemacht, die diese Aufgabe erfüllt. Deshalb besitzt der TimeTicker auch die Methode
Java:
 public long getExpectedDelayInMilliSeconds() {
        return 1000l / max[PART_OF_SECOND];
    }
Diese gibt keine Konstante zurück, um es zu ermöglichen mit einer setter Funktion die Auflösung des TimeTicker einzustellen.
8) Das Testprogramm macht genau das was es soll.
9) Die Uhr beginnt wieder bei 00:00:00,0
 
Durch break wird hier jedes 10 mal eine 2te, jedes 600 mal eine 3te und jedes 36000te mal eine if Bedingung abgefragt
Die Funktion hat die Aufgabe den Zeit Zähler zu erhöhen. Die Abbruchbedingung der Schleife ist hier gut lesbar in dem 4zeiligen Code formuliert. Deine "verbesserte Variante" mit der while Schleife reduziert die Lesbarkeit anstatt sie zu verbessern.
Das sieht Dijkstra anders. ;)

2) Die Konstanten sind nicht magisch sie dienen der Lesbarkeit und können später für eine Getterfunktion der einzelnen Zählerstände benutzt werden.
In der einen Methode hast du eine magische Konstante...

3) 4) Das ist nicht die Aufgabe des Timetickers.
Das stimmt, wenn man die Aufgabe des TEs so auslegen möchte.

5) 6) ein private Array final zu machen hat keinen Effekt in diesem Zusammenhang
Aber in einem Späteren. ;)

Die Logik von Timeticker ist nicht in der main. Was Du meinst ist die Testklasse, um den Timeticker zu testen. Wenn es später einmal um Genauigkeit geht wird das von einer Klasse z.B. Uhr gemacht, die diese Aufgabe erfüllt
Du hast also nur die halbe Aufgabe gelöst. ;)

8) Das Testprogramm macht genau das was es soll
Ja, solange keine Fehler auftreten...

9) Die Uhr beginnt wieder bei 00:00:00,0
Stimmt, das habe ich übersehen. :(

--

Jedenfalls sollte es doch jetzt viiiele Lösungsmöglichkeiten für den TE geben. :)
 
Das sieht Dijkstra anders
Mit welchen Argumenten ? lol Bitte die Quelle mit Kontext angeben, bevor Du solche Dinge in den Raum stellst.

Java:
 public void tick() { // 4 Zeilen Code
        for (int i = 0; i < time.length; i++) { // Bedingung 1 = Länge des Arrays
            time[i] = countUpValue(time[i], max[i]);
            if (time[i] != 0) // Bedingung 2 = Überlauf des jeweiligen Counters
                break;
        }
    }
versus
Java:
public void tick() { // 6 Zeilen Code
        int time; // unnötige Variable
        int i = 0;
        do {
            time = (this.time[i] = countUpValue(this.time[i], max[i]));
            i++;
        } while (time == 0 && i < max.length); // verknüpfte Bedingungen erschwert die Lesbarkeit
    }
In der einen Methode hast du eine magische Konstante...
Falls Du diese Funktion meinst,
Java:
   public long getExpectedDelayInMilliSeconds() {
        return 1000l / max[PART_OF_SECOND];
    }
dann übersetze erst einmal den Methodennamen und Dir wird klar woher die Konstante 1000l kommt. Ob diese Konstante magische ist hängt dann nur mehr von den Fähigkeiten einen Code zu lesen ab. ;)
 
Zuletzt bearbeitet:
K

kneitzel

Ähm, das break mit einem GOTO zu vergleichen ist gewagt. Ebenso bei aktuellen Clean Code Fragen einen Pionier zu bringen, dessen aktive Zeit gut 2 Jahrzehnte vorbei ist, halte ich ebenso für gewagt.

Daher ist die Frage nach einer Begründung doch durchaus angebracht. Und so Kritik sollte halt begründet werden können. (Und aus aktuellem Anlass: Etwas dann einfach als "Bullshit" zu bezeichnen ist keine Begründung!)
 
Ich kann das lesen, allerdings erschwert...

Zum Versus... Das stimmt, eine Variable wäre überflüssig, spart aber einen Array Zugriff und ist leichter zu lesen...

Zu Dijkstra: https://en.wikipedia.org/wiki/Considered_harmful . Genaue Belege habe ich aber nich.

Nimm meine Kritikpunkte doch mal als sehr sinnvoll an. ;)
Ein Arrayzugriff passiert direkt. (Basics). Wo wird hier irgend etwas gespart? Und leichter zu lesen? --> time = this.time[] . Hier muss ich zwei Variablen betrachten anstatt einer.
Der Link zu Dijkstra ist mir bekannt. Du solltest diesen aber lesen, da geht es um GOTO also einen Sprung. Das hat mit break gar nichts zu tun. Der Unterschied ist Dir aber scheinbar nicht geläufig. Also ich bin gerne bereit begründete Kritikpunkte anzunehmen, weil man sich nur mit Kritikfähigkeit weiterentwickelt. Wobei hier die Betonung auf begründet liegt. Ich kann in Deiner Argumentation keinen wirklich guten Grund für eine Codeänderung finden außer ich möchte diesen 'verschlechtbessern'.
 
K

kneitzel

Gewagt ist auch ein geflügeltes Wort... etwas wischi waschi... Du weißt aber schon, das Dijkstra seit geraumer Zeit nicht mehr unter den Lebenden weilt?
Schön das Thema gewechselt. 99 ist er in Ruhestand gegangen (Also aktive Zeit seid 2 Jahrzehnten vorüber - so wie ich geschrieben habe. Seine großen Veröffentlichungen waren sogar deutlich vor 99!), 2002 gestorben (Was aber in diesem Zusammenhang egal ist. Entscheidend sind ja die Aussagen, die er in seiner aktiven Zeit gemacht hat und genau diese aktive Zeit ist lange vorbei!)

Und nun? Kannst Du Deinen Kritikpunkt nun irgendwie belegen? Oder wieder mal eine unbelegte Aussage, die alle Anderen als Tatsache entgegen nehmen müssen?
 
Der Link zu Dijkstra ist mir bekannt. Du solltest diesen aber lesen, da geht es um GOTO also einen Sprung. Das hat mit break gar nichts zu tun. Der Unterschied ist Dir aber scheinbar nicht geläufig.
Ersetz das break einfach durch ein return, dann ist er sicher zufriedengestellt :p

(Im Byte-Code entspricht ein break btw einem goto. Die Punkte von Dijkstra dürften für breaks in Verbindung mit Labeln genauso gelten)
Java:
private int labels() {
    label:
    {
        label2:
        if (new Random().nextBoolean()) {
            if (new Random().nextBoolean()) {
                break label2;
            }
            return 17;
        } else {
            break label;
        }

        return 42;
    }
    return 0;
}
 
Außerdem meinte ich damit, dass man nichtmehr irdische Personen schwer fragen kann, wie sie etwas gemeint haben. (Es sei denn, jemand versteht hier etwas von Okkultismus, aber das ist jetzt wirklich am Thema vorbei...)
 
K

kneitzel

break == goto statement ist (für mich) keine unzulässige Äquivalenz. *schulterzuck*
Damit sind dann für Dich also auch switch Statements, in denen break Statements vorkommen, nicht zulässig?

Ersetz das break einfach durch ein return, dann ist er sicher zufriedengestellt :p

(Im Byte-Code entspricht ein break btw einem goto. Die Punkte von Dijkstra dürften für breaks in Verbindung mit Labeln genauso gelten)
Dann ist aber auch gar nichts erlaubt, denn Sprünge (GOTO) sind ja generell das, was am Ende die CPU macht. Also wenn man die Trennung zwischen erstelltem Code und dem daraus generierten Code nicht hat, dann wird man nur noch einfache, gradlinige Software entwickeln können fürchte ich.
(Selbst ein Funktionsaufruf ist ja nur ein pushen von Werten auf den Stack gefolgt von einem Sprung. Und am Ende dann das herunternehmen von Werten vom Stack und dann ein Sprung zu der Rücksprungadresse....)
 
break == goto statement ist (für mich) keine unzulässige Äquivalenz. *schulterzuck*
Die Anmerkung für mich ist wirklich notwendig. Du brauchst augenscheinlich einen Nachschulung für die Bedeutung Gleichheit.
GOTO. erlaubt den Sprung an eine beliebig definierte Stelle im Code.
break unterbricht eine Schleife. Genau das passiert auch in Deiner schwerer zu lesenden Version der Methode tick() in Deiner while Schleife auch.
Der Punkt ist mit break kann ich nicht an eine beliebige Stelle im Code springen. --> break != goto
Benutzt hier ein Anfänger den Account (seit 2015) von @Tobias-nrw ?
 
break unterbricht eine Schleife. Genau das passiert auch in Deiner schwerer zu lesenden Version der Methode tick() in Deiner while Schleife auch.
Der Punkt ist mit break kann ich nicht an eine beliebige Stelle im Code springen. --> break != goto
Genauer springt break hinter einen gelabelten Block, auch unabhängig von Schleifen. Aber es erlaubt eben keine Rückwärtssprünge.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben