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

1

26.12.2015, 00:34

C++: Design für Datenbankklassen

Guten Abend,

ich bin gerade an der Projektplanung für ein kleines Browsergame. Dieses soll serverseitig mit dem cppcms-Framework einen Webservice zur Verfügung stellen, der auf Anfragen reagiert und Daten im JSON-Format liefert. Der Client ist bisher noch offen. Während meinen Überlegungen bin ich auf die Frage gekommen, wie es am sinnvollsten ist, die Kommunikation zwischen C++ und dem Datenbanksystem zu regeln. Dabei geht es mir weniger um die Wahl der Schnittstelle bzw. des Systems, sondern eher um die Übermittlung der Daten an eine sinnvolle C++-Klassen bzw. Interface Struktur.

Meine bisherige Überlegung dazu sieht folgendermaßen aus: Pro Tabelle in der Datenbank existiert eine Klasse, deren Attribute die einzelnen Spalten der Tabelle darstellen und diese mittels get/set Methoden zur Verfügung stellen. Einzelne Objekte dieser Klasse repräsentieren somit die verschiedenen Zeilen. Mittels unterschiedlicher statischer get-Methoden in der Klasse können verschiedene SQL-Queries ausgeführt werden (zB getAllByID() getAll() getAllByName() etc.). Nicht-statisch hingegen sind save()- und delete()-Methoden, mit welchen einzelne Objekte gelöscht bzw. gespeichert werden können.
Allgemein entsprechen diese Klassen somit nur einem Daten-Container, der ein wenig Logik implementiert. Die eigentliche Logik des Spiels wird separat dazu umgesetzt, hier will ich lediglich auf die DB-Kommunikation hinaus.

Ich bin mir nicht sicher, wie sinnvoll dieses 'Design' tatsächlich ist, daher würde mich interessieren, wie ihr an eine solche Sache herangehen würdet.

Mit freundlichen Grüßen

Kyle

Thandor

Frischling

Beiträge: 84

Wohnort: Berlin

Beruf: Softwareentwickler

  • Private Nachricht senden

2

26.12.2015, 11:03

Also ich halte dein Design für "gefärlich"...

Es kann zu Inkonsistenzen zwischen den Daten in der Datenbank un deinen Datenklassen kommen, es sei denn deine Datenklassen schreiben alle Änderungen automatisch in die Datenbank.
Oder ist diese "Inkosistenz" gewollt?
Ich mag pewn.de.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

3

26.12.2015, 15:53

Da ist überhaupt nichts gefährlich an dem Entwurf, genau so machen es viele Frameworks auch in anderen Sprachen. Die "Inkonsistenzen" sind sogar sehr sinnvoll, automatische DB-Updates hingegen sind sehr gefährlich, Stichwort Transaktion.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

26.12.2015, 21:32

Meine bisherige Überlegung dazu sieht folgendermaßen aus: Pro Tabelle in der Datenbank existiert eine Klasse, deren Attribute die einzelnen Spalten der Tabelle darstellen und diese mittels get/set Methoden zur Verfügung stellen. Einzelne Objekte dieser Klasse repräsentieren somit die verschiedenen Zeilen. Mittels unterschiedlicher statischer get-Methoden in der Klasse können verschiedene SQL-Queries ausgeführt werden (zB getAllByID() getAll() getAllByName() etc.). Nicht-statisch hingegen sind save()- und delete()-Methoden, mit welchen einzelne Objekte gelöscht bzw. gespeichert werden können.
Allgemein entsprechen diese Klassen somit nur einem Daten-Container, der ein wenig Logik implementiert. Die eigentliche Logik des Spiels wird separat dazu umgesetzt, hier will ich lediglich auf die DB-Kommunikation hinaus.

Ja, so ein Design sieht man recht häufig. Meine Erfahrung mit Datenbanken hält sich in Grenzen (ich darf mich allerdings regelmäßig mit einer Website, die auf praktisch exakt einem solchen Design in PHP aufbaut, rumschlagen und kann es gar nicht mehr erwarten, bis das Ding endlich weggeworfen und neu geschrieben wurde), aber ich persönlich würde versuchen, die Abstraktion etwas höher anzusetzen. Das von dir vorgeschlagene Design kapselt effektiv nur die SQL Abfragen; bereits das Datenbankschema an sich leaked in einem solchen Interface so halb heraus. Ich würde versuchen, die Abstraktion so hoch anzusetzen, dass selbst die Tatsache, dass im Hintergrund eine Datenbank steht, gänzlich zu einem Implementierungsdetail wird. Insbesondere das mit den statischen Methoden würd ich mir schonmal schwer überlegen. (Wieso überhaupt erst eine Klasse, wenn es effektiv nur ein paar Funktionen geben soll, die auf globalem Zustand arbeiten? Wenn es eine globale Datenbank geben soll, wäre es nicht besser, einfach ein globales Objekt mit entsprechenden Methoden zu haben?) Überleg dir mal, wofür genau die Datenbank verwendet werden soll. Musst du wirklich alle Arten von Objekten per Name oder ID oder was auch immer abfragen können? Wie sieht denn die Anwendungslogik aus, die auf dieser Datenbank errichtet werden soll? Geht es im Endeffekt nicht vielleicht sogar mehr einfach nur um Serialisierung/Deserialisierung!?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (26.12.2015, 21:47)


Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

5

27.12.2015, 14:22

Für ein früheres Projekt haben wir genau so einen Ansatz gewählt. Bei uns war die Datenbank aber auch "nur" eine reine Backup Lösung. Dafür funktioniert es aber recht gut. Inkonsistenzen können zwar entstehen, aber SQL kann dabei dabei helfen Fehlerquellen zu vermeiden (ID Überprüfungen).
Zwar ein wenig Offtopic aber:
Schau doch mal in die diversen Projekte, die "Alternativserver" für überaus populäre RPGs bieten. Das sind zwar keine Browserspiele, aber arbeiten serverseitig mit einer Datenbank und C++ Logik. Vielleicht findest du da einige Inspirationen/Alternativansätze. Und da ich schon ein wenig im Off bin ein paar Stichworte für mögliche Implementierungswege (falls du dich da noch nicht festgelegt haben solltest): mysql++, MySQL’s Connector/C++, postgreSQL, libpqxx, libpq++.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

6

28.12.2015, 12:34

Also ich halte dein Design für "gefärlich"...

Es kann zu Inkonsistenzen zwischen den Daten in der Datenbank un deinen Datenklassen kommen, es sei denn deine Datenklassen schreiben alle Änderungen automatisch in die Datenbank.
Oder ist diese "Inkosistenz" gewollt?


Ja gewollt ist diese Inkonsistenz natürlich nicht. Ich habe mir bereits über ein allgemeineres System Gedanken gemacht, bei dem die Objekte in regelmäßigen Intervallen mit der Datenbank synchronisiert werden, habe dies aber schnell wieder verworfen, da ich es für ein wenig überdimensioniert halte. Mit wenigen Ausnahmen würden die Objekte eh nach Bedarf aus der Datenbank geladen werden und nach der vollständigen Verarbeitung auch wieder dort gespeichert werden. Ich möchte also eigentlich keine zwei Datensätze parallel im System (also in der DB sowie im RAM) liegen haben.


Ja, so ein Design sieht man recht häufig. Meine Erfahrung mit Datenbanken hält sich in Grenzen (ich darf mich allerdings regelmäßig mit einer Website, die auf praktisch exakt einem solchen Design in PHP aufbaut, rumschlagen und kann es gar nicht mehr erwarten, bis das Ding endlich weggeworfen und neu geschrieben wurde), aber ich persönlich würde versuchen, die Abstraktion etwas höher anzusetzen. Das von dir vorgeschlagene Design kapselt effektiv nur die SQL Abfragen; bereits das Datenbankschema an sich leaked in einem solchen Interface so halb heraus. Ich würde versuchen, die Abstraktion so hoch anzusetzen, dass selbst die Tatsache, dass im Hintergrund eine Datenbank steht, gänzlich zu einem Implementierungsdetail wird. Insbesondere das mit den statischen Methoden würd ich mir schonmal schwer überlegen. (Wieso überhaupt erst eine Klasse, wenn es effektiv nur ein paar Funktionen geben soll, die auf globalem Zustand arbeiten? Wenn es eine globale Datenbank geben soll, wäre es nicht besser, einfach ein globales Objekt mit entsprechenden Methoden zu haben?) Überleg dir mal, wofür genau die Datenbank verwendet werden soll. Musst du wirklich alle Arten von Objekten per Name oder ID oder was auch immer abfragen können? Wie sieht denn die Anwendungslogik aus, die auf dieser Datenbank errichtet werden soll? Geht es im Endeffekt nicht vielleicht sogar mehr einfach nur um Serialisierung/Deserialisierung!?


Du meinst also mit höherer Abstraktion, dass ich ohne Datenbankklassen auskommen und das Laden der Daten direkt in meinen 'Logik'-Klassen ausführen sollte? Habe ich das richtig verstanden? ^^
Mit den Datenbankklassen versuche ich eben, die Logik des Ladens/Speicherns der Daten im Hintergrund zu belassen, sodass alle meine Logik-Komponenten nur auf diese Datenklassen zugreifen und mit der eigentlichen Datenbank nichts mehr zu tun haben.
Bei den statischen Methoden habe ich mich vielleicht etwas unklar ausgedrückt. Hier ein kurzes Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
class DummyRow {
public:
  unsigned int getID();
  void setID(unsigned int id);
  ...
  static smart_ptr<DummyRow> getByID(unsigned int id);  //Lädt ein Objekt
  static vector<smart_ptr<DummyRow> > getAll();  //Lädt alle Objekte aus der Tabelle
private:
  unsigned int mID;
};


Für ein früheres Projekt haben wir genau so einen Ansatz gewählt. Bei uns war die Datenbank aber auch "nur" eine reine Backup Lösung. Dafür funktioniert es aber recht gut. Inkonsistenzen können zwar entstehen, aber SQL kann dabei dabei helfen Fehlerquellen zu vermeiden (ID Überprüfungen).
Zwar ein wenig Offtopic aber:
Schau doch mal in die diversen Projekte, die "Alternativserver" für überaus populäre RPGs bieten. Das sind zwar keine Browserspiele, aber arbeiten serverseitig mit einer Datenbank und C++ Logik. Vielleicht findest du da einige Inspirationen/Alternativansätze. Und da ich schon ein wenig im Off bin ein paar Stichworte für mögliche Implementierungswege (falls du dich da noch nicht festgelegt haben solltest): mysql++, MySQL’s Connector/C++, postgreSQL, libpqxx, libpq++.


Das mit den alternativen Projekten ist eine super Idee. Schwebt dir da im Kopf zufällig etwas rum, das dafür taugen könnte?
Bei der Datenbank habe ich mich so weit auf PostgreSQL festgelegt. Da libpq++ wohl nicht mehr gepflegt wird und ich ungern mit der C-Variante libpq auskommen möchte, verwende ich cppdb als C++-Wrapper. Ganz sicher bin ich dabei jedoch noch nicht, da ich nicht weiß, wie hoch die 'Abdeckung' durch den Wrapper ist, also ob auch wirklich alle Funktionen zur Verfügung stehen.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

7

28.12.2015, 17:21

Und libpqxx ist nichts für dich? Zu der anderen Frage: Ich habe mich selbst noch nicht damit intensiv beschäftigt, aber vllt sind ArcEmu und MangosZERO für dich interessant.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

8

02.01.2016, 12:44

Und libpqxx ist nichts für dich? Zu der anderen Frage: Ich habe mich selbst noch nicht damit intensiv beschäftigt, aber vllt sind ArcEmu und MangosZERO für dich interessant.

Stimmt die hatte ich ganz überlesen. Danke! Schau ich an.

Zum Thema hätte ich nun noch eine andere Frage: Meine Datenbankklassen haben eben alle die Form: Private Attribute. Public Setter/Getter zum verändern. Dies ist natürlich viel Schreibarbeit. Da ich auch viel darüber lese, dass get/set Methoden schlechte Objektorientierung wären, bin ich nun am überlegen, sie ich das ganze sinnvoller gestalten könnte. Ich könnte natürlich einfach eine Struktur nehmen, in der alle Attribute sowieso public sind und die get/set Methoden einfach weglassen. Instanzen dieser Struktur würden dann von einer separaten Datenbankklasse erzeugt und zurückgegeben. Ihren Sinn würde die Struktur so erfüllen, es wäre ein reiner Datenspeicher. Jedoch sträube ich mich irgendwie noch etwas gegen diesen Ansatz ...

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

02.01.2016, 20:09

Die getter/setter Frage wurde in diesem Forum schon vielfach behandelt. Eine kurze Suche sollte dazu viel hervorbringen. Am Ende wird es oft zur Glaubensfrage. Ich persönlich bin da eher pragmatisch: Wenn ein Attribut eh gelesen und geschrieben wird und dabei keine zusätzliche Logik mitspielt, warum dann den Aufwand?
Und wenn man mal ganz ehrlich ist, ist es bei einem Einmann-Projekt nicht sooo kritisch alles supersauber zu designen/kapseln etc (Wenn man vorankommen will ist es u.U. sogar garnicht so vorteilhaft-Stichwort Scrum).
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

02.01.2016, 20:11

Ich sehe das ähnlich. Wenn eine Klasse nur ein Datencontainer ist, dann ist es eben so. Für Persistierung von Daten sind diese eben notwendig.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige