Du bist nicht angemeldet.

Werbeanzeige

Sacaldur

Community-Fossil

Beiträge: 2 330

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

71

16.01.2014, 15:03

Im Hintergrund hat man sehr wahrscheinlich Objekte, die die ihre Position in ihrer Umgebung (dem Level oder der Map, wenn man am Beispiel von Spielen bleibt). Diese Verfügen dann über Methoden, über die man ihre Geschwindigkeit und Bewegungsrichtung beeinflussen kann bzw. worüber man ihnen sagen kann, an welche Position sie sich mit ihrer Bewegungsgeschwindigkeit bewegen sollen (wobei die Ausführung dann nicht innerhalb eines Aufrufs stattfinden würde.
Wenn sich diese Objekte nicht selbst darstellen, sondern (wie es meines Wissens in SFML der Fall ist) separat dieser noch Sprite Objekte notwendig sind, welche sich selbst zeichnen können, dann sollte jedes Sprite, welches auf den Bildschirm gezeichnet wird, auch einem im Hintergrund liegenden Objekt entsprechen.

Wenn man nun mit der Position irgendwelche Sachen (Vergleiche, Berechnungen) anstellen möchte, wird man die Position des Objekts verwenden, welches im Hintergrund verwaltet wird. Das hat zur Folge, dass man die Position des Sprites zwar irgendwie immer wieder setzen muss, man sollte diese aber nie vom Sprite abrufen müssen.
Dadurch ergibt sich, dass man hier auf den Getter (am Sprite) problemlos verzichten kann. (Und wie ich schon erwähnt habe, würde ich dots Aussagen nicht so interpretieren, dass er gegen Getter und Setter an und für sich ist oder gegen nur eine der beiden, sondern dagegen, dass beide gleichzeitig auftreten. Das basiert allerdings auf diversen anderen Diskussionen, die es in diesem Forum bereits zu dem Thema gab.)

Sauberer wäre es meiner Meinung nach, wenn man nicht manuell die Position etc. übertragen müsste, sondern dem Sprite die Quelle für seine Position mitteilen könnte. Sobald diese Datenquelle (welche auch den sichtbaren Ausschnitt und den Zoom/Betrachtungsabstand, die Kamerarotation etc. berücksichtigt) dann darüber informiert, dass sich die gewünschte Position des Sprites geändert hat, speichert das Sprite diese.


Zu deiner Sprache:
In einem anderen Thema wurde mal Rust angesprochen, da es dort nicht möglich ist, auf NullPointer-/NullReferenceExceptions/... zu stoßen, da es null in dieser Sprache nicht gibt. Ich will dir nicht vorschlagen, dieses Konzept genau so in deine Sprache zu übernehmen, allerdings wäre es evtl. ganz interessant, wenn standardmäßig einer Variable keine null-Werte zugewiesen werden könnne (und kein null durch Funktionen/Methoden zurückgegeben werden können), man aber explizit angeben kann, dass eine Variable "nullable" ist (bzw. dass eine Funktion bzw. eine Methode potenziell null zurückgeben kann). Im .NET Framework gibt es Nullable<T>, womit null an Stelle von Wertetypen möglich wird. (Die Syntax ist dabei bspw. private int? myMember;.)
Ich finde ein solches Konzept durchaus überlegenswert, nur kommt es auf das verwendete Typsystem an, ob es sich sinnvoll umsetzen lässt und dann auch brauchbar ist.

Bezüglich der Attribute kannst du dich evtl. auch an den Annotationen in anderen Klassen orientieren. In Java notiert man vor einer Klasse/einem Member mit einem @ vorangestellt (@Annotation) und in C# von eckigen Klammern eingeschlossen ([Annitation]). In Java und C# werden für solche im Hintergrund Klassen verwendet, allerdings kann das eigene System in der Hinsicht evtl. auch ein wenig anders ausgelegt werden. (Wenn man sich die Propertys in Python ansieht, sieht man auch 2 Möglichkeiten, wobei bei einer auch eine Java-artige Syntax verwendet wird, aber dennoch im Hintergrund wohl keine Klassen vorhanden sein müssen.)
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

dot

Supermoderator

Beiträge: 9 854

Wohnort: Graz

  • Private Nachricht senden

72

16.01.2014, 15:33

Deine (dot) Meinung dazu dürfte, wenn ich mich nicht irre, sein, dass man grundsätzlich nur einen Getter oder nur einen Setter braucht, da es andernfalls häufig schlechtes Design dazu führt, beides zu haben.

Richtig, meine Einstellung ist, dass es idealerweise keinen Getter oder Setter für irgendwas gibt und in den seltenen Fällen, wo man sowas doch macht, dann maximal entweder einen Getter oder Setter, beides ist unbedingt zu vermeiden.


Mit Eigenschaften meine ich Felder einer Klasse.

Sobald du das tust, ist es mit der Kapselung dahin. Wieso nicht einfach die Datenmember public machen, wenn es das ist, was du willst?

Programme bestehen doch nunmal aus Daten und Logik.

Richtig, Logik, die auf Daten arbeitet. Und die Idee von OOP ist es, Daten zu kapseln und eine Schnittstelle zur Verfügung zu stellen die die mit den Daten verbundene Logik abbildet. Properties, zumindest in der Form, wie sie wohl praktisch überall eingesetzt werden, stehen im Widerspruch dazu.

Ich denke bestes Beispiel ist doch wohl Darstellung von Daten. Wenn du getrennte Schichten für Darstellung und Logik hast, dann muss die Darstellung die Daten aus der Logik-Schicht bekommen. Wie soll das denn bitte ohne Getter gehen?! (Ich vernachlässige jetzt mal aus Einfachsheitsgründen Darstellungsobjekte, bspw. ViewModels).

Wenn deine Darstellung sich die Daten über Getter von der Logik holt, koppelst du doch unweigerlich die Darstellung an die Logik, denn auf einmal muss die Darstellung die Logik kennen und wissen, was genau in welcher Form wo aus der Logik zu holen ist!? Dies ist aber nicht Aufgabe der Darstellung. Sollte die Darstellung nicht unabhängig von der Logik sein? Eigentlich sollte die Darstellung doch nichtmal wissen müssen, dass es sowas wie "die Logik" überhaupt gibt!?


@dot:
Was ist denn mit sowas wie SetPosition oder SetColor für irgendwelche grafischen Objekte? Oder SetCaption für ein GUI-Element?
Wie würdest du das anders machen? Klar könnte man SetPosition auch MoveTo nennen (oder so ähnlich), aber im Kern bliebe es dasselbe.

Das ist imo ein wunderbares Beispiel für die verdrehte Denkweise, zu der Properties einen erziehen. Ich persönlich unterscheide zwischen Shape und Brush und bei mir zeichnet der Brush den Shape. Farbe ist eigentlich keine Eigenschaft eines Rechtecks. Ein Rechteck ist einfach nur eine Form. Gleichermaßen hat ein Shape selbst keine Position, sondern wird an eine Position gezeichnet. Ein Rechteck ist ein Rechteck, egal wo es sich befindet, wie herum es gedreht ist und welche Farbe es auch haben mag. Die Caption eines GUI Elements ist Content. Ein GUI Element stellt Content dar, dient aber nicht als Datencontainer, daher gibt es maximal ein SetCaption() o.ä., auf keinen Fall gibt es ein GetCaption(). Ich finde übrigens move() ist ein wesentlich besserer Name als setPosition(). Die Bezeichnung move() impliziert nicht so stark, dass die Position eine abfragbare Eigenschaft des Objektes ist. ;)


Warum Getter und Setter:
Kapselung von zusätzlicher Funktionalität. z.B. Validierung oder nachfolgender Mechanismen. + Erweiterbarkeit!
Verstecken des Types durch Interfaces.
konsistente Interfaces, unabhängig von der Implementierung.
Debugging
externe Libs, die automatisiert Getter und Setter verwenden
Funktion überschreiben

Könntest du das etwas genauer erläutern? Ich versteh leider überhaupt nicht, was du sagen willst oder worauf du hinauswillst.


Ich bin auch grundsätzlich gegen die Philosophie, Programmierer durch die Sprache disziplinieren zu wollen.

Dito.

Es geht nicht darum, Programmierer zu disziplinieren. Es geht um die Frage, wieso man dieses Feature in eine Sprache einbauen sollte. Ich kann dich nicht daran hindern und werde es auch nicht versuchen, denn darum geht es mir überhaupt nicht. Ich wollte nur mal so etwas wie eine Diskussion herbeiführen (was mir ja wohl gelungen ist; ich denke, das ist wohl eigentlich auch der Grund, wieso du diesen Thread eröffnet hast ;)), da ich ein wenig den Eindruck hatte, dass hier einfach wahl- und zusammenhanglos ein Feature nach dem Anderen aufgetürmt wird, ohne dabei überhaupt irgendetwas zu hinterfragen. Ich bin jedenfalls der Ansicht, dass die Qualität einer Sprache nicht von der Anzahl ihrer Features abhängt. Im Gegenteil. Dass nichts so wirklich dagegen spricht, impliziert nicht, dass etwas dafür spricht...

Ich will nicht deine Begeisterung schmälern, im Gegenteil, ich möchte dich nur dazu anregen, die Chance zu nutzen, vorhandene Konzepte zu hinterfragen und am Ende eine neue Sprache mit neuem, eigenen Charakter zu schaffen. ;)

Das habe ich z.B. oft gebraucht, wenn ich Strukturen direkt aus einer Datei lesen wollte.
Da aber der Compiler bei Optimierung Byte-Alignments nach belieben einbauen kann, sollte das dadurch verhindert werden.

Wäre es nicht sinnvoller, automatische Serialisierung und Deserialisierung von Objekten einzubauen (etwas dazu verwandtes hast du mit deinem copy ja bereits in Angriff), statt so einen Hack, der inhärent unportabel ist, weil auf vielen Hardwarearchitekturen gar nicht vernünftig umsetzbar!? Selbst auf dem x86 PC, der diesbezüglich eher eine Ausnahme darstellt, ist dies imo selten eine gute Lösung. Ja, du kannst so ein struct direkt aus einer Datei lesen, bezahlst dafür aber durch suboptimales Objektlayout bei jedem einzelnen Zugriff auf die so gelesenen Daten. Es hat wirklich gute Gründe, wieso es Padding und Alignment gibt, die sind nicht nur dazu da, dass man sie erst abschalten muss... ;)

Ich persönlich erachte u.A. Interfaces - die erzwungener Maßen keine Funktions-Implementierungen haben können - als eher unwichtig in einer Sprache.
Wer ein reines Interface habe will, der soll eine reine abstrakte Klasse schreiben - das geht mit meiner Sprache auch, so wie in C++ mit "virtual ... = 0",
bei mir heißt es dann halt "abstract ...".

Auf jeden Fall interessant, wie die Geschmäcker verschieden sind. Wenn ich eine Sprache entwerfen würde, wäre Vererbung vermutlich eines der ersten Dinge, die ich kicken würde, es würde nur Interfaces geben... :D

Ich habe genau deshalb Reference-Counting ewählt, weil das schon in C++11 und boost implementiert ist.
Außerdem halte ich Garbage-Collection für ineffizienter (zumindest was die Leistung betrifft).
In Objective-C z.B. wird GC zwar generell unterstützt, für iPhone/ iPad ist es aber nicht verfügbar.

Reference Counting und Garbage-Collection sind ja bei weitem nicht die einzigen Optionen, die man hat. Wirklich geteilte Besitzverhältnisse hat man eigentlich nur sehr selten, in deinem Baumbeispiel ja z.B. auch nicht. Reference Counting ist in diesem Fall ineffizient, in C++ würde man eher std::unique_ptr verwenden, als std::shared_ptr...

Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von »dot« (16.01.2014, 15:52)


TrommlBomml

Community-Fossil

Beiträge: 2 142

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

73

16.01.2014, 15:48

Na moment du bist der Meinung, dass Getter und Setter schlechtes Design sind, benutzt aber selber mindestens einen? Dann brauchst du sie ja doch ;). Kapselung heißt doch auch nur, dass die Funktionalität und Fähigkeiten (== Eigenschaften == Felder) nicht direkt publiziert werden sollten, dass die Kontroller innerhalb des Objektes bleibt. Aber genau das wird doch durch Getter und Setter gekapselt. Und das ganze in einem Getter/Setter zu tun und immer das in eine Struktur oder Subklassen zu tun ist doch teilweise total overengineered. Selbst dein Brush hat doch wohl mehr als einen Getter und Setter?! Es gibt halt auch einfach Fälle, wo Eigenschaften publiziert werden können, einfach, weil sie ziemlich "frei" sind. Bspw. Debug-Flags, die Namen in Trace-Ausgaben repräsentieren, Position von Objekten. Ich glaube, du siehst da einige Teile der theoretischen Informatik etwas zu sehr mit Tunnelblick. Ich hab in meiner ganzen Laufbahn noch nie gehört oder Erfahren, dass sowas schlechtes Design ist. Du versuchst doch auch nicht jede Klasse in ein Design-Pattern zu pressen, weil man die Benutzen soll oder?

Schorsch

Supermoderator

Beiträge: 5 193

Wohnort: Wickede

Beruf: Student

  • Private Nachricht senden

74

16.01.2014, 16:14

Warum müssen eigentlich immer direkt so Grundsatzdiskussionen angezettelt werden? Vor allem denke ich haben solche Diskussionen doch recht wenig mit der Praxis zu tun. In der Industrie muss vieles eben nun mal quick and dirty gehen. Zeit ist eben Geld. So habe ich es zumindest teilweise erlebt und so sieht es auch bei Bekannten von mir aus. Ob man das jetzt unterstützen möchte ist eine andere Sache. Aber vor allem um so Dinge wie Code Design und was ist jetzt besser im OOP Sinne als etwas anderes, das sind Punkte da kann man sich im Prinzip beliebig lange drüber streiten und kommt zu keinem Ergebnis. Dann können wir als nächstes darüber sprechen ob die Sprache low level Dinge unterstützen soll um möglichst performant entwickeln zu können oder nicht, danach geht es dann darum ob OpenGL oder DirectX Anbindung besser wäre und wenn wir dann damit fertig sind streiten wir uns noch ein wenig über Betriebssysteme die den Compiler dann am Ende benutzen können sollen.
dot dir ging es jetzt hier ja um Getter und Setter und darum dass diese oft ein Anzeichen für schlechtes Design sind. Das würden dir die meisten wohl so unterschreiben, aber Properties haben ja mehr Nutzen als einfache schlichte Getter und Setter. Und weiterhin weißt du doch eigentlich dass diese Grundsatzdiskussionen wie hier zu nichts führen. Ich mein wenn du/ihr euch das antun wollt könnt ihr das ja gern tun, aber an sich macht das so ein Thema wie hier schnell kaputt finde ich.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

dot

Supermoderator

Beiträge: 9 854

Wohnort: Graz

  • Private Nachricht senden

75

16.01.2014, 16:59

Na moment du bist der Meinung, dass Getter und Setter schlechtes Design sind, benutzt aber selber mindestens einen?

Extrem selten, niemals beides und ganz sicher nicht in einer Form, die spezielle Sprachunterstützung rechtfertigen würde...und ich sage nicht, dass ich mit meinem Design immer und überall völlig zufrieden wäre, oder es gar als makellos ansehen würde, ganz im Gegenteil, ich bin praktisch nie mit meinem Design zufrieden... ;)


Im Kern hast du Recht, pauschalisierst aber zuviel. Ich denke man sollte Getter/Setter vermeiden, wenn es geht, aber in der Praxis geht es eben oft nicht. Das ist dann aber auch kein Zeichen von schlechtem Design, sondern einfach notwendig.

Nun, genau hier muss ich widersprechen. Meiner Erfahrung nach geht es in der Praxis eben meist schon und steigert die Codequalität enorm. Wenn man allerdings von vornherein mit der Einstellung herangeht, dass es sich eh nicht vermeiden lässt, wird man es wohl auch kaum ernsthaft versuchen... ;)

Die Tween Engine setzt Getter sowie Setter voraus um ein Objekt über die Zeit zu manipulieren. Heißt du musst Getter und Setter bereitstellen um ein definiertes Attribut zu verändern.

Und dass es in der Praxis gemacht wird, heißt für dich, dass es in der Praxis nicht besser geht und man daher am besten vor dem Problem kapituliert!? :P


Selbst dein Brush hat doch wohl mehr als einen Getter und Setter?!

Nope, keinen einzigen, wofür sollte er denn sowas brauchen? Der grüne Brush ist doch ein anderer Brush, als der blaue und der, der die Holztextur malt, ist sowieso nochmal was völlig Anderes... ;)

Ich glaube, du siehst da einige Teile der theoretischen Informatik etwas zu sehr mit Tunnelblick. Ich hab in meiner ganzen Laufbahn noch nie gehört oder Erfahren, dass sowas schlechtes Design ist.

Ich hab ehrlich gesagt relativ wenig Ahnung von theoretischer Informatik und ich versichere dir, dass ich nicht einfach nur nachplappere, was ich mal in irgendwelchen Büchern, Vorlesungen oder sonst wo aufgeschnappt hab. Alles was ich bisher hier gesagt hab, basiert auf persönlicher Erfahrung...das bedeutet auch, dass ich nicht behaupte, meine Meinung wäre die einzig richtige Meinung... ;)

Allerdings muss man schon sagen, dass 1) nur dass etwas eine theoretische Disziplin ist nicht heißt, dass Erkenntnisse aus dieser Disziplin keinen praktischen Wert besitzen und 2) Softwaredesign absolut keine theoretische Disziplin ist. All diese Grundsätze für "gutes Design", Design Pattern etc. kommen aus der Praxis. Man schaue sich nur mal an, wer das ursprüngliche Design Patterns Buch geschrieben hat und was dort im Vorwort steht...

Kapselung heißt doch auch nur, dass die Funktionalität und Fähigkeiten (== Eigenschaften == Felder) nicht direkt publiziert werden sollten, dass die Kontroller innerhalb des Objektes bleibt. Aber genau das wird doch durch Getter und Setter gekapselt. Und das ganze in einem Getter/Setter zu tun und immer das in eine Struktur oder Subklassen zu tun ist doch teilweise total overengineered.

Prinzipiell hast du damit nicht unrecht, darum ging es mir allerdings nicht wirklich. Aber lassen wir das, es passt langsam tatsächlich nicht mehr ins Thema hier.


Warum müssen eigentlich immer direkt so Grundsatzdiskussionen angezettelt werden? Vor allem denke ich haben solche Diskussionen doch recht wenig mit der Praxis zu tun. In der Industrie muss vieles eben nun mal quick and dirty gehen. Zeit ist eben Geld. So habe ich es zumindest teilweise erlebt und so sieht es auch bei Bekannten von mir aus. Ob man das jetzt unterstützen möchte ist eine andere Sache. Aber vor allem um so Dinge wie Code Design und was ist jetzt besser im OOP Sinne als etwas anderes, das sind Punkte da kann man sich im Prinzip beliebig lange drüber streiten und kommt zu keinem Ergebnis.

Ich finde, wenn es darum geht, eine Sprache zu designen, dann sind solche Grundsatzfragen von essentieller Wichtigkeit.

Dann können wir als nächstes darüber sprechen ob die Sprache low level Dinge unterstützen soll um möglichst performant entwickeln zu können oder nicht [...]

Das wäre wohl in der Tat eine sehr interessante Frage! ;)

dot dir ging es jetzt hier ja um Getter und Setter und darum dass diese oft ein Anzeichen für schlechtes Design sind.

Mir ging es vor allem darum, mal irgendetwas zu hinterfragen, anstatt einfach nur neue Features zu proposen. Getter und Setter waren lediglich das Feature, um das es zuletzt ging. Ich fand es bedenklich, dass sofort klar war, dass die Sprache Properties haben muss, wo noch nichtmal die Frage gestellt wurde, ob sie überhaupt Klassen haben soll und wenn ja wieso, wie das Typsystem aussieht (statisch/dynamisch? stark/schwach?), was überhaupt für Programmierstile unterstützt werden sollen oder was eigentlich ein konkreter Einsatzzweck der Sprache wäre. Ich bin nicht Designer der Sprache und mir geht es absolut nicht darum, diese Sprache in irgendeine Richtung zu lenken, die meinem persönlichen Geschmack entspricht. Ich denke allerdings, dass der Threadersteller sehr viel davon hätte, wenn seine Designentscheidungen, kritisch hinterfragt werden...

Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von »dot« (16.01.2014, 17:38)


dot

Supermoderator

Beiträge: 9 854

Wohnort: Graz

  • Private Nachricht senden

76

16.01.2014, 17:32

Zitat von »LetsGo«
Die Tween Engine setzt Getter sowie Setter voraus um ein Objekt über die Zeit zu manipulieren. Heißt du musst Getter und Setter bereitstellen um ein definiertes Attribut zu verändern.

Und dass es in der Praxis gemacht wird, heißt für dich, dass es in der Praxis nicht besser geht und man daher am besten vor dem Problem kapituliert!?


OK und dein konkreter Lösungsansatz wäre?

Ich kenn die Engine nicht und ich müsste mir diese wohl erstmal im Detail anschauen. Eine Beobachtung kann ich basierend auf deiner Beschreibung allerdings machen: Die Position von Objekten ergibt sich in der Regel wohl aus der Spiellogik. Eigentlich müsste also lediglich die Spiellogik die Objekte bewegen, niemals muss aber deren Position abgefragt werden. Die Engine würde idealerweise intern gar keine explizite Position speichern, sondern lediglich was auch immer für Daten für die Darstellung des Objektes benötigt werden (also z.B. eine Matrix) und keinen Getter anbieten, um Stateduplication zu vermeiden. Das Vorhandensein eines Getters verführt in dem Fall nur dazu, dass die Spiellogik die Engine-Objekte als Datencontainer missbraucht und nun plötzlich alles in beide Richtungen synchron gehalten werden muss...

Aber ich stimme zu, wenn dann sollten wir diese Diskussion nun besser in dem von dir verlinkten Thread fortführen...

Sacaldur

Community-Fossil

Beiträge: 2 330

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

77

16.01.2014, 17:33

[unnötiges Zitat entfernt]
Zitat von »LetsGo«
Die Tween Engine setzt Getter sowie Setter voraus um ein Objekt über die Zeit zu manipulieren. Heißt du musst Getter und Setter bereitstellen um ein definiertes Attribut zu verändern.

Und dass es in der Praxis gemacht wird, heißt für dich, dass es in der Praxis nicht besser geht und man daher am besten vor dem Problem kapituliert!?


OK und dein konkreter Lösungsansatz wäre?

Eine Möglichkeit schließt eine Sache ein, die ich bereits erwähnt hatte (für den aktuellen Kontext leicht angepasst):
Sauberer wäre es meiner Meinung nach, wenn man nicht manuell die [Position, Farbe, Größe, ...] etc. übertragen müsste, sondern dem [Zielelement] die Quelle für seine [Eigenschaft] mitteilen könnte. Sobald diese Datenquelle [...] dann darüber informiert, dass sich die gewünschte [Eigenschaft] geändert hat, speichert das [Element] diese.

Die Quelle der Eigenschaft (z. B. der Farbe) könnte nicht nur auf normale Objekte und deren Veränderungen reagieren und den Wert direkt durchreichen, sondern auch anhand von bestimmten Bedingungen eine Interpolation durchführen (oder andere Arten der Umrechnung anwenden, wie ich ursprünglich bereits ein Beispiel gebracht habe).
Sollte man die Datenquelle im Konstruktor übergeben können, sind keine Getter und Setter notwendig.

@dot (der ein wenig schneller war):
Anhand des "Tween" schließe ich darauf, dass es ein Framework für ein UI ist, welches vor allem für Interpolationen von Farben, Positionen, Skalierungen, Rotationen, Ausmaßen etc. da ist. Wahrscheinlich wird es auf bestimmte Events reagieren und dann definierbare Animationen (Interpolationen) starten (bspw. Umfärben der Hintergrundfarbe eines Buttons und Skalieren des Buttons beim Hovern).
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Sacaldur« (16.01.2014, 18:52)


Sacaldur

Community-Fossil

Beiträge: 2 330

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

78

16.01.2014, 18:51


Ich kenn die Engine nicht und ich müsste mir diese wohl erstmal im Detail anschauen. Eine Beobachtung kann ich basierend auf deiner Beschreibung allerdings machen: Die Position von Objekten ergibt sich in der Regel wohl aus der Spiellogik. Eigentlich müsste also lediglich die Spiellogik die Objekte bewegen, niemals muss aber deren Position abgefragt werden. Die Engine würde idealerweise intern gar keine explizite Position speichern, sondern lediglich was auch immer für Daten für die Darstellung des Objektes benötigt werden (also z.B. eine Matrix) und keinen Getter anbieten, um Stateduplication zu vermeiden. Das Vorhandensein eines Getters verführt in dem Fall nur dazu, dass die Spiellogik die Engine-Objekte als Datencontainer missbraucht und nun plötzlich alles in beide Richtungen synchron gehalten werden muss...

Aber ich stimme zu, wenn dann sollten wir diese Diskussion nun besser in dem von dir verlinkten Thread fortführen...



Die TweenEngine hat aber gar keine Ahnung davon.
Die weiß nur ich hab Attribut A und soll das in der Zeit X mit einem bestimmten Interpolations-verfahren, in einer bestimmten Zeit, einem Wert B zuweisen.
Klar wird die Spiellogik den Tween(z.B Alphafading/Positionsänderung/Farbe) anstoßen, aber um die Engine zu verwenden muss sich eben Getter und Setter bereitstellen, denn es gibt keine Alternative, außer die Funktionalität im Spieleobjekt selbst zu implementieren.

Werde ich ignoriert?
[unnötiges Zitat entfernt]
Zitat von »LetsGo«
Die Tween Engine setzt Getter sowie Setter voraus um ein Objekt über die Zeit zu manipulieren. Heißt du musst Getter und Setter bereitstellen um ein definiertes Attribut zu verändern.

Und dass es in der Praxis gemacht wird, heißt für dich, dass es in der Praxis nicht besser geht und man daher am besten vor dem Problem kapituliert!?


OK und dein konkreter Lösungsansatz wäre?

Eine Möglichkeit schließt eine Sache ein, die ich bereits erwähnt hatte (für den aktuellen Kontext leicht angepasst):
Sauberer wäre es meiner Meinung nach, wenn man nicht manuell die [Position, Farbe, Größe, ...] etc. übertragen müsste, sondern dem [Zielelement] die Quelle für seine [Eigenschaft] mitteilen könnte. Sobald diese Datenquelle [...] dann darüber informiert, dass sich die gewünschte [Eigenschaft] geändert hat, speichert das [Element] diese.

Die Quelle der Eigenschaft (z. B. der Farbe) könnte nicht nur auf normale Objekte und deren Veränderungen reagieren und den Wert direkt durchreichen, sondern auch anhand von bestimmten Bedingungen eine Interpolation durchführen (oder andere Arten der Umrechnung anwenden, wie ich ursprünglich bereits ein Beispiel gebracht habe).
Sollte man die Datenquelle im Konstruktor übergeben können, sind keine Getter und Setter notwendig.




Anderes Bsp:
Ich hab ein Button, der erzeugt bei Click ein Event. Dem Event ist eine VerursacherObjekt zugeordnet (der Button.) Im Zuge der Eventbehandlung(Dispatcher) wird dem Event dynamisch ein ZielObjekt(set) zugeordnet, wenn es bisher noch nicht bekannt war(get ==null). Ein Event ist abstrakt, es kann auch durch etwas anderes entstanden sein bei dem schon ein Zielobjekt bekannt war. Angekommen am Evenhandler, der für eben dieses Event zuständig ist werden sowohl Zielobjekt als auch Verursacherobjekt benötigt (get). (Der Button(Verursacher) wird ausgeblendet und das Zielobjekt tut irgendwas).
Immer dann wenn Ein Objekt eine Kette von Handlern (Consumerchain)oder sonstwas durchläuft (die Hierarchie einer Anwendung nach oben geht) muss es evtl mit Informationen, die zuvor nicht bekannt waren, angereichert werden. Da die jeweilige Ebene aber nicht weiß, ob die Information schon vorher bekannt war muss ich eben schauen, ob das der Fall ist oder nicht. (Getter/Setter)

Mag in Spielen vllt. nicht so häufig vorkommen, aber in verteilten Systemen ist sowas sehr sehr oft der Fall. (z.B. JavaEE).
BTW: Jemand sollte das abspalten

Mir ist nicht bekannt, dass ein Button ein Ziel hat. Ein Button kann angeklickt werden und wenn er angeklickt wurde, führen die Eventhandler ihre Aktionen aus. Die Eventhandler können dabei wiederum mit anderen Elementen Interagieren (also "ein Ziel haben").
Wenn das Ziel ermittelbar ist, dann muss es auch nicht dem Button angehangen werden, sondern kann, wenn erforderlich, von der ermittelnden Stelle zwischengespeichert werden.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Sacaldur

Community-Fossil

Beiträge: 2 330

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

79

16.01.2014, 20:10

Wenn ich nicht ignoriert werde, warum bist du dann nicht bereits vorher darauf eingegangen, warum meine Herangehensweise in diesem Fall so unangebracht wäre?
Da ich aber keinen Grund dafür herauslesen konnte, warum meine HErangehensweise schlecht wäre oder nicht funktionieren würde (oder warum das nichts mit der Thematik zu tun habe), hier meine Vorgehensweise nochmal anders formuliert.

Übergänge (Tweening) für die Hintergrundfarbe:
Gegeben ist der Button.
Der Button bezieht seine Hintergrundfarbe von irgendwoher. Woher ist in diesem Fall definiert durch die Datenquelle.
Die Datenquelle wartet wiederum auf Benachrichtigungen der Eventhandler/eines Eventhandlers am Button (MouseOver+MouseOut für einen Hovereffekt oder MouseDown+MouseUp für einen Klickeffekt).
Entweder wird der ganz normale Weg gegangen und die Datenquelle liefert als Hintergrundfarbe bei den Events direkt die neue Hintergrundfarbe.
Oder, damit farbliche Übergänge da sind, wird von der Datenquelle widerum bspw. eine Tweening Framework angeregt, welches selbst wiederum der Datenquelle über Events permanent (mehrmals die Sekunde, damit eine Animation da ist) den neuen Farbwert mitteilt.

Anklicken des Buttons und Zielobjekt:
Gegeben ist der Button.
Dem Button wurden die Eventhandler zugewiesen.
Es ist ungewiss, ob das Zielobjekt bereits bekannt ist, wenn nicht, muss es ermittelt und zugewiesen werden.
Wenn die Eventhandler es aber ermitteln müssen, ist eine Speicherung am Button lediglich ein Caching, damit bei späteren Events das Zielelement nicht wieder ermittelt werden muss.
Zudem kann der Button selbst damit nichts anfangen, sondern _nur_ die Eventhandler.
_Deshalb_ ist das Zielelement am Button fehl am Platz.
Wenn der Button in deinem Beispiel eins hat, wäre meine Lösung dennoch, es woanders hinzulegen (bspw. an die Eventhandler oder an die Stelle, die zur Ermittlung von den Eventhandlern aufgerufen wird).

Du gehst davon aus, dass die Speicherung am Button gut/sauber ist, womit du wiederum die Notwendigkeit von Gettern und Settern begründest.
Ich habe gezeigt, dass diese Annahme sehr wahrscheinlich nicht gut/unsauber ist, wodurch die darauf aufbauende Begründung der Notwendigkeit hinfällig ist.

Bei meinem anderen Beispiel hast du nicht aufgezeigt, warum dieses schlecht/ungünstig/unsauber wäre, weshalb ich auch die damit zusammenhänge Begründung zur Notwendigkeit der Getter und Setter als widerlegt sehe.


(Ich bin ein Mensch und die menschliche Wahrnehmung ist subjektiv. Es kann durchaus sein, dass ich irgendetwas übersehen habe, allerdings sehe ich derzeit nichts in dieser Richtung. Wenn du (oder ein anderer Leser) wiederum Punkte in meinen Beschreibungen siehst, die unsinnig/unverständlich/nicht schlüssig sind, kann ich darauf nur eingehen, wenn diese genannt werden.)
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

3D BYTE

Frischling

Beiträge: 12

Wohnort: Neu-Isenburg (b. Frankfurt/main)

  • Private Nachricht senden

80

16.01.2014, 21:48

Sorry das ich zwischenfunke, aber das Property-System wie bei C# hat definitiv sehr viele Vorzüge und spart viel Schreibarbeit. Auch bei Interfaces. Es ist in der Anwendung das Selbe in Grün, weil es wie Get- und Set-Methoden die gleichen Aufgaben hat. Und um ehrlich zu sein, geht es mir gewaltig auf den Nerv, in C++ jedes Get und Set ausführlich in den Interfaces zu deklarieren. Ob das jetzt einzelne Werte sind oder ganze Strukturen/Objekte ist vom Endeffekt egal. Vom Zugriff ist es schöner, einfacher, genauso sicher und lässt mich schneller gleiche sich wiederholende Ergebnisse erzielen. Von daher spricht viel für das System von C#.

dot, weil ich dir beim Besten willen nicht mehr bei den ständigen Themenwechsel folgen kann, kannst du dich mal in einem konkreten Snippet mal ausdrücken, wie du auf Objekteigenschaften eingehst und veränderst? Weil die Nummer mit dem Brush und das jede Machart und Textur eine eigene Klasse besitzen soll, kaufe ich nicht ab. Daten sind letztendlich auch Eigenschaften, deren Zugriff erforderlich ist (egal ob von der Schnittstelle oder der Implementation). Würdest du auch in konkreten Stichpunkten eingehen, wie es den Arbeitsprozess einfacher macht (Logik, Sicherheit, Performance) als bekannte Verfahren der Set und Get von Properties/Methoden?
http://www.3dbyte.de

Werbeanzeige