Warum ist Objekt befüllt?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Nein, eine eigene Datei ist nicht nötig. Das Programm ist noch so kurz, dass es gut ein eine Datei passt.
Was aber stört ist, dass die eine Klasse sehr lang ist und sehr viele Attribute hat. Da solltest Du Dir überlegen, wie Du das auf mehr Klassen aufteilen kannst, z.B. einen Kartenstapel.
Bei manchen Methoden ist es gar nicht nötig, dass sie in einer Klasse sind, wie wähle_farbe, bildschirm_leeren, etc.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@betzi1985: Man muss Methode nicht *immer* Parameter mitgeben (ausser `self`), aber wenn man das so gut wie *nie* tut, ist das komisch und man sollte mal schauen welche Attribute da vielleicht gar nicht in die Klasse gehören.

Der Zustand von einem Spiel mit Zügen ist das was man zwischen den Zügen wissen muss. Welche Karte ein Spieler *während* des Zugs mal ausgewählt hat und die dann während des Zugs geprüft wird ob sie denn überhaupt passt, ist wenn der Zug gespielt ist uninterresant. Das gehört nicht zu Spielzustand, also nicht als Attribut auf das Objekt. Genau so Werte die sogar nur innerhalb einer einzelnen Methode verwendet werden und das nicht über Spielzüge hinweg.

Methoden müssen auch nicht den Zustand verändern. Es gibt Methoden die einfach nur etwas berechnen und zurückgeben. Dazu zählen üblicherweise „getter“, also zum Beispiel die oberste Karte vom Kartenstapel abfragen, oder auch Prüfmethoden wie „Kann man diese Karte gerade ausspielen oder nicht“. Und letzteres sollte die Karte als Argument bekommen und auf keinen Fall den Zustand ändern. Denn wenn man diese Frage zweimal direkt hintereinander stellt, sollte da ja das gleiche Ergebnis heraus kommen.

Zustand bei MauMau sind die beiden Spieler, der verdeckte Kartenstapel, der Stapel mit den ausgespielten Karten, und Informationen die man aus der vorherigen Runde braucht; also muss ausgesetzt werden, wie viele Karten müssen gezogen werden, und was ist die Wunschfarbe. Im Grunde reicht das auch schon — man muss sich eigentlich nicht nicht extra eine „Sonderfunktion“ merken, die ergibt sich aus diesen Werten. Falls die Wunschfarbe beispielsweise nicht `None` ist, dann ist das ja gleichzeitig das Zeichen, dass die Sonderfunktion „Bube“ aktiv ist.

Weiterer Fall: Eine Methode benutzt nicht einmal `self` → dann ist das keine Methode und man muss sich fragen was diese *Funktion* eigentlich in der Klasse zu suchen hat. Es gibt tatsächlich Fälle wo die Funktion tatsächlich in die Klasse gehört — da sollte man das dann kenntlich machen, in dem man eine `staticmethod()` daraus macht.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
betzi1985
User
Beiträge: 13
Registriert: Mittwoch 1. Juni 2022, 14:00

@__Backjack__ die Wunschfarbe gehört denke ich schon in die Klasse, da sie über mehrere Spielzüge hinweg gelten könnte, weil es sein kann, dass kein SPieler über mehrere Runden diese Farbe auf der Hand hat, aber ich werde mal schauen wie ich es besser machen kann. Ich bin halt Java gewöhnt, da hast du immer meistens nur die eigenen Attribute die Du veränderst.
betzi1985
User
Beiträge: 13
Registriert: Mittwoch 1. Juni 2022, 14:00

Aber wo lernt man genau sowas? Grund lagen sind ja gut und schön, aber da lernt man nicht diese "Regeln", wie man sie anscheinend anwenden könnte. Welches gute Buch dafür, könnt ihr denn empfehlen?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@betzi1985: Ja, die Wunschfarbe gehört da rein, das habe ich doch aber geschrieben. Was redundant ist, ist die Sonderfunktion. Denn wenn die Sonderfunktion sagt „Bube“ dann ist auch immer gleichzeitig die Wunschfarbe mit einer Farbe belegt. Und wenn die Sonderfunktion nicht „Bube“ ist, dann sollte die Wunschfarbe immer `None` sein, denn das sagt ja genau das aus „es gibt keine Wunschfarbe“. Das heisst dann aber auch, dass man die Sonderfunktion „Bube“ alleine an dem Wert erkennen kann, den die Wunschfarbe hat, und man nicht extra noch mal vermerken muss, dass gerade die Sonderfunktion „Bube“ aktiv ist. Das gleiche gilt für Karten ziehen und Aussetzen, da muss man sich ja merken wie viele Karten, oder dass oder wie oft ausgesetzt werden muss. Das heisst falls die Anzahl zu ziehender Karten gleich Null ist, dann ist die Sonderfunktion „Sieben“ nicht aktiv und wenn der Wert grösser Null ist, dann ist diese Funktion offensichtlich aktiv. Damit kann man sich dann ein extra Attribut das nur sagt welche Sonderfunktion aktiv ist, sparen.

Was man natürlich auch machen kann ist einfach nur *ein* Attribut `sonderfunktion` zu haben was aber nicht einfach nur ein Aufzählungswert ist, sondern sowohl den Zustand der Sonderfunktion speichert, als auch Methoden zur Verfügung stellt um das beispielsweise als „Strategy“-Entwurfsmuster geeignet in die Spielklasse zu integrieren. Würde ich aber nicht ohne guten Grund machen, weil das erst einmal nur die Komplexität erhöht, ohne das man wirklich etwas davon hat.

Das mit dem meistens nur die eigenen Attribute verändern ist ja okay, weil Objekte hauptsächlich selbst dafür zuständig sind was mit ihrem ”inneren” Zustand passiert. In Java ist es etwas ”strenger” weil dort in der Regel selbst ”direkter” Zugriff über triviale Getter/Setter geregelt wird, wo man in Python direkt auf die Attribute zugreift, weil man die ja jederzeit durch `property()`-Attribute ersetzen kann, ohne das sich die Schnittstelle für den Benutzer der Klasse ändert.

Ein gutes Buch wo alles drin steht weiss ich jetzt so auf Anhieb nicht. So allgemein vom drüber schauen fand ich „Weniger schlecht programmieren“ von Kathrin Passig. Gleiches für „Code Craft“ von Pete Goodliffe. Beide sind allgemein und nicht für eine spezifische Programmiersprache, beide haben aber Beispiele in spezifischen Programmiersprachen, und man muss immer im Hinterkopf behalten, dass nicht alles was in den Büchern steht auf alle Programmiersprachen 100% passt. Bei Passig liest es sich beispielsweise so als wenn es eine gute Idee ist Code auf mehrere Dateien aufzuteilen und das einzelne Klassen generell ein guter Punkt für die Trennung sind, was in Python beispielsweise nicht gilt. Oder aus dem Kapitel zu OOP könnte man meinen, dass Klassen nur Sinn machen wenn sie Methoden haben und mit anderen Objekten interagieren. Das mag bei C++ oder Pascal stimmen, weil man dort alternativ reine Daten ohne zusätzliches Verhalten mit ``struct`` oder RECORD zusammenfassen kann, aber in Python oder Java ist das eine “Datenklasse“ und okay.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten