Member - Leichen vermeiden



  • Naja, ich gehe wie gesagt dabei von mir aus. Meist fällt mir erst nach einer ganzen Weile auf, das ich in so eine Situation gekommen bin. D.h. man müßte das Gerüst nachträglich zersägen, oder lebt halt mit nicht benötigten Membern / Schnittstellen.
    -> Wäre mir also schon lieber sowas von vornherein zu vermeiden. Ich habe im Moment so eine Situation. Gerade, wenn davon nur 1..3 abgeleitete Klassen betroffen sind tue ich mich doch schwer gleich eine neue Basisklasse einzuführen.



  • du leitest beide klassen von einer grundklasse auto ab.
    in der klasse speiechrst du nur die räderanzahl oder sachen die jedes auto hat.
    von der Klasse leitest du dann zb die klasse pkw(lichter) oder formeleinswagen ab.
    also machs wie lösung2,eine baseklasse für den kleinsten gemeinsamen nenner, und dann vererben.

    vorallem bei objekten kann man schon sehr früh sehen, dass man ne basisklasse haben muss...



  • Hi!

    TheBigW schrieb:

    Gerade, wenn davon nur 1..3 abgeleitete Klassen betroffen sind tue ich mich doch schwer gleich eine neue Basisklasse einzuführen.

    Was ist denn daran so schlimm? Es kostet doch nichts außer Zeit.
    Vielleicht solltest Du Dir mal irgendein Tool anschauen, mit dem man Code einlesen kann, ein UML-Diagramm erstellen, dieses modifizieren und wieder als Code rauslassen kann. Da liest man den Code einfach ein, legt ne neue Klasse an, zieht die Members rüber, löscht die überflüssigen raus und schon ist das fertig.
    Möglicherweise kann man auch z.B. mit Eclipse und den dort eingebauten Refactorings was reißen, das weiß ich aber leider nicht genau.

    MfG Jester



  • Was ist denn daran so schlimm? Es kostet doch nichts außer Zeit.

    Yop, schlimm genug - oder :), wo man die Zeit doch lieber für fetzige, neue Features nutzt.
    Ich werd mal schauen, was mit diversen Tools so geht - Jumli (mein bevorzugtes UML Tool) kann das IMO nicht.

    @Otze:

    Ich spreche ja nicht gegen Basisklassen -> bisweilen habe ich auch welche :). Es geht darum das solche unschönen Situationen entstehen, wenn die Projektanforderungen mutieren.
    Um bei dem kleinen Beispiel zu bleiben -> jetzt will ich noch auf Fahrzeug verallgemeinern -> Absrtraktionsebene rauf -> neue Basisklasse -> wieder Member - hin und hergezerre....



  • das ist kein hin und her gezerre, du veränderst die Klasse auto, und lässt sie dann von Fahrzeug erben :p.

    aber wenn man das problem hat, geht man definitiv von der falschen Richtung an:
    du musst dich fragen, was jedes objekt, ob auto schrank,mensch tier usw gemeinsam an sich haben, und musst davon eine baseObjekt ableiten.
    dann fragst du dich, welche arten von Objekten du überhaupt haben wirst-> ableitung von baseObjekt.
    vielleicht legst du aber noch eine Abstraktionsebene dazwischen und fragst erst,ob das objekt beweglich ist oder nicht, halt einen kleinen zwischenschritt.
    von moveableObjekt leitest du dann Fahrzeuge ab.
    von Fahrzeuge Auto und von Auto PKW.

    ok, diese aufteilung ist jetzt sehr fein,aber es wird sinnvoll, wenn man ein sehr komplexes und vorallem erweiterbares programm schreiben will.
    desweiteren sollte man drauf achten, dass jede funktion virtual bzw pure virtual sein muss(aber das wirste dir ja schon gedacht haben).



  • Ist "Hat Lichter oder nicht" so ein wichtiges Konzept in deienm Modell, das es das Einführen einer neuen Basisklasse rechtfertigt? Oder wäre "Anzahl Leuchten = 0" eine korrekte Antwort für ein Auto vom Type Formel-1?

    Wenn ja, ist Containment wahrscheinlich eine zu starke Bindung, Aggregation liegt dann näher. Natürlich erhöht das den Aufwand der Basisklasse (Enumeration und Abfrage der Komponenten, usw.), da gibt es aber auch generische Lösungen.

    Denk8t) immer daran, daß eine Objekthierarchie nur ein Modell ist - und bestimmte Aspekte der Realität betont und andere wegläßt. Ob ein Modell geeignet ist, wird allein durch die Aufgabe bestimmt.

    (beliebte Einstellungsgesprächsfrage: "Wie würdest du eine Klasse für ein Auto modellieren?" Die einzig 100% korrekte Antwort ist: "für welchen Zweck?")

    Es kostet doch nichts außer Zeit.

    "every line of code - a liability!"

    Ich klaue den Erbsenzählern gern den Begriff "Total Cost of Ownership": Existierender Code muß debuggt, gepflegt und erweitert werden. Eine komplexeres Modell erhöht den Schulungsaufwand für Neue und macht ab einem bestimmten Punkt das Gesamtsystem weniger flexibel. Insofern kannst du an jede Programmzeile ein kleines Preisschild dranhängen - und der große Batzen dabei sind laufende Kosten.



  • Ist "Hat Lichter oder nicht" so ein wichtiges Konzept in deienm Modell, das es das Einführen einer neuen Basisklasse rechtfertigt? Oder wäre "Anzahl Leuchten = 0" eine korrekte Antwort für ein Auto vom Type Formel-1?

    ist es sinnvoll abzufragen wieviele lichter ein auto hat, wenn man im vorfeld schon genau wissen kann, dass es nie lichter haben wird?

    Denk8t) immer daran, daß eine Objekthierarchie nur ein Modell ist - und bestimmte Aspekte der Realität betont und andere wegläßt. Ob ein Modell geeignet ist, wird allein durch die Aufgabe bestimmt.

    wenn man sich aber einmal für ein modell entschieden hat, sollte man es aber auch bis zum Ende durchziehen

    (beliebte Einstellungsgesprächsfrage: "Wie würdest du eine Klasse für ein Auto modellieren?" Die einzig 100% korrekte Antwort ist: "für welchen Zweck?")

    nein, das ist nicht die korrekte antwort. Denn wenn der Personalleiter jemanden mit kenntnissen im Hierarchischen Objektaufbau haben will, hast du mit der antwort verloren.
    Eine Klasse Auto ist auch definierbar, nämlich mit geschwindigkeit,position im raum,Treibstoffart(Diesel,Super,Strom,Erdgas),Verbrauch usw usf.
    Was man nicht in die Klasse auto packend arf ist zb schon die hubraumanzahl->wankelmotor.

    Ich klaue den Erbsenzählern gern den Begriff "Total Cost of Ownership": Existierender Code muß debuggt, gepflegt und erweitert werden. Eine komplexeres Modell erhöht den Schulungsaufwand für Neue und macht ab einem bestimmten Punkt das Gesamtsystem weniger flexibel. Insofern kannst du an jede Programmzeile ein kleines Preisschild dranhängen - und der große Batzen dabei sind laufende Kosten.

    Ich behaupte mal, dass code, der dahingehend programmiert wurde, dass er fast beliebig erweiterbar ist,länger ist, als Code der nicht erweiterbar ist.



  • @peterchen

    Ist "Hat Lichter oder nicht" so ein wichtiges Konzept in deienm Modell, das es das Einführen einer neuen Basisklasse rechtfertigt? Oder wäre "Anzahl Leuchten = 0" eine korrekte Antwort für ein Auto vom Type Formel-1?

    ist ja nur ein Beispiel. Es geht ja nicht (nur) um die Funktionalität, sondern darum zu verhindern, das Balast (Member / Schnittstellen) mitgeschleift wird. Bei diesem simplen Beispiel hätte ich das wohl auch so gelöst.

    Ich denke du hast Recht: irgendwie immer die Wahl zwische Pest und Cholera :).
    Leider giebt es dafür wohl keinen allgemeingültigen schicken Merksatz sondern nur von Fall zu Fall Sinn oder Unsinn.



  • ist es sinnvoll abzufragen wieviele lichter ein auto hat, wenn man im vorfeld schon genau wissen kann, dass es nie lichter haben wird?

    Ob die Frage sinnvoll ist, wird von den Applikations-Anforderungen geklärt.
    Wenn man es im Vorfeld weiß, dann ist "is-a C(Base)Auto" nicht die richtige Relation, und das wird auch nicht vom Einschieben einer Basisklasse gelöst.

    wenn man sich aber einmal für ein modell entschieden hat, sollte man es aber auch bis zum Ende durchziehen

    Ein Modell ist immer nur ein Werkzeug - natürlich bringt es nichts, bei der ersten Frage (z.B. "hat ein Formel-1 Lampen?") das ganze Modell umzuwerfen (z.B. Containment->Aggregation). Aber ein Modell sollte immer mit der Anwendung mitwachsen.

    Ich habe (leider) noch kleine Modellierungsmethode gefunden, die in der Lage ist, <i>alle</i> zukünftigen Anforderungen vorherzusehen. Meine ganz persönliche Schlußfolgerung aus den letzten 17 Jahren ist also: das einfachste, das deine jetzigen Bedürfnisse befriedigt und den absehbaren Bedürfnissen nicht im Wege steht, ist immer noch das beste.

    nein, das ist nicht die korrekte antwort. Denn wenn der Personalleiter jemanden mit kenntnissen im Hierarchischen Objektaufbau haben will, hast du mit der antwort verloren.

    Vielleicht brauch' ich ja nur Marke, das Nummernschild, und den Namen des Halters...

    Natürlich kann mich der Kandidat mit einem ungewöhnlichen, aber funktionalen Modell überraschen. Eine solche Frage zielt aber auf etwas anderes ab (was ich versucht habe in meinem vorigen Post klarzumachen): Kann der Kandidat über den Tellerrand "Objektmodellierung" hinausschauen, weiß er warum er das macht?
    ~(Außerdem: Man hat gleich einen Hinweis auf den Arbeitsstil - traut er sich, eine Frage zu stellen, wenn er etwas nicht weiß? Arbeitet er hemmungslos nach Schema F los, oder versucht er, das nicht-wissen zu kaschieren? Und wenn der Projektleiter - von dem wird die Frage ja am ehesten kommen - diese Gegenfrage nicht mag oder nicht beantworten kann, dann hab ich auch als Kandidat was über die Firma gelernt - nix gutes.)~

    Ich behaupte mal, dass code, der dahingehend programmiert wurde, dass er fast beliebig erweiterbar ist,länger ist, als Code der nicht erweiterbar ist

    Sicher. Aber wie sieht es mit Änderungen aus? Kürzungen?
    Je komplexer die Hierarchie ist, desto mehr Code ist von Änderungen bzw. Schnitten betroffen. Für eine flexible Struktur ist die Wahl der Schnittstellen selbst wichtiger als deren Anzahl.

    So oder so ist nach meiner Erfahrung das erste Schreiben einest Codeschnipsels der geringste Teil - für mich noch ein Grund , zur einfachst möglichen Struktur zu gehen.

    Dazu muß natürlich gesagt werden, daß ich Objektmodellierung nie formal als solche gelernt habe, sondern immer nur als "Gebrauchsgegenstand". Außerdem sind meine Erfahrungen sicherlich stark durch die Projekte beeinflußt, an denen ich in den letzten Jahren gearbeitet habe.



  • Ich denke nicht, daß die Einführung einer neuen Basisklasse die Applikation zwangsläufig komplexer machen muß. Zumiest verwendet man ja in der Applikation nur die hohe Abstraktionsebene, sodaß dort die Sache sogar vereinfacht wird. Und die speziellen Details der Unterklassen befinden sich alle zusammen schön an einem Fleck in deren Implementierung.



  • @BigW:
    Wie schon (viel zu oft) gesagt: Kommt halt auf die Aufgabenstellung an.

    Das Problem stellt sich ja meist, wenn CAuto schon längst in Benutzung ist. Das Einschieben einer "Verzweigung" ist oftmals der naheliegende Ausweg, allerdings sind Objekthierarchien für soetwas zu starr (bring in der Hirarchie mal "Fahrräder ohne Licht" unter...), es sei denn du willst dich mit Multiple inheritance und dem "Dreaded Diamond" rumschlagen.

    Der generische Ausweg wäre auf Aggregation zu wechseln (d.h. das "Auto" hat eine Liste von Komponenten, eine davon wäre die Lampenzahl.) Ist aber gerade in C++ durch die Unterscheidung integrale Typen vs. Klassen und den etwas exotischen Status von RTTI mit hinreichend Aufwand verbunden. Aber mit einer map<id, boost::any> kommt man hier sicher schon recht weit. Als id könnte z.B. ein String "Lampen" fungieren.

    [edit]
    eine andere Lösung wären Multiple Interfaces (ala COM), also Merfachvererbung von ABC's.
    [/edit]

    Die Diskussion "Ist ein Kreis eine Elllipse? eine Ellipse ein Kreis" in Clines CPP FAQ ist da m.E. ziemlich aufschlußreich: Clickety


Anmelden zum Antworten