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

Beitrag lesen

Hallo Matthias,

so, Fußball ist vorbei und ich melde mich wie versprochen zurück.

Nachdem ich mir gerade den Thread und auch meine Antwort nochmal durchgelesen habe, glaube ich, dass mein beschriebener Ansatz tatsächlich funktionieren könnte. Allerdings habe ich noch keine wirkliche Idee, wie man anhand dieses Beispiels Vererbung vernünftig darstellen/erklären könnte. Wahrscheinlich könnte man schon eher DI erklären, was aber bestimmt zu Anfang zu weit führen würde. Ich überlege aber weiter.

Ich hab von Pascal überhaupt keine Ahnung. Noch nie was mit zu tun gehabt.

Ich möchte aber, um die Idee etwas weiter zu spinnen, Whouzuos Beitrag aus einem anderen Post aufgreifen und versuchen, das Ganze ganz grob mittels PHP zu veranschaulichen. In diesem Beitrag steht:

Du wirst mir in PHP (ohne Nutzung einer Library, die multiple dispatch emuliert) keine Implementierung zeigen können, bei der du jeweils nur an einer Stelle im Code Änderungen vornehmen musst, um folgende Liste an fachlichen Änderungen durchzuführen:

  1. Spiel um eine Karte erweitern (oder um eine Karte löschen)
  2. Das Verhalten beim Vergleich von zwei Karten ändern
  3. Eine Karte in einem anderen Zusammenhang verwenden (z.B. als Restaurantkarte) ohne ihre bisherigen Eigenschaften zu verändern oder zu löschen (lediglich ggf. zu ergänzen) (= keine Verletzung von Seperation of concerns)

Ich gehe jetzt einfach mal davon aus, dass mit "nur an einer Stelle im Code Änderungen vornehmen" heißt, dass dies unabhängig von der neu zu erstellenden Klasse ist.

Sollte ich mit Folgendem falsch liegen, korrigiert mich bitte (ich hab das nicht getestet, es geht nur um's Prinzip. Allerdings sollten sich, wenn ich richtig liege, die vorherigen Aussagen widerlegen lassen).

Guter Versuch, aber du hast erstens die Anforderungen verändert und insbesondere hast du folgendes verletzt: "ohne Nutzung einer Library, die multiple dispatch emuliert".
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). 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. In Sprachen die multiple dispatch ermöglichen, ist dieses Drumherumarbeiten hingegen nicht nötig.

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). 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.

Dein Ansatz und Bauchgefühl ist somit völlig richtig! Du hast instinktiv gespürt, dass diese Sprache nicht mächtig genug ist, um deine Gedanken in ihr auszudrücken. Du hast daher die Sprache so erweitert, dass sie ausdrucksstärker wird. Das zeigt, dass du ein gutes Gespür dafür hast, ob du deine Gedanken 1:1 in eine Sprache übertragen kannst oder eben nicht. Vielen fällt es nichteinmal auf, dass sie um ihre wirklichen Gedanken "drumherum" arbeiten.

Ein gutes Beispiel sind auch Arrays oder Listen. Nehmen wir eine Liste an Dateien, wobei jede Datei, die die Dateiendung "txt" hat, ausgegeben werden soll. Was sind deine Gedanken? "Nimm jede Datei aus der Liste, die keine Dateiendung hat und gib sie aus". In ausdrucksstarken Sprachen sieht das so aus:

listeDerDateien.filter(datei -> datei.hatDateiEndung("txt)").each(datei -> datei.ausgeben())

oder z.B. in Scala in kürzerer Form (wobei das _ sich immer auf ein Element der Liste bezieht):

listeDerDateien.filter(_ hatDateiEndung "txt").forEach(_ ausgeben)

Das spiegelt die Gedanken schon ziemlich gut wider. Wie oft sehe ich Programmierer, die folgendes schreiben (natürlich gibt es auch in PHP foreach o.ä.):

for(int $i = 0; $i < size(listeDerDateien) - 1) {
   $aktuelleDatei = listeDerDateien[$i]
   if(aktuelleDatei.hatDateiEndung("txt")) {
      aktuelleDatei.ausgeben()
   }
}

Aber sind das wirklich die Gedanken, die man hat? Denkt man wirklich "mach eine Variable i und gib ihr den Wert 0, dann guck dir die Liste der Dateien an und hol dir die Anzahl deren Elemente, zieh davon 1 ab und solange Variable i kleiner als diese Anzahl ist tue... usw.
Nicht wirklich oder? Eine Sprache sollte die eigenen Gedanken möglichst 1:1 widergeben, sodass Quellcode leicht verstanden und verändert werden kann. Die Aufgabe eines guten Entwicklers ist es dann, ein Problem richtig zu verstehen und es dann mithilfe der Sprache als Werkzeug zu formalisieren.

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