Whouzuo: Stein-Schere-Papier-Echse-Spock in OOP

Beitrag lesen

Hallo Whouzuo,

freut mich, dass Du geantwortet hast. Ein bisschen schade finde ich aber, dass Du eigentlich nicht mehr auf die eigentliche Ausgangsfrage (Matthias Frage im Zusammenhang mit dem, was ich geschrieben habe) eingegangen bist. Vielleicht holst Du das ja noch nach. Wäre doch schön, wenn wir mit Matthias zusammen eine schöne Lösung finden würden.

Worauf denn jetzt genau? Ich bin der Meinung, dass man gar nicht mit OOP anfangen sollte, sondern mit funktionaler Programmierung. Denn OOP ist viel viel schwieriger - wir empfinden es nur nicht so, weil wir den Lernprozess schon hinter uns haben.

Aber auch so hat mich interessiert, was zu antwortest. Deshalb hab ich Dich auch zitiert, weil ich Deine Aufgabenstellung gut fand. Ich hatte zuerst auch überlegt, ob ich Dich überhaupt zitieren sollte oder ob das am Ende blöd rüberkommt.

Nein wieso denn? Das ist doch ein spannendes und interessantes Thema. Ich habe das jetzt auch nicht so empfunden als würdest du "gegen" mich schreiben. Falls das aufgrund meines Schreibstils (bei diesem Thema werde ich einfach emotional ;)) so herübergekommen ist, dann sei hiermit gesagt, dass es nicht so gemeint war.

Guter Versuch, aber du hast erstens die Anforderungen verändert

Ja, das habe ich. Und ganz so toll fand ich das auch nicht. Habe deswegen auch nochmal explizit nach Kritik gefragt. Warum ich die Anforderung verändert habe? Eigentlich einfach, ich kann mir einfach nicht vorstellen, wie Du bei Multiple Dispatch nur an _einer_ Stelle Änderungen im Code vornehmen willst, um eine neue Klasse einzufügen (ich bin übrigens weder Informatiker noch sonst etwas in der Richtung und bei Multiple Dispatch weiß ich nur grob, um was es dabei geht).

Dem Hinzufügen einer neuen Klasse _muss_ natürlich auch das Hinzufügen einer Bewertung an einer anderen Stelle folgen - außer es wird sonst ein default Verhalten vorgegeben. Das hast du ja auch erkannt.

Meiner Meinung nach bräuchte es auch da Änderungen an mindestens zwei Stellen: Einmal musst Du eine Klasse (Karte) erstellen, auch wenn das bei Multiple Dispatch, wenn ich mich recht erinnere, nur ein mehr oder weniger leerer Rumpf ist (Änderung 1).

Der Punkt ist, dass der Typ der Karte selbst für die späteren Entscheidungen herangezogen wird und man somit mit der Definition der Klasse bereits fertig ist.

und insbesondere hast du folgendes verletzt: "ohne Nutzung einer Library, die multiple dispatch emuliert".

Das musst Du mir bitte näher erklären, das verstehe ich nicht wirklich.

Denn sollte stimmen, was ich glaube, was Du damit sagen möchtest, kann und will ich Dir zwar gar nicht widersprechen. Dann wäre diese Anforderung aber "für die Katz'". Klar, ich kann mir immer definieren, was eine "Library" ist. So können schon zwei Methoden, die eine bestimmte Aufgabe lösen sollen, eine Library sein. Und auch kann man sagen, dass "Vergleiche x mit y" eine Emulation von Multiple Dispatch ist.

Genau so ist es. In einer entsprechend ausdrucksstarken Sprache musst du solche Vergleich nicht mehr "händisch" anstellen, das übernimmt das Typsystem der Sprache vollständig für dich. Mit allen Vorteilen, z.B. automatischer Prüfung, ob jeder Typ definiert wurde, ob du Subtypen an den entsprechenden Stellen verwenden darfst und viel viel mehr. Es ist absolut kein Vergleich von Strings, Ints oder Ähnlichem notwendig, weil das der Compiler für dich tut - und wie er das intern tut, das interessiert dich nicht (solange es funktioniert).

Was du im Grunde getan hast ist ein einfaches "Scoringsystem" zu implementieren und einen eigenen Parser geschrieben, der Anhand festgelegter untypisierter Eigenschaften entsprechende Funktionalität ausführt (hier z.B. einfach Anhand von Vergleichen (bzw. dem Finden) von Strings in Arrays).

Ja, wenn Du möchtest, darfst Du das so nennen, auch wenn ich persönlich das in diesem Kontext als verwirrend empfinden würde. Ich kriege es aber gerade ehrlich gesagt nicht hin, hier den Punkt zu finden, auf den Du hinaus möchtest.

Verwirrend? Ein Parser ist jetzt nichts besonders Kompliziertes. Und dass ich es nicht schaffe dir näher zu bringen, was ich meine, das stimmt wohl. ;)

Das geht natürlich und soetwas kann man in jeder Turing-vollständigen Sprache machen, es arbeitet aber um die Sprache herum, d.h. du hast quasi eine "Sprache in einer Sprache" implementiert.

Auch das darfst Du so nennen, wenn Du möchtest. Mit dieser Argumentation könnte man aber wirklich so ziemlich alles "Sprache in einer Sprache" nennen.

Nein. Man kann das leicht prüfen. Du willst ein Programm schreiben, das eine bestimmte Funktionalität beinhaltet und tust das in einer Sprache mit "mittlerer" Ausdrucksstärke, die aber völlig ausreicht, um dein Programm umzusetzen, ohne dass du um die Sprache drumherum arbeiten musst. Wenn du das Programm jetzt in eine Sprache mit höherer Ausdrucksstärke portierst, musst du konzeptionell nichts ändern, du kannst deinen Code quasi bis auf eine andere Syntax 1:1 übernehmen. Willst du das Programm hingegen in eine Sprache niedrigerer Ausdrucksstärke portieren, musst du plötzlich das Design deines Programms umändern. Z.B. mehr oder andere Methoden verwenden, neue Variablen einführen etc.
Stell dir mal vor eine Sprache unterstützt keine Funktionen mit Rückgabewerten, sondern nur Prozeduren. Dann musst du erstmal eine Variable vor dem Aufruf der Prozedur erstellen, in der Prozedur diese Variable verändern und dann dafür sorgen, dass alle anderen Variablen nicht verändert wurden. Du bildest damit also einen Teil des Compilers, der Funktionen unterstützt, in der Sprache nach.

Lies auch mal das: http://gafter.blogspot.de/2007/03/on-expressive-power-of-programming.html

Wenn dir das immernoch alles zu schwammig ist oder unklar ist, melde dich auf Stack Overflow. ;)

In Sprachen die multiple dispatch ermöglichen, ist dieses Drumherumarbeiten hingegen nicht nötig.

Auch hier bitte ich um eine Erklärung, weil nun folgendes Beispiel _mir_ überhaupt nicht erklären kann, was Du damit ausdrücken möchtest.
Im Gegenteil erscheint es mir so, dass Du gerade genau gegen Multiple Dispatch argumentierst (siehe dazu auch weiter unten, auch wenn Du dort bereits auf "ausdrucksstarke Sprachen" zu sprechen gekommen bist; da das alles aber fließend ineinander übergeht, vermute ich, es steht in Zusammenhang zueinander).

Das ist etwas abstrakt, aber hier ein Beispiel, das es vielleicht etwas klarer macht, warum du "um die Sprache drumherum gearbeitet" hast: nehmen wir an jemand fügt eine neue Karte hinzu und ändert dein Array und ergänzt es um 'zertrümmern' => 'hart (oder irgendwas anderes)'. Was passiert? Es ändert sich das Verhalten von Karten, die überhaupt nicht betroffen sein sollten, es kann sogar zu logischen Fehlern führen (z.B. wenn für eine Karte gar kein Eintrag im Array ist).

Nein, kann es meiner Meinung nach nicht.

Es kann nicht zu logischen Fehlern führen, wenn man den von mir oben genannten Eintrag macht? Was denn sonst?

Erstens ging es um ein Lehrbeispiel und zweitens um etwas realitätsnahes, was verständlich rüberkommt.

  • Die einzelnen Spielobjekte sollen realitätsnahe Eigenschaften bekommen. Diese gelten auch außerhalb des Spiels bzw. in einem anderen Kontext (Ein "Stein" ist "hart", egal ob im Spiel oder in der Realität; ja, ich weiß, es gibt auch "weiche" "Steine", das spielt aber doch für diese ganz abstrakte Veranschaulichung keine Rolle).
  • Die einzelnen Spielobjekte sollen realitätsnahe "Angriffe" erhalten, welche auch außerhalb dieses Kontextes gelten (Ja, eine Schere muss auch nicht spitz sein...)
  • Die Korrelationen sollen "echte physikalische Gegebenheiten" oder so was in der Art erfassen und diese auch außerhalb des Spiels beibehalten (Ja, etwas "flexibles" wickelt nicht zwingend etwas "hartes" ein...)

Stimmt ja alles, hat aber was hat das jetzt mit dem Array zu tun, durch das die Bewertung gemacht wird? Das bleibt ja wie es ist.

Von der technischen Seite her: Wenn für eine Karte kein Eintrag im Array ist, beeinflusst das die Funktionsweise keineswegs, wenn ich im Beispiel keinen Fehler gemacht habe. Findet man im Korrelations-Array den entsprechenden "Angriff" nicht, so führt er schlicht und einfach ins Leere.

