Forum: PC-Programmierung C++: Daten wie stark kapseln?


von Ben (Gast)


Lesenswert?

Ich schreibe grad an nem C++ Programm.
Unter anderem wird da eine "Datenbank" verwaltet, die global irgendwo 
rumfliegt.

Diese Datenbank ist im Prinzip nur ein Vector, der die einzelnen 
Einträge zusammenfasst:
1
std::vector<DatabaseEntry>;

Mir stellt sich nun die Frage ob es sinn macht, diesen globalen Vektor 
zu kapseln, nach dem Motto:
1
class Database
2
{
3
    std::vector<DatabaseEntry>;
4
...
5
//public interface
6
...
7
}

Bin mir da nicht sicher ob es guter Stil ist, den "Anwender" der 
Datensätze direkt an die Implementierung der Datenbank ranzulassen (auch 
wenn der Anwender nur ich selbst bin) oder ob eine Kapselung Sinn macht. 
Nachteil ist eben der Aufwand, ich muss einige Zugriffsfunktionen 
"durchschleifen", z.B. um Einträge hinzuzufügen.
Die Datenbank soll auch mittels boost serialisiert und abgespeichert 
werden. Grade da fände ich es schick, wenn der Anwender nur schreiben 
könnte
1
myDatabase.save();
anstatt selbst die Details der boost::serialization lib kennen zu 
müssen.

Selbiges Problem hab ich eigentlich recht oft, wenn Daten global 
verfügbar sein sollen.
Wie würdet ihr vorgehen?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Ben schrieb:
> Die Datenbank soll auch mittels boost serialisiert und abgespeichert
> werden

Und irgendwan wohl auch gelesen werden und und und ... Eine Kapselung 
macht dir das Leben einfacher, spätestens wenn deine "Datenbank" auch 
mal an verschiedenen Orten Verwendung finden soll, du das 
zugrundeliegende Datenformat oder die speicher/lade logik Ändern 
möchtest.

von Ben (Gast)


Lesenswert?

Danke, du bestätigst was ich vermutet habe.
Allerdings, ich muss halt erstmal die Zugriffsmethoden auf den internen 
Container nachbilden. Denke aber dass man eh nicht alle braucht, die so 
ein STL Container anbietet.

Zwar leicht offtopic:
Angenommen ich möchte eine Namensliste der Einträge abfragen:
wäre dieser Weg in Ordnung?:
1
std::vector<std::string> getEntryList(void)
2
{
3
    std::vector<std::string> ret;
4
  
5
  for (auto i : entries)
6
      ret.push_back(i.name);
7
  
8
  return ret;
9
}
Dank RVO müsste ich eigentlich wenig Overhead haben, obwohl ich einen 
Vector zurückgebe.
Das Iterieren über die Einträge hätte ich ja ohne extra Kapselung auch.

Grüße,
Ben

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Vielleicht offtopic: Was ist das für eine Datenbank, die in einen 
std::vector passt?

von Karl H. (kbuchegg)


Lesenswert?

Läubi .. schrieb:
> Ben schrieb:
>> Die Datenbank soll auch mittels boost serialisiert und abgespeichert
>> werden
>
> Und irgendwan wohl auch gelesen werden und und und ... Eine Kapselung
> macht dir das Leben einfacher, spätestens wenn deine "Datenbank" auch
> mal an verschiedenen Orten Verwendung finden soll, du das
> zugrundeliegende Datenformat oder die speicher/lade logik Ändern
> möchtest.

Und die Erfahrung zeigt, dass das früher oder später immer irgendwann 
der Fall sein wird.

D.h. derartige Nicht-Kapselungen sehen zwar auf den ersten Blick nach 
Arbeitsersparnis aus. Aus der Praxis heraus kann ich aber sagen, dass 
das nur auf den ersten Blick so ist. Macht man die Kapselung nicht 
heute, dann macht man sie eben morgen oder nächste Woche. Aber 
irgendwann ist der Punkt erreicht und sei es nur, weil man erkannt hat, 
dass eine derartige Kapselung auch noch ein perfekter Ort wäre, um 
zusätzliche Funktionen unterzubringen wie zb Datenvalidierung, 
Absicherung beim Einfügen von Werten, Laden/Speichern auf Datei, 
Clipboard, XML Generierung, etc. etc.

Der Unterschied: je später man die Kapselung macht, desto mehr Arbeit 
hat man damit, weil ja in der Zwischenzeit auch verwendender Code 
angefallen ist, der jetzt auf die neue Klasse umgestellt werden muss.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Ben schrieb:

> Dank RVO müsste ich eigentlich wenig Overhead haben, obwohl ich einen
> Vector zurückgebe.

Lass das das Problem des COmpilers sein. Wenn du nett bist, dann 
schreibst du diese kleine Funktion inline ins Header File. Dann hast du 
praktisch gesehen gegenüber deiner Alternativlösung ....

> Das Iterieren über die Einträge hätte ich ja ohne extra Kapselung auch.

... überhaupt keinen Overhead.

Das C++ bzw. die Verwendung von Klassen einen gewaltigen Overhead bei 
gleicher Funktionalität mit sich bringen, ist ein Mythos.

von Sebastian (Gast)


Lesenswert?

Ben schrieb:
> Allerdings, ich muss halt erstmal die Zugriffsmethoden auf den internen
> Container nachbilden. Denke aber dass man eh nicht alle braucht, die so
> ein STL Container anbietet.

Du machst natürlich nur die Zugriffsmethoden, die du jetzt gerade 
brauchst - lass das Interface so klein wie möglich, dann ist es 
hinterher einfacher, die dahinterliegende Implementierung zu ändern.
Passe das Interface so gut wie möglich an deine Bedürfnisse an, versuche 
nicht, das Interface von std::vector zu spiegeln.

von Rolf M. (rmagnus)


Lesenswert?

Ben schrieb:
> Zwar leicht offtopic:
> Angenommen ich möchte eine Namensliste der Einträge abfragen:
> wäre dieser Weg in Ordnung?:
> std::vector<std::string> getEntryList(void)
> {
>     std::vector<std::string> ret;
>
>   for (auto i : entries)
>       ret.push_back(i.name);
>
>   return ret;
> }
> Dank RVO müsste ich eigentlich wenig Overhead haben, obwohl ich einen
> Vector zurückgebe.

Ja. Ich würde beim Erzeugen des Vektors aber gleich die Kapazität 
passend angeben, da die benötigte Größe ja bekannt ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.