OOP - Endloses gewrape und endlose Verschachtlung von Kalssen



  • Programme mit einer Java-typischen Struktur, also alles ueber Vererbung zu loesen, finde ich meistens sehr unuebersichtlich.
    Wenn man zwischen den Aufgabengebieten sinnvoll unterscheidet, kann das aber sehr zur uebersichtlichkeit beitragen.



  • Der Grund aus dem ich das original ins C++ Forum geschrieben hatte war der, dass C++ ja, was den Programmierstil angeht, mehrere Optionen gibt.
    Daher dachte ich, dass man gegenüber von zB Java, das ja rein OOP ist, vielleicht durch Einsetzen mehrer Stils eventuell schönere Ergebnisse erzielt.

    Aber ich hatte mir schon fast gedacht, dass es nun mal nicht besser geht und es einfach Notwendigkeit ist.

    Danke an Euch 🙂



  • DasIstÄtzend schrieb:

    Meine Frage: Ist das denn normal und einfach durch den großen Umfang von Quellcode zwingend gegeben?

    Nein, das ist nicht zwangsweise normal. Es kommt auf den Programmierstil in der jeweiligen Firma an. Es gibt viele Entwickler die OOP mit einer tiefen Klassenhierarchie gleichsetzen, wie es beispielsweise auch in Java üblich ist. Aber dies ist nicht zwangsweise nötig oder sinnvoll. Ich persönlich versuche die Tiefe der Hierarchie möglichst gering zu halten (In der Regel hat eine Klassenhierarchie bei mir maximal 2-3 Ebenen*), und versuche auch abzuwägen ob Vererbung immer das sinnvolle ist.

    * Reine Interfacevererbung berücksichtige ich dabei aber nicht zwangsweise.

    Wir haben in unseren Projekt aber auch an 2 Stellen extrem Tiefe Hierarchien, das sind die 2 Programmteile bei denen die wenigsten durchblicken und Änderungen am längsten dauern. Ich habe dies zumindest an der ein oder anderen Stelle inzwischen auf 2 getrennte Bäume auftrennen können, dennoch ist der Code noch immer ein monolithischer Moloch.

    Nach meiner eigenen Erfahrung erscheint einem eine tiefe Klassenhierachie anfangs einfacher (zumindest ist dies mein Eindruck bei einigen Entwicklern), doch umso tiefer umso schwerer wartbar wird das Ganze, und umso größer sind die Abhängigkeiten. Lieber mehrere flache Hierarchien die beispielsweise mittels Strategiemuster kombiniert werden, als eine Tiefe.

    DasIstÄtzend schrieb:

    ...von einer professionallen Firma entwickelt.

    Was ist bitte eine "professionelle" Firma? Machst du das an der Firma, den Entwicklungskosten oder was bitte fest?

    DasIstÄtzend schrieb:

    Man ist zB in der Klasse XY und man sieht, dass dort die Methode doSomething() einer includeten Klasse aufgerufen wird.

    Das als solches ist noch nichts ungewöhnliches... doch sollte sich dies in überschaubaren Grenzen halten.

    DasIstÄtzend schrieb:

    Nicht unoft ist man 6 Implementierungen tief gewrapt ...

    Und das halte ich für eindeutig zu extrem.



  • Das ist die moderne Interpretation von "Spaghetti-Code". Nicht schön, aber leider üblich.



  • Wo lest ihr heraus dass es tiefe Vererbungshierarchien gibt?



  • hustbaer schrieb:

    Wo lest ihr heraus dass es tiefe Vererbungshierarchien gibt?

    Gut, beim zweiten Lesen ist das tatsächlich nicht ganz deutlich ob es sich um das weitergeben von Methoden außerhalb oder innerhalb einer Hierarchie handelt. Das tief in "...6 Implementierungen tief..." ebenso wie die "Verschachtelungen" hatte ich so interpretiert.



  • Ich bin nicht zwangsläufig von Vererbungshierachien ausgegangen, ich hatte mehr an 6-fach verschachtelte Wrapperfunktionen gedacht. Klar, das kann man mit Vererbung kombinieren 😉



  • Ich hab auch nicht dich, Mr X, gemeint, sondern die beiden die explizit etwas von Vererbung geschrieben haben. Also asc und Marthog.

    @asc
    Ich finde tiefe Vererbungshierarchien anscheinend so grausam, dass ich nichtmal an die Möglichkeit gedacht habe dass das gemeint sein könnte. Wobei es mir auch bei nochmaligem Lesen nicht so vorkommt als wäre das gemeint. Ich kann nur hoffen es ist nicht gemeint. 🙂



  • das ist mir aber auch schon aufgefallen, dass viele programmierer gerne wrapper schreiben, sogar für klassen die in der selben firma entwickelt wurden.



  • reisaboutaface schrieb:

    das ist mir aber auch schon aufgefallen, dass viele programmierer gerne wrapper schreiben, sogar für klassen die in der selben firma entwickelt wurden.

    Ist aber auch oft schöner als eine Klasse mit Millionen von Funktionen zu zuballern.

    Wir haben bei uns ind er Firma eine Reihe Klassen (unsere grundlegenden Masterdaten), die halten einfach nur einige Attribute wie Name, Firmenname, Anschrift und soweiter. Sagen wir je nachdem zwischen 5 und 20 Attributen. Dazu dann Getter und Setter und ein paar kleine Methoden, um einige Daten zu interpretieren (z.B. exisitert eine Firma an der Anschrift überhaupt doer sowas). Selbst mit viel wohlwollen keine 200 Zeilen.

    Trotzdem ist jede dieser Klassen um die 1500-2000 Zeilen lang, weil die gesamte Datenbankfunktionalität da noch reingebaut ist, jede einzelne Abfrage in eienr eigenen Methode, selbst gleiche oder ähnliche Abfragen, die sich nur in einem Punkt unterscheiden sind komplett neue Methoden mit Kopierpasta erzeugt.

    Da kann man einiges schön rauswrappen.



  • Skym0sh0 schrieb:

    reisaboutaface schrieb:

    das ist mir aber auch schon aufgefallen, dass viele programmierer gerne wrapper schreiben, sogar für klassen die in der selben firma entwickelt wurden.

    Ist aber auch oft schöner als eine Klasse mit Millionen von Funktionen zu zuballern.

    Ich sehe keinen zusammenhang.



  • Hm.

    Grundsätzlich steckt ja schon eine saubere Überlegung hinter dem Code. Ich hab halt nur überlegt, ob man das Ganze nicht villeicht doch übertrieben hat.

    DAOs, DTOs, Services (jeweils abstracte Überklasse und dann Implementierungen), Facades, Converter und meistens halt noch nen Controller.

    Die wrapen dann öfters um andere Klassen, die die gesuchte Funktionalität schon implementiert haben (in gleichem Aufbau an Klassen) und so ergibt sich dann ein komplexer Mix aus verschiedensten Klassen.

    Ist schon manchmal etwas verwirrend und anstrengend, aber ich denke es wird seinen Sinn haben 🙂



  • Naja, wenn du dir natürlich ALLES anschaust, was irgendwie damit was zu tun hat, wirst du ausflippen. Aber das ist ja nicht der Sinn hinter z.B. einer Facade. Ganz im Gegenteil: damit soll es eine Abgrenzung geben, womit sich jemand nur beschäftigen soll. Und dann sieht die Welt schon wieder viel übersichtlicher aus.

    Und wer hinter der Facade arbeitet, schaut sich auch nicht den Code vor der Facade an.

    Das ist ja gerade der Sinn von Blackboxes, Interfaces, Abstraktion usw.

    Was meinst du was z.B. alles Windows API für Abstraktionen hat, wo du nie dahinter schauen kannst und auch nicht WILLST, um z.B. eine Windows Anwendung zu entwickeln. Irgendwo muss man auch für sich selber eine Grenze ziehen.



  • DasIstÄtzend schrieb:

    Meine Frage: Ist das denn normal und einfach durch den großen Umfang von Quellcode zwingend gegeben?
    Ich will hier die Firma nicht schlecht machen, die das geschrieben haben. Die haben alle tausend mal mehr Ahnung als ich.

    Lustig, was hier diskutiert wird, obwohl die Fragestellung so eigentlich nicht zu beantworten ist.

    Ich habe schon komplexe Software gesehen, die allein auf Grund der Aufgabenstellung so kompliziert war, wie das hier beschrieben wird - die hätte sich zwar im Detail verbessern und optimieren lassen, aber nicht grundsätzlich verändern.

    Und ich habe schon vergleichsweise triviale Konstrukte gesehen, die waren genau so verschachtelt. OK, DASS die Software so trivial war, hat man nicht auf Anhieb erkennen können, da der Code so dermaßen vermurkst war. Absolutes Highlight: eine Implementierung einer Funktion, die Daten von einer RS232-Schnittstelle liest und interpretiert. Die war so dermaßen verkompliziert und verschachtelt, dass schon beim lesen von mehr als 500 Bytes der komplette Rechner gestanden hat. Und der Code kam auch von einer "Profi"firma.

    Fazit: die ursprüngliche Frage lässt keine pauschale Antwort zu, was hier im Thread gemacht wird ist reine Protzerei und Kaffeesatzleserei.



  • DasIstÄtzend schrieb:

    Grundsätzlich steckt ja schon eine saubere Überlegung hinter dem Code. Ich hab halt nur überlegt, ob man das Ganze nicht villeicht doch übertrieben hat.

    DAOs, DTOs, Services (jeweils abstracte Überklasse und dann Implementierungen), Facades, Converter und meistens halt noch nen Controller.

    Okay, scheinbar vollständig missverstanden. Diese Form der Trennung kann durchaus Sinn ergeben bei großen Projekten (Thema Schichtentrennung...). Und ja, da hat man durchaus mehrere Fälle wo die Behandlung durch gereicht wird.

    Nehmen wir einmal folgendes an: Du möchtest die Abhängigkeit von bestimmten Technologien verringern und Austauschbar halten. Gleichzeitig sollen viele verschiedene Geräteklassen unterstützt werden, wobei möglichst viel Code gemeinsam genutzt werden soll.

    Am Beispiel .Net: Gehen wir einmal davon aus das du die 3 großen Mobilplattformen, den Windows-Desktop sowie Web unterstützten willst. Die UI ist bei jeder Plattform weitgehend unterschiedlich:

    Windows Desktop: z.B. WPF [MVVM-Pattern, hier View]
    Mobilplattformen: z.B. Xamarin.Forms [MVVM-Pattern, hier View]
    Web: ASP.Net

    Nun kann man zwischen Windows Desktop und den Mobilplattformen durchaus Code teilen (MVVM-Pattern: z.B. das ViewModel), ASP.Net läuft seperat.

    Alle 3 Varianten greifen weiter unten Auf einen Service (WebAPI oder WCF) zu.

    Auf den Server läuft dann zudem die Businesslogik (weitere Schicht) und Datenzugriffsschicht. Alleine wenn man bedenkt wie häufig MS die Datenzugriffstechniken geändert hat, oder man vielleicht mehrere Datenbanken unterstützten will, ist auch diese Trennung gerechtfertigt.

    In diesen Fall komme ich auf bis zu 5 Schichten: User Interface (XAML...), Präsentationsschicht (ViewModels...), Serviceschicht, Businesslogik und Datenzugriffsschicht.

    Dieser Aufwand der Trennung ist dann gerechtfertigt wenn das Projekt lang gewartet und weiter entwickelt werden soll, sowie einen größeren Umfang hat. Nachträglich kann man solche Schichtentrennung nur mit sehr viel Mühe umsetzen.



  • Ich bin Ex-ITler und habe dieses OOP auch gehasst wie die Pest. Sich da durch den Code zu fummeln ist echt das Letzte. Es ist eben in der Praxis selten alles gut dokumentiert und oft haben da schon viele Köche in den Brei gespuckt, bevor man selbst mal ran muss. Klar gibt es immer die Ausnahmefirmen in denen alles ordentlich läuft, die habe ich aber nie wirklich kennen gelernt.

    So sinnvoll OOP oft sein mag. Ich habe es in der Praxis gehasst.



  • H4ck3r schrieb:

    Ich bin Ex-ITler und habe dieses OOP auch gehasst wie die Pest. Sich da durch den Code zu fummeln ist echt das Letzte.

    Lag das wirklich an OOP, oder an den Programmierern? Ich könnte per se genau das Gegenteil von nicht-OOP bei großen Projekten behaupten, oder bei nicht verstandenen OOP (C mit Klassen).

    H4ck3r schrieb:

    Es ist eben in der Praxis selten alles gut dokumentiert und oft haben da schon viele Köche in den Brei gespuckt, bevor man selbst mal ran muss.

    1. Gute Dokumentation habe ich bis heute noch in KEINEM Projekt erlebt. Entweder einer verlangt es für jeden Codeschnipsel, obwohl es in einer C++ Referenz gut erklärt wird, oder es ist so stark veraltet das es nichts bringt (wenn nicht gar nicht existent).

    2. Code kann dennoch lesbar oder gut strukturiert sein (Egal ob OOP oder nicht, egal ob mit Schichtentrennung oder nicht). Normalerweise sollte einem bei OOP sogar der konkrete Code hinter einer Implementierung solange egal sein, wie man nicht genau an dieser Implementierung etwas ändern muss. Dafür sind Schnittstellen doch gerade dar.

    H4ck3r schrieb:

    So sinnvoll OOP oft sein mag. Ich habe es in der Praxis gehasst.

    Ich habe bislang jedenfalls noch keine bessere Alternative erlebt (Und ich habe nicht mit OOP angefangen).



  • Es gibt da meiner Meinung nach einige fundamentale Missverständnisse was die objektorientierte Programmierung angeht.

    Auch in der heutigen Zeit fängt man meistens an mit rein imperativer Programmierung. Wenn man mit Java anfängt hat man da zwar Objekte, aber man setzt nicht um was der Grundgedanke von OOP ist. Man programmiert immer noch nach dem imperativen Ansatz. Eigentlich sollte man zum Einstieg in die Programmierung erstmal ein paar Wochen Problemstellungen nur auf dem Papier mit Objekten modellieren. Dann würde OOP den Leuten so viel leichter fallen. Und die meisten Leute die meinen sie hätten OOP verstanden haben es doch nicht.

    Jetzt geht man also an ein Stück Software-Code ran und möchte diesen verstehen. Aber nirgendwo passiert etwas. Man geht von Objekt zu Objekt, alle deligieren irgendwas oder erstellen neue Objekte, aber vom rein imperativen Ansatz her geschieht einfach nichts. Und das ist der Denkfehler. Es geschieht sehr wohl etwas. Aber nicht nach dem imperativen Ansatz. Das ist Objektorientierung. Man darf den Code nicht nach dem imperativen Ansatz her lesen (immer in jede tiefer verschachtelte Funktion reinspringen ...) sondern muss verstehen was die Objekte grundsätzlich an Funktionalität bereitstellen. Das kann zunächst über eine sinnvolle Benamsung (auch das können nur wenige Programmierer wirklich gut) erkenntlich gemacht werden.

    Wenn man von einer Software nur die Klassennamen durchließt sollte man schon eine Ahnung haben was die Software tut (ohne sie vorher zu kennen). Ansonsten ist dein Projekt Dreck. Datenmodell scheiße -> OOP scheiße -> Software scheiße.

    Und das ist auch das Problem des Autors dieses Threads. Du hast den OOP Ansatz (wie so viele andere) noch nicht voll begriffen. Aber wenn man noch ein bisschen übt wird das schon. Da kann ich nur empfehlen viel zu lesen und sich z.B. mal mit der Clean Code Developer "Bewegung" auseinanderzusetzen.


Anmelden zum Antworten