Es wird dann entsprechend eine 0 zurückgegeben, d.h. der Default-Case für nicht vorhandene Karten wäre, dass keine gewinnt. Solange das so gewollt ist, okay. Aber der Compiler schützt dich hier nicht davor, den Fehler zu machen, dass du eben eine Kombination vergisst. Du musst dich selbst darum kümmern und dir entweder darüber im Klaren sein, dass der defaultcase = 0 okay ist oder du musst abprüfen, ob keine Kombination vergessen wurde und dann eine Exception schmeißen.
Was in deinem kleinen Beispiel noch kein Problem sein mag, führt bei größeren Spielen sehr schnell zu einem Problem. Dort will man in Regel explizit vom Compiler darauf hingewiesen werden, dass z.B. der Aufruf von ergebnis(karte1, karte2) nicht erlaubt ist, weil diese Funktion (noch) nicht existiert (wenn kein Defaultfall angegeben ist).
Was passiert, wenn in deinem Array zweimal der gleiche Eintrag drin ist? Es wird eine 2 zurückgegeben, deine Abfrage ob ergebis = 1 oder ergebnis = -1 trifft nicht zu und es wird ausgegeben, dass es keinen Gewinner gab. Das war mit Sicherheit nicht das, was du gewollt hast oder? In einer entsprechenden Programmiersprache hättest du gar kein "if" schreiben müssen - der Fehler hätte dir nie passieren können. Den können dann natürlich stattdessen die Entwickler der Sprache machen, aber das ist nicht mehr dein Toast. ;)

Wie würdest du dem begegnen? Richtig, du würdest Prüfungen machen, die dafür sorgen, dass jemand, der diese Funktionalität nutzt, nichts "logisch Falsches" eintragen kann, höchstens etwas "fachlich Falsches". Wenn du das vernünftig umsetzt, dann hast du nichts anderes getan als einen Parser zu schreiben, der die Struktur von deinem (immernoch recht einfachen) Array oder allgemeiner ausgedrückt deiner verwendeten Datenstruktur analysiert und validiert und dann die Eingaben in unterschiedliche Funktionalität umsetzt. Ups, das ist ja genau das, was ein Compiler macht.

Nö, für solch ein Szenario (Lehrbeispiel) braucht man keine weiteren Prüfungen.

Natürlich! Für ein Lehrbeispiel braucht man auch keine "high sophisticated" Programmiersprache. Das ändert aber nichts daran, dass dieses Problem mit PHP nicht ausgedrückt werden kann, ohne die von mir aufgestellten Bedingungen zu verletzten. PHP ist nicht ausdrucksstark genug.

Wahrscheinlich nicht mal in einem praxisnahen Beispiel. Blödsinn und Fehler kann man immer machen, da hilft auch die beste Prüfung nichts. Wenn da einer reinschreibt "Fußgänger überfährt Auto" soll er das machen.

Das ist aber ein fachlicher Fehler, kein logischer. Dagegen kann dich natürlich nichts schützen - aber das ist auch nicht die Aufgabe des Compilers. Der soll dich vor logischen Fehlern schützen.

0 55

Stein-Schere-Papier-Echse-Spock in OOP

Matthias Apsel
  • programmiertechnik
  1. 0
    Whouzuo
    1. 0
      T-Rex
      1. 0
        Whouzuo
  2. 0
    T-Rex
    1. 0

      Stein-Schere-Papier-Echse-Spock

      Auge
      • menschelei
  3. 0
    M.
  4. 0
    Encoder
    1. 0
      Matthias Apsel
      1. 0
        Encoder
        1. 0
          Matthias Apsel
          1. 0
            Whouzuo
            1. 0
              Matthias Apsel
              1. 0
                Whouzuo
        2. 0
          Matthias Apsel
  5. 0
    T-Rex
    1. 0
      Whouzuo
      1. 0
        Encoder
        1. 0
          Whouzuo
          1. 0
            Encoder
            1. 0
              Whouzuo
              1. 0
                Encoder
                1. 0
                  Matthias Apsel
                2. 0
                  Whouzuo
                  1. 0
                    Matthias Apsel
                    1. 0
                      Whouzuo
                    2. 0
                      Whouzuo
                      1. 0
                        Matthias Apsel
      2. 0
        Matthias Apsel
        1. 0
          Whouzuo
          1. 0
            Matthias Apsel
            1. 0
              Whouzuo
              1. 0
                Matthias Apsel
                1. 0
                  Whouzuo
                  1. 0
                    Matthias Apsel
              2. 0
                dedlfix
                1. 0
                  dedlfix
                2. 0
                  Whouzuo
      3. 0
        T-Rex
    2. 0
      T-Rex
      1. 0
        Matthias Apsel
  6. 3
    Der-Dennis
    1. 3
      Der-Dennis
      1. 0
        Whouzuo
        1. 0
          Der-Dennis
          1. 0
            Whouzuo
            1. 0
              Der-Dennis
          2. 0

            Stein-Schere-Papier-Echse-Spock in OOP (Teil 2)

            Whouzuo
            1. 0
              Der-Dennis
              • menschelei
    2. 0
      Matthias Apsel
      1. 0
        Der-Dennis
        1. 0
          bubble
          1. 0
            Der-Dennis
        2. 0
          Matthias Apsel
        3. 0
          Matthias Apsel