Übersichtlichkeit einer Klasse?



  • Hallo Jungs...

    ich habe eine Klasse mit bestimmten eigenschaften... der Code der klasse ist sehr viel... und eine weitere Abstraktion ist nich möglich... Wie geht ihr dann vor? leitet ihr dann die Klasse ab, und erweitert diese?

    class A{
    
      void func1();
    
    };
    
    class B: public A{
    
     void func2();
    
    };
    
    class C: public B{
    
      void func3();
    
    };
    

    wenn ich nun nur C benutze, und A und B gemacht habe, damit C nicht alle func1-3 enthält um Code übersicht zu haben macht ihr sowas? oder ist das schwachsin? Weil wenn ich ne klasse habe mit 1000-1500 Zeilen hab ich immer das gefühl es übersichtlicher lösen zu wollen!



  • Wenns nur der Übersichtlichkeit dient finde ich ist die Idee Unsinn. Wiederspricht ja auch der OOP Idee von Klassenbeziehungen, imo.



  • d.h. du aktzeptiert dann das die klasse soviel code hat?



  • Ich würd mir erstmal Gedanken machen ob die Klasse überhaupt so viel Code haben muss. In der Praxis hatte ich das Problem noch nie.



  • Also ich kenne einen Kollegen, der hat Vererbung gemacht, um sich "Schreibarbeit" zu sparen. Den habe ich erstmal aufgeklärt, das OOD damit nichts zu tun hat. Im Prinzip versuchst du hier etwas ähnliches, Aber OOD hat mit sowas herzlich wenig zu tun. Du mußt deine Klassen so gestalten, das sie fachlich korrekt sein. Wenn eine Klasse 20 Methoden hat... dann ist das erstmal so.

    Man kann sich dann aber natürlich nachträglich Gedanken machen, ob man vielleicht nicht fachlich einen Fehler gemacht hat. Es muß aber nicht zwingend ein Fehler vorliegen, weil die Klasse so groß ist. Man kann nicht pauschal sagen: Eine Klasse ist nur dann korrekt, wenn sie nur max. 3 public und 2 protected Methoden hat. (private Methoden sind eh schnutz, die gehen niemand was an... da kann man auch 50 private Methoden haben, wenn man lustig ist)



  • Jup.
    Bei größeren Projekten ist es eigentlich auch normal, dass man große Klassen mit vielen Zeilen Code hat. Du musst halt immer selbst schauen, ob das was du da hast tatsächlich alles reingehört oder es nicht Dinge gibt, welche man eigentlich in eigene Klassen auslagern kann. Wenn nein, dann ist alles wunderbar.
    Hab auch schon Java-Klassen mit ~10000 Zeilen Code gesehen, wobei das da dann tatsächlich "falsch" war 😉



  • Hallo,
    bei einer sehr umfangreichen Klasse würde ich Schritt für Schritt vorgehen:
    Als erstes, die Klasse von außen betrachten:

    a) Was ist die Aufgabe der Klasse? Kann ich die noch kurz und knapp formulieren, ohne dass ich dauernd "und" benutzen muss. Welche Gründe gibt es, die eine Änderung der Klasse nötig machen würden? Wenn die Klasse mehr als eine Aufgabe hat und damit mehr als ein "Cluster" von Gründen weshalb sie geändert werden müsste, heißt es splitten (und das heißt in den seltesten Fällen Vererbung).

    b) Wie wird die Klasse verwendet? Als Basisklasse? Als konkrete Klasse? Gar beides? Welche Interfaces gibt es neben dem öffentlichen? Wenn man die Interfaces nach Verwendung clustert, wieviele Cluster erhält man? Hat die Klasse mehr als ein Interface (z.B. ein öffentliches und ein protected) -> aufteilen (Base + Derived). Wenn es mehrere Cluster gibt -> splitten (Stichwort: "Interface Segregation")

    Jetzt auch die "innere Werte" der Klasse berücksichtigen:

    Memberfunktionen bezüglich Verwendung der privaten Daten clustern. Gibt es mehrere Cluster bzw. kann ich durch kleine Änderungen mehrere unabhängig Cluster erzeugen? -> splitten.

    Der Nummer 1 Grund für zu große Klassen ist, dass eine Klasse zuviel macht (Stichwort: mangelnde Kohäsion). Die beste Kur dagegen heißt: zerschmettern und durch mehrere (kollaborierende) Klassen ersetzen.



  • Ich hab das auch öfters, kapsele dann (fast immer) nochmal die Daten der Klasse in einzelne Klassen.
    Ein Beispiel, kein Paradebeispiel aber das Prinzip sollte klar werden:
    Angenommen, du hast eine Klasse, die Multithreading-fähig sein soll und sie benutzt einen oder mehrere Semaphoren. Wenn du mit der WinAPI arbeitest, musst du den Semaphor erstellen, jedesmal locken und unlocken und am Schluss zerstören. Anstatt die Semaphor-Aufrufe im Code zu haben, bastelt man sich eine Klasse "Semaphore", die das Objekt automatisch erstellt und löscht. Dazu noch eine Klasse "SemaphoreLocker", die beim Konstruktor-Aufruf den übergebenen Semaphor lockt und ihn beim Destruktor unlockt.
    Etwa so:

    MeineKlasse::MeineKlasse() {
        // nix :)
    }
    
    MeineKlasse::~MeineKlasse() {
        // Auch nix...
    }
    
    void MeineKlasse::DoSomething() {
        SemaphoreLocker locker( sem );
        // ....
    }
    

    statt

    MeineKlasse::MeineKlasse() {
        sem = CreateSemaphore( ... );
    }
    
    void MeineKlasse::DoSomething() {
        LockSemaphore( sem );
        // ....
        UnlockSemaphore( sem );
    }
    
    MeineKlasse::~MeineKlasse() {
        DestroySemaphore( sem );
    }
    

    Das sieht erstmal wenig aus, aber bei vielen solchen Objekten spart das dann doch eine _Menge_ an Code, der sich dann nur noch auf die Kern-Funktionalität beschränkt.



  • BorisDieKlinge schrieb:

    ... und eine weitere Abstraktion ist nich möglich...

    Das halte ich für ein Gerücht!
    Poste mal den Code 🙂


Anmelden zum Antworten