Designfehler ? (Vererbung)
-
Hallo,
ich habe gerade über Code von mir geguckt und da eine unschöne Sache gesehen.
Ich frage mich ob ich da eine Designfehler gemacht habe.Ich habe eine Basisklasse DBObject die ich abstrakt machen wollte, weil es keinen Sinn machte direkt Instanzen dieser Klasse zu erzeugen.(Das ist evtl. schon der Denkfehler).
Diese Klasse stellt grundlegende Datanbankfunktionen zur Verfügung. Diese Methoden kann die Klasse voll implementieren und würde völlig unabhängig von anderen Klassen in ihrer Form mit Ihren Beschränkungen funktionieren. Weil ich keine Methode hatte die ich reinvirtuell machen müsste, habe ich einfach eine Dummymethode Derive eingeführt um die Klasse abstract zu machen. (Ziemlich unschön).
Eine Klasse Manager erbt protected von DBObject. Die Managerklasse ist ihrerseits auch abstract. Dieses mal aus gutem Grund weil abgleitete Klassen die von Manager eingeführten Methoden implementieren müssen.
Was ich mich frage ist ob die protected Vererbung von DBObject an Manager wirklich ne gute Idee war, oder ob es besser gewesen wäre Manager einen DBObject-member zu geben. Da später die verwendeten Klassen nur von Manager erben ändert sich das Interface nicht. Ich tu mich nur schwer damit zu entscheiden was besser ist. Mein Gefühl sagt mir dass die Memberlösung besser ist.
Was denkt ihr ?
-
Zunächst mal, wenn Du keine Methode hast, die Du rein virtuell machen kannst, dann nimm den Destruktor (Achtung: Du brauchst trotzdem ne Implementierung).
Ansonsten kannst Du ja mal überlegen, was gegen Containment spricht. Mußt Du Methoden überladen? Dann mußt Du erben. Ansonsten müßte eigentlich auch so alles gehen.
MfG Jester
-
prolog schrieb:
Ich habe eine Basisklasse DBObject die ich abstrakt machen wollte, weil es keinen Sinn machte direkt Instanzen dieser Klasse zu erzeugen.(Das ist evtl. schon der Denkfehler).
Klingt für mich als wäre DBObject eine Art Interface. Wenn ja, dann ist es voll
Diese Klasse stellt grundlegende Datanbankfunktionen zur Verfügung. Diese Methoden kann die Klasse voll implementieren und würde völlig unabhängig von anderen Klassen in ihrer Form mit Ihren Beschränkungen funktionieren.
Das verstehe ich nicht ganz.
völlig unabhängig von was?Weil ich keine Methode hatte die ich reinvirtuell machen müsste, habe ich einfach eine Dummymethode Derive eingeführt um die Klasse abstract zu machen. (Ziemlich unschön).
Den Dtor rein virtuell machen.
Eine Klasse Manager erbt protected von DBObject.
protected - da denken wir immer sofort nach. Denn protected Vererbung kommte quasi nie vor. Alle heiligen Zeiten hat man eine private Vererbung, aber das war es dann auch schon. Das heisst jetzt natürlich nicht, dass protected Vererbung hier unpassend ist - sondern lediglich dass wir lieber doppelt sogenau hinsehen.
Was ich mich frage ist ob die protected Vererbung von DBObject an Manager wirklich ne gute Idee war, oder ob es besser gewesen wäre Manager einen DBObject-member zu geben.
protected/private vererbung verwendet man dann, wenn man es muss. Sonst ist ein Memberobjekt immer besser. Müssen tut man es, zB wenn es um protected members und/oder virtuelle Methoden geht. Siehe dazu auch Effective C++ Item 42.
Mein Gefühl sagt mir dass die Memberlösung besser ist.
Mir auch.
Allerdings hast du uns nicht erklärt in welcher Beziehung DBObject und Manager stehen. Das ist ja n relativ wichtiger Punkt.
-
Ok, danke euch beiden soweit. Ja an den Destructor hatte ich überhaupt nicht gedacht.
Jester schrieb:
Ansonsten kannst Du ja mal überlegen, was gegen Containment spricht. Mußt Du Methoden überladen? Dann mußt Du erben. Ansonsten müßte eigentlich auch so alles gehen.
MfG Jester
Das ist es ja eigentlich muss ich nichts überladen.
Shade of Mine schrieb:
Zitat:
Diese Klasse stellt grundlegende Datanbankfunktionen zur Verfügung. Diese Methoden kann die Klasse voll implementieren und würde völlig unabhängig von anderen Klassen in ihrer Form mit Ihren Beschränkungen funktionieren.Das verstehe ich nicht ganz.
völlig unabhängig von was?Ich wollte sagen, dass sie Ihre Aufgabe tut und dass eine Spezialisierung nicht notwendig ist, da sie die Methode, die sie bereitstellt selbst implementieren kann ohne dass ein Nachteil entsteht.
Hmm damit ist sie kein Interface also doch lieber einen Member nehmen.
Shade of Mine schrieb:
Allerdings hast du uns nicht erklärt in welcher Beziehung DBObject und Manager stehen. Das ist ja n relativ wichtiger Punkt.
ich dachte mir das Manager ein DBObject ist, dass ein einheitliches Interface für erlaubte Datenbankoperationen zur Verfügung stellt.
Wobei Manager keine Methoden von DBObject überläd sondern lediglich definierte Aufgaben mithilfe des DBObjects bzw. dessen Methoden erledigt.ums mal Konkret zu machen.
DbObject hält Klassen die vom Framework zur Verfügung gestellt werden und implementiert eine Methode namens SafeQuery.Manager ist die Basisklasse für abgeleitete Manager die jeweils für ihr Objekte die von der Basisklasse definierten Methoden implementieren.
Die verwalteten Objecte sind alle samt von einer Klasse Managable abgeleitet.
class DBObject{ private: //zugriffskomponenten public: virtual SafeQuery(parameter); }; class Manager : protected DBObject{ //hier die frage ob das richtig ist private: Managable *mObject; public: virtual const bool Insert(void)=0; virtual const bool Modify(void)=0; virtual const bool Delete(void)=0; };
Die von Manager abgeleiteten Klassen benutzen die Safequerymethode von DBObject.
Der Grund warum ich nicht Manager auch die Zugriffsobjecte und die SafeQuerymethode gegeben habe ist, dass es auch Objecte gibt die keine Manager sind aber eben die Funktionalität von DBObject brauchen, weil sie auch mit der Datenbank arbeiten.Während ich das hier schreibe wird mir immer klarer, dass die Member-Lösung besser ist, weil es ja doch Sinn macht eine Instanz von DBObject zu erzeugen weil sie das Lowlevelinterface zu Datenbank zur Verfügung stellt.