Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

1

30.08.2015, 21:29

Kohäsion / Architektur

Hi,
in meiner Game Engine bzw. im Grafikmodul sieht es zur Zeit so aus,
dass 3 Klassen von einander abhängig sind.
Gemeint sind folgende Klassen:
  • Noir::Graphics::Window
  • Noir::Graphics::GL4::Context
  • Noir::Graphics::GL4::Renderer
  • Noir::graphics::GL4:: RenderQueue (bewusst nicht mitgezählt)

Die Verwendung sieht dann in etwa so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
    using namespace Noir::Graphics;
    using namespace Noir::Graphics::GL4;

    Window      window(600, 600, L"bla bla");
    Context     context(&window);

    Renderer        renderer        = context.getRenderer();
    RenderQueue   queue         = renderer.getRenderQueue();


Zitat


Anmerkung:
RenderQueue ist noch keine Feature, wird aber hinzugefügt,
damit ich eine abstrahierte, "stateless" Rendering API habe.


Ich finde dieses Design mittlerweile relativ fragwürdig, da z.B.: die Klasse "Context" absehen vom Konstruktor, der einen OpenGL 4 Kontext erstellt, keine wirkliche Funktionalität bietet,
außer wenige "Getter"-Methoden. Andererseits habe ich dadurch das, was ich unter guter Kohäsion verstehe: Jede Klasse macht nur das was sie tun soll.

Window verwaltet das Fenster, Context den Kontext (Version, Vendor etc. pp.) und Renderer verarbeitet alle Drawcalls im RenderQueue; RenderQueue sotiert alle DrawCalls und macht ggf. nutzen von Instancing um Drawcalls zu sparen.

Nur ist die Frage, ob dieses Design denn überhaupt auch wirklich GUT ist. Wäre es besser z.B.: Context und Renderer oder sogar Window,Context und Renderer in eine Klasse zusammen zu fassen?
Oder sollte man die "hat ein"-Beziehung zwischen den Klassen ändern?

Mit freundlichen Grüßen,
Julien
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Julién« (30.08.2015, 21:48)


xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

2

31.08.2015, 01:49

Bei solchen Designentscheidungen nutze ich oft gerne das KISS und YAGNI Prinzip.

Als Entwickler hat man oft eine Tendenz unnoetig komplexe Strukturen zu entwerfen weil sie sich "schoener" oder "eleganter" anfuehlen. Klassen die keine wirkliche Funktionalitaet bieten sind ein gutes Anzeichen dafuer. Erweiterbarkeit/Abstraktion/etc wird oft als Grund fuer komplexere Loesungen genannt, oft wird eine derartige Erweiterbarkeit jedoch gar nicht gebraucht.

Ich denke es laesst sich nicht pauschal sagen welche von den beiden Optionen die du genannt hast die "bessere" ist.
Was ich vorschlagen wuerde ist lieber mit einer simpleren Loesung zu beginnen, und diese zu erweitern wenn es wirklich benoetigt wird. Frueher oder spaeter wirst du eh Refactorings machen muessen.

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

3

31.08.2015, 05:11

Der Witz an der Sache ist, dass ich ja gerade beim "Refactoring" bin.

Die beiden Prinzipien hören sich gut an. Ich lese sie mir mal durch :thumbup:
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Tobiking

1x Rätselkönig

  • Private Nachricht senden

4

31.08.2015, 09:25

Bei Engines bzw. Bibliotheken allgemein macht es auch Sinn die Komplexität separat aus interner und externer Sicht zu betrachten. Als interne Umsetzung finde ich es gar nicht so schlecht. Jede Klasse hat halt genau seinen Zweck. Wobei ich mich frage warum der Context den Renderer erzeugt statt das der Renderer einen eigenen Konstruktor mit Context als Parameter hat. Als Benutzer der Engine interessiert mich der Context aber eher wenig. Da will ich eher (im Stil wie bei SFML) ein RenderWindow, das ich in einer Zeile erstellen kann und dann direkt zum Rendern verwendet werden kann. Das RenderWindow kann da halt intern auf Window, Context und Renderer zurückgreifen, damit der Umfang der Klasse in Grenzen gehalten wird.

Werbeanzeige