Seltsames Design?



  • Hallo zusammen,
    im Rahmen der anstehenden Prüfung wurde uns ein Klassendiagramm für die Realisierung eines Graphen gegeben.
    Das sieht folgendermaßen aus:
    Edit: Linkfix, und brandneue Version des Designs vom Lehrer. Jetzt noch schwachsinniger!
    http://www.picfront.org/d/7z4l (so sieht's im Schulbuch aus)
    http://www.picfront.org/d/7z4k (Lehrer-Implementierung)
    Nicht wundern, warum die UML-Repräsentation so abgrundtief hässlich ist, das ist BlueJ (...).

    Was mich stört ist eigentlich der Aufbau der Vorrangwarteschlange.
    Das ist doch eine relativ unsinnige Ableitungsorgie, wie ich finde.
    Das "Abschluss"-Element ist einfach nur eine "leere" Variante des Listenelements, in dem einfach sämtliche Methoden für rekursive Aufrufe (anstatt dass auf null geprüft wird) nichts machen. Das Ganze wird uns unter dem Namen des Composite-Patterns verkauft.
    Um es an diesem Bild zu erfragen:
    http://upload.wikimedia.org/wikipedia/de/3/31/Kompositum_Klassen.png
    Ich sehe zwar die Komponente (Listenelement), eine Blatt-Klasse (Abschluss) und das Kompositum (Datenknoten), aber Datenknoten fehlt doch der Verweis auf ein Listenelement?
    Und selbst wenn ich das Pattern nur nicht erkenne, wieso verwende ich das bitteschön für eine Warteschlange, die über eine verkettete Liste implementiert wird (und nicht wie von einer Priority Queue zu erwarten als AVL-Baum oder Heap)? Habe ich das Entwurfsmuster falsch verstanden? Ich bitte um Aufklärung 🙂

    Ich bin ob der (in meinen Augen) etwas aufgesetzten Komplexität des Designs verwirrt, wie man sieht.
    Das ginge doch auch einfacher und schöner, ohne den ganzen Abschluss/Datenknoten/Datenelement-Klamauk, oder etwa nicht?

    Ich hoffe ihr könnt mir helfen, ein wenig Klarheit zu schaffen.
    Danke im Voraus,
    MfG Cox



  • Dein erster Link funktioniert nicht.
    Ich halte von Vererbung generell nichts. Es zerstört die Übersicht und ist noch viel schlimmer als goto.
    Ich würde raten, dass jemand versucht hat ein möglichst einfaches Beispiel zu konstruieren, wo Composite-Patterns sinnvoll sind, und es nicht geschafft hat.
    Dir würde ich raten dir keine Gedanken über den Sinn zu machen. Du sollst es nicht verstehen, du sollst nur das Schema auswendig lernen und anwenden. Zu mehr ist Schule leider nicht fähig. Wenn das von einer Uni kommt ist das traurig, ändert aber nichts.



  • Vererbung generell zu verteufeln halte ich für ein bisschen übertrieben, aber deine Vermutung, wie das Beispiel zu Stande kam, teile ich 😉
    Gelehrt wird das in der gymnasialen Oberstufe des G8 in Bayern. Ich hoffe, an der Uni bessert sich das, was die Qualität des Lehrinhalts angeht.

    Naja, dann bleibt mir wohl nichts über, als die Pille zu schlucken, und zu tun als sei nichts gewesen...



  • Hach ja, BlueJ durfte ich in der Schule auch genießen. Ich habe es nie verstanden. Inzwischen habe ich auch eine Abneigung gegen Java weil es versucht alles in ein objektorientiertes Korsett zu zwängen, egal ob das in diesem Falle sinnvoll ist oder nicht.

    Cox schrieb:

    Ich hoffe, an der Uni bessert sich das, was die Qualität des Lehrinhalts angeht.

    Bei mir ist es deutlich besser geworden. Von gut ist es allerdings noch etwas entfernt (Berlin). Es liegt auch etwas an deinem Vorgehen. Die Uni gibt die Möglichkeit, Material und Lehrveranstaltungen um den Inhalt zu verstehen. Man kann/muss allerdings auch ein paar Schemas/Schemen/Schemata auswendig lernen um die Prüfung zu bestehen.

    Vielleicht war ich etwas zu streng zur Vererbung. Es ist schlimmer als goto, aber auch goto hat seine Vorteile. Solange es funktioniert und es nicht nötig ist, dass man es versteht, weil es ordentlich gekapselt ist, ist gegen goto und Vererbung nichts einzuwenden. Leider kommt man aber irgendwann zu dem Punkt wo etwas nicht funktioniert oder man eine Erweiterung einbauen will, und dann flucht man über jedes goto und jede Vererbung.



  • Hier zu erben kann sinnvoll sein. Aber das hängt von der verwendeten Sprache ab. Deswegten ist UML ja auch als Planungsmittel nicht das Papier wert, das man damit verballert.



  • Wenn ich so ein Umldiagram sehe, dann frage ich mich, wie man sowas als übersichtlich oder als gute Doku bezeichnen kann.



  • ehrlich schrieb:

    Wenn ich so ein Umldiagram sehe, dann frage ich mich, wie man sowas als übersichtlich oder als gute Doku bezeichnen kann.

    es behauptet ja auch niemand ernsthaft, uml sei übursichtlich...



  • Auch wenn ich privat mit NetBeans arbeite, BlueJ macht es einem nicht leichter, Java zu mögen.
    Vielleicht wäre die Sprache nicht so schlimm, wenn sie einem ordentlich beigebracht würde...nunja.
    Ich akzeptier' das mal so, danke für eure Antworten. Wenn noch wem was wichtiges Einfällt, das zu dem "Design" zu sagen ist, freue ich mich natürlich trotzdem 🙂



  • nwp2 schrieb:

    Ich halte von Vererbung generell nichts. Es zerstört die Übersicht und ist noch viel schlimmer als goto.

    Und was würdest du für alternativen vorschlagen? (Für Vererbung, nicht für goto)



  • Vererbung wo Vererbung angebracht ist. Komposition wo Komposition angebracht ist.
    Wobei man die Hierarchien schön flach halten sollte und nicht (als Beispiel) 5 Ebenen tief vererben. Komposition sollte man lieber Vererbung vorziehen.

    Wenn Datenknoten und Abschluss von Listenelement erben, wieso haben sie noch eine extra Assoziation zu Datenelement? Das Klassendesign deines Lehrers hat irgendwie viel zu viele Assoziationen, manche doppelt und dreifach.



  • redoundo schrieb:

    Und was würdest du für alternativen vorschlagen? (Für Vererbung, nicht für goto)

    Strukturen oder Klassen ohne Vererbung benutzen und die Vererbung in die Programmlokik einbauen.

    Beispiel von mir:
    Ich mache eine Semantikanalyse für C-Quelltext. Dazu ist es erforderlich eine Symboltabelle mit Symboltabelleneinträge zu haben. Darin stehen Dinge wie Name, Art, Zeile und so weiter. Verschiedene Variablentypen brauchen nun verschiedene Extras. Primitive Datentypen brauchen den Datentyp, Prototypen brauchen den Rückgabewert und eine Symboltabelle mit Parametern, Funktionen brauchen dasselbe wie Prototypen + eine Symboltabelle für lokale Variablen.
    Meine Struktur (eigentlich ist es eine Klasse) sieht nun gekürzt so aus:

    struct Symboltabelleneintrag{
        char *name;
        unsigned int line;
        int type;
        union typeformat;
    };
    
    union typeformat{
        struct funktionstyp *funktion; //wird auch für Prototypen verwendet
        char *primitivetyp;
        struct strukturtyp *struktur;
    };
    

    Ich hoffe mal du siehst die "Vererbung" in der Struktur.

    Die Alternative wäre eine abstrakte Symboltabelleneintrag-Klasse zu bauen und dann Primitivtyp, Structtyp und Prototyptyp davon abzuleiten und Funktionstyp von Prototyp abzuleiten.

    Im Prinzip tut beides dasselbe.
    Ich vergesse allerdings ständig welche Member die Objekte haben. Bei Structs kann ich einfach nachsehen. Bei Klassen nicht. Wenn ich einen struct Symboltabelleneintrag* gegeben habe habe ich alle Informationen über den Eintrag. Wenn ich einen class functiontyp* habe muss ich mir die einzelnen Daten mühsam aus den Klassen zusammensammeln.
    Da ich nicht sonderlich viel RAM im Hirn habe, habe ich nach dem Zusammensammeln der einzelnen Elemente aus den Klassen vergessen was ich eigentlich machen wollte.

    Beispiel von Microsoft:
    Man benutzt die WinAPI um Fenster zu machen. Fenster haben ein paar Eigenschaften wie Titel und den dazugehörigen Message Handler. Man könnte eine allgemeine Fensterklasse bauen und Tooltips, Tabs, Textfenster und so weiter davon ableiten.
    Stattdessen gibt es für die WinAPI Subclassing. Man nimmt zum Beispiel ein Textfeld, findet es ganz nett, will aber zusätzlich auf Rechtsklicks reagieren und ein Menü anzeigen. Also macht man sich ein Standard-Textfeld wo das Tippen, malen der Buchstaben und so weiter vom Defaultmessagehandler übernommen wird und tauscht einfach nur den Messagehandler mit SetWindowLong aus. Dieser neue Messagehandler reagiert nun auf Rechtsklicks und den Rest lässt er den Defaultmessagehandler machen.
    Ich denke mal hier ist klar Vererbung erkennbar. Außerdem ist genau nachvollziehbar was wo passiert.
    Wenn man stattdessen Klassen benutzt (MFC macht das glaube ich), dann sieht man nicht mehr durch, denn um herauszufinden welches Objekt für den Fensterstil zuständig ist muss man viiiiiel Code wälzen. Bei der WinAPI sieht man sich die Doku für SetWindowLong und fertig, da stehen alle Möglichkeiten aufgelistet.
    Sieht man sich hingegen die Dokumentation der Textfensterklasse an steht dort nirgends was vom Messagehandler, sondern nur textfensterspezifische Optionen. Und dann geht die Suche los, die Klasse erbt von sonstwievielen anderen Klassen die man alle durchsuchen darf.

    Einen Teil der Unübersichtlichkeit lässt sich durch semantische IDE's und redundante Dokumentationen umgehen. Das ist aber nicht viel besser als ein Texteditor der bunt anzeigt welches goto zu welchem Label springt. Es hilft, löst aber das Problem nicht.

    Bei Wiki gibts eine nette Liste über Kritik an objektorientierten Sprachen.
    Objektorientiertes Programmieren und Vererbung kann hilfreich sein und man kann es benutzen, auch in C, aber Objektorientierung wo keine Objekte sind und Mehrfachvererbung nur um des Vererbens Willen (siehe erster Post) schadet nur.


Anmelden zum Antworten