Laden...

Sind eigene Listenklassen zur Verwaltung von Objekten sinnvoll?

Erstellt von wickedcsharper vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.590 Views
wickedcsharper Themenstarter:in
160 Beiträge seit 2008
vor 13 Jahren
Sind eigene Listenklassen zur Verwaltung von Objekten sinnvoll?

Hallo zusammen,

in unserem Projekt habe ich ein Modul bzw. eine Sammlung von Klassen zur Deckungsbeitragsrechnung und Kosten/Erlösberechnung programmiert.

Dabei habe ich eine Klasse Mitarbeiter und eine Klasse Mitarbeiterliste zur Verwaltung der Mitarbeiterobjekte sowie eine Klasse Kosten und Kostenliste zur Verwaltung von Kostenobjekten.

Mein Vorgesetzter Projektleiter sagte, dass sei nich "objektorientiert" und es sei besser, die Verwaltung der Objekte in einer Hashliste oder Dictonary zu führen, die sich in der Klasse Mitarbeiter bzw. Kosten befinden. Meine Listklassen seien nur "Hilfsklassen" die den Code undurchsichtig machen.

Nun hatte ich das entsprechende Beispiel sogar aus einem Lehrbuch und war recht erstaunt über diese Aussage.

Meine Frage ist: Hat er eventuell Recht, oder gibt es tiefgründige Argumente für Klassen, die Objekte anderer Klassen verwalten ?

Gruß

„Wenn man eine Katze auseinandernehmen will, um zu sehen, wie sie funktioniert, hat man als erstes eine nicht funktionierende Katze in den Händen.“

3.430 Beiträge seit 2007
vor 13 Jahren

Hallo wickedcsharper,

in solchen Fällen sind Dictionaries immer sehr nett.
Denn du hast in dem Beispiel eine Abhängigkeit zwischen dem Mitarbeiterobjekt und einem Kostenobjekt (1:1)

Wenn deine Listeklasse nicht viel macht ausser die Zugehörigkeit zu definieren / erkennen dann ist diese relativ sinnfrei und somit wäre ein Dictionary vorzuziehen.

Wenn diese jedoch alle möglichen Berechnungen per se macht dann kann man darüber schon nachdenken.

Gruss
Michael

6.862 Beiträge seit 2003
vor 13 Jahren

Hallo,

also wenn die Listenklassen nichts anderes machen als die Menge der Objekte zu halten, dann sind sie in der Tat überflüssig und man kann gleich den passenden Collectiontypen ausm Framework nehmen.

Aber ich denke nicht zwangsweise das diese Listen dann in die entsprechende Klasse gehören. Nen Mitarbeiter muss nicht die anderen Mitarbeiter verwalten. Die Listen sollten lieber an die Stelle wo sie gebraucht werden im Code.

Bissle anders sieht es wieder aus wenn man nen Konzept hat in dem man irgend ne zentrale Mitarbeiterverwaltungsklasse hat die aus vielen Stellen im Code benutzt wird. Dann bieten sich eher eigene Klassen an die man statisch machen kann um nicht unnötig komplizierten Code schreiben zu müssen wo man unnötig Parameterobjekte hin und her übergeben muss um überall Zugriff auf die Listen zu erhalten.

Baka wa shinanakya naoranai.

Mein XING Profil.

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

wenn die Implementierung von List<T>, Dictionary<K,V>, etc. ausreicht können diese durchaus verwendet werden. Hier ist ein Wrapper um diese oder eine Eigenimplemntierung nicht sinnvoll.

Sind die Forderungen jedoch verschieden zur Implementierung der Standardklassen dann muss selbst eine gemacht werden. Dabei aber nicht unbedingt von zB List<T> ableiten, sondern eine Kompositon machen, d.h. die List<T> als privaten Member in der eigenen Klasse haben.

oder gibt es tiefgründige Argumente für Klassen, die Objekte anderer Klassen verwalten ?

Ein Repository wäre so ein Beispiel für deine Vorgehensweise.

die Verwaltung der Objekte in einer Hashliste oder Dictonary zu führen, die sich in der Klasse Mitarbeiter bzw. Kosten befinden.

Wie ist das genau gemeint? In der Klasse Mitarbeiter eine List<Mitarbeiter> macht nur dann Sinn wenn zB die Hierarchie Vorgesetzter -> Arbeiter abgebildet werden soll. In der Klasse Mitarbeiter eine List<Projekte> macht schon Sinn.

Um das aber genauer beurteilen zu können müsste mehr von deiner Architektur bekannt sein.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

wickedcsharper Themenstarter:in
160 Beiträge seit 2008
vor 13 Jahren

Hallo zusammen,

Die Klasse Mitarbeiter behinhaltet Mitarbeiter, Angestellte, Vorgestzte, Chefs , Putze, Hilfskraft, Azubi etc.

Die verschiedenen Mitarbeiterobjekte haben Löhne, Gehälter, Urlaubstage usw.

Nun ist denkbar die Mitarbeiter in einer Liste, Dictonary, Hashliste oder einer sonstigen Collection innerhalb der Klasse zu speichern.

Funktionen zum Erechnen des Lohns oder zum Sortieren der Mitarbeiter, sprich die Bearbeitung und Pflege der Objekte müsste dann über Klassenmethoden der Klasse Mitarbeiter erfolgen.

Meine Idee war die Objektverwaltung in eine Hilfsklasse Mitarbeiterliste zu packen und über Indexer auf die Mitarbeiter zuzugreifen.Die Hilfsklasse lädt anfangs die Mitarbeiterdaten in die Liste<T> genauer list<Mitarbeiter> und implementiert auch hier Methoden zur Sortierung der Mitarbeiter und eventuelle Berechnungsmethoden.

Man entkoppelt nun Methoden, die alle Mitarbeiter betreffen (wie z.b: berechne Lohn aller Mitarbeiter) von denen, die nur einzelne Mitarbeiter betreffen.

Aber man kann sowas natürlich auch innerhalb der Klasse Mitarbeiter direkt machen.

Beides geht. Nur was ist aus OOP Sicht die bessere Alternative?

„Wenn man eine Katze auseinandernehmen will, um zu sehen, wie sie funktioniert, hat man als erstes eine nicht funktionierende Katze in den Händen.“

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

Die Klasse Mitarbeiter behinhaltet Mitarbeiter, Angestellte, Vorgestzte, Chefs , Putze, Hilfskraft, Azubi etc.

Es gibt wohl hoffentlich eine Basisklasse Mitarbeiter von der die anderen erben? Wenn nicht lerne die OO-Grundlagen. Diese stehen in zB 🛈

Meine Idee war die Objektverwaltung in eine Hilfsklasse Mitarbeiterliste zu packen und über Indexer auf die Mitarbeiter zuzugreifen.

Warum eine Hilfsklasse? Erstell eine Klasse Personal (oder ähnlich) welche die Mitarbeiter hält, aber keine Hilfsklasse denn diese Klasse ist ja mehr oder weniger das Herz deiner Anwendung. Wennschon eine Masterklasse 😉

Wenn ich das so lese habe ich das Gefühl dass einfach die Grundlagen in OOP fehlen. Die Aufgabe die du hast ist eigentlich Standard und findet sich exakt so irgendwo in den OOP-Grundlagenbeispielen (hab gerade keine Link parat, aber das wirst du schon finden). Lies dir auch Objektorientierte Programmierung durch. Und v.a. Vererbung!

Edit: Oben erwähnter Link wäre zB Dependency injection and service locator Dort wird ein ähnliches Beispiel gezeigt.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

wickedcsharper Themenstarter:in
160 Beiträge seit 2008
vor 13 Jahren

Hallo gfoidl,

danke für deine Antwort. Ich denke wir reden etwas aneinander vorbei.
Im Übrigen bist du auch schnell mit der Bemerkung dabei dass man die OOP nicht beherrscht ...

Aber dennoch nochmal mein Anliegen: Es geht hier nicht darum Basisklassen für Mitarbeiter zu entwerfen, weil wir Mitarbeiter verschiedener Typen haben (Putze, Angestelletr, Chef). Die Daten sind alle gleich (Lohn, Gehalt, Urlaub...)

Daher reicht die Klasse Mitarbeiter. Vererben brauchen wir hier nix.

Es geht um die Verwaltung selbiger in einer klasseninternen Struktur bzw. Collection oder alternativ in einer Listenklasse. Wie ich oben beschrieb, war die Intention
verschiedene Methoden aus der Klasse Mitarbeiter zu entkoppeln, da sie alle Mitarbeiterobjekte betreffen. z.B. Ich will die gesamten Lohnkosten aller Mitarbeiter berechnen und an eine GUI weitergeben.

Nun kann ich die Berechnungsmethode so gestalten, dass ich sie direkt in die Klasse Mitarbeiter verfrachte oder aber - eben weil sie ja alle Mitarbeiter durchläuft in die Hilfsklasse Mitarbeiterliste.

Ich hatte das Beispiel glaube ich aus irgendeinem OOP Buch oder OpenBook und fand es ganz gut. Angenommen du hast 10 Methoden, die nur einen Mitarbeiter betreffen (wie z.B. getName) und 10 Methoden wie sortMitarbeiter, getGesamtlohnkosten etc.

Ist es da nicht sinnvoll solche wie die letztgenannten in die Klasse Mitarbeiterliste zu packen? Aber vielleicht irre ich ja auch und liege völlig daneben....

„Wenn man eine Katze auseinandernehmen will, um zu sehen, wie sie funktioniert, hat man als erstes eine nicht funktionierende Katze in den Händen.“

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

Ich denke wir reden etwas aneinander vorbei.

Du zumindest nicht an mir 😉

Im Übrigen bist du auch schnell mit der Bemerkung dabei dass man die OOP nicht beherrscht ...

Wenn ich deine Posts lese dann hab ich einfach das Gefühl. Das zeigt auch obiger Post. Es ist aber keinesfalls böse gemeint.

weil wir Mitarbeiter verschiedener Typen haben

Es steht da verschiedener Typen. Wenn ein Typ nunmal eine Klasse ist dann sinds auch verschiedene Klassen. Die Modellierung richtet sich ja geradezu nach der natürlichen Sprache.

Putze, Angestelletr, Chef). Die Daten sind alle gleich (Lohn, Gehalt, Urlaub...)

Wenn alle Daten gleich sind dann hats du Putze gut und der Chef schneidet schlecht ab 😄. Ich bezweifle auch dass dieses Modell sehr an die Realität angelehnt ist. Was ist zB mit Bonuszahlungen? Eine Putze wird davon wohl nix bekommen. Der Chef schon eher. Es sind eben verschiedene Typen von Mitarbeitern -> Modellierung -> Basisklasse Mitarbeiter und Klassen für Chef, Angestellter, Putze, etc. die alle von Mitarbeiter erben. Die natürliche Sprache gibt das ja schon vor.

klasseninternen Struktur bzw. Collection oder alternativ in einer Listenklasse.

Ziemliches Begriffswirrwarr 😉 Was ist für dich eine Listenklasse? Eine List<T>? Warum erwähnst du 3 Möglichkeiten wenn weiter oben schon genug darüber gesagt wurde?

verschiedene Methoden aus der Klasse Mitarbeiter zu entkoppeln, da sie alle Mitarbeiterobjekte betreffen

Wozu das entkoppeln? Diese Methoden müssen mit dem Daten des Mitarbeiter-Objekts arbeiten. Da wäre es sinnvoller die Methoden in der Mitarbeiter-Klasse zu deklarieren. Diese Methoden gehören ja zum Mitarbeiter sowie die Daten. Kapselung - eines der OO-Prinzipien - besagt dass privates von außen verborgen werden soll. Warum also die Kapselung aufbrechen? Nur dass Methoden von andren Klassen darafu zugreifen können?

Ich will die gesamten Lohnkosten aller Mitarbeiter berechnen und an eine GUI weitergeben.

Die Basisklasse Mitarbeiter hat zB eine Methode CalculateCost() und die anderen Klassen welche von der Basisklasse erben können diese Methode ggf. überschreiben. Die Berechnung der Gesamtlohnkosten ist dann einfach eine foreach-Schleife über alle Mitarbeiten wo die CalculateCost-Methode aufgerufen wird und entsprechend aufsummiert wird. Das findet alles in den Modell-Klassen statt. Wie vorhin erwähnt gibts zB eine Klasse Personal welche die Methode CalculateOverallCost hat und in dieser ist auch die foreach-Schleife für die Berechnung.

Für die Anezige in der UI ist dann der Presenter/ViewModel verantwortlich indem er eien Eigenschaft bietet welche in der UI gebunden wird.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

wickedcsharper Themenstarter:in
160 Beiträge seit 2008
vor 13 Jahren

Danke dir,

ich entnehme deinen Ausführungen, dass man auf Listenklassen verzichten kann
und die Liste der erzeugten Objekte in der Klasse selber führt.

Ich habe gedacht eine separate Klasse zur Führung der Objekte hätte Vorteile,
aber offensichtlich nicht...

danke für die Ausführungen

„Wenn man eine Katze auseinandernehmen will, um zu sehen, wie sie funktioniert, hat man als erstes eine nicht funktionierende Katze in den Händen.“

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

die Liste der erzeugten Objekte in der Klasse selber führt.

Versteh nich was du damit meinst. Welche Objekte und welche Klasse meinst du?

In den letzten beiden Antworten steht anders.


class Personal
{
    List<Mitarbeiter> Mitarbeiter {...}

    double CalculateOverallCost()
    {
        // mit LINQ, sonst foreach-Schleife
        return this.Mitarbeiter.Sum(m => m.CalculateCost());
    }
}

class Mitarbeiter
{
    virtual double CalculateCost() {...}
}

class Chef : Mitarbeiter
{
    override double CalculateCost() {...}
}

// usw.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

wickedcsharper Themenstarter:in
160 Beiträge seit 2008
vor 13 Jahren

Hallo nochmals,

separate Listenklassen sollten durchaus Sinn machen, wenn sie etwas mehr machen als nur die Liste der Objekte selbst zu halten.

Folgendes macht Sinn:


public class Personen:...
{
.
.
}

public class Personenliste:CollectionBase
{

public BindingList<Person> persList = new BindingList<Person>();

      //Indexer gibt Typ Person zurück und fügt der Liste eine neue Person hinzu
      public Person this[int index]
      {
         get
         { 
            if(index >= 0)
               return persList[index];
            else return null;               
         }
         set
         {
            //Prüfen, ob schon vorhanden
           
           persList.Add(value);
         }

      }

Add()
Remove()
Sort()
ToArray()

}

Hier werden in der Tat Funktionen zur Verwaltung von Objekten "gekapselt".

Ich hatte das aus einem Lehrbuch

Visual C# 2010: Grundlagen, Programmiertechniken, Datenbanken

und fand die grundlegende Idee nicht schlecht, da so die Klasse Person um einige Funktionen erleichtert wird, was dem prinzip der Verteilung nach Zuständigkeiten - SOC ja eigentlich entgegenkommt ?

„Wenn man eine Katze auseinandernehmen will, um zu sehen, wie sie funktioniert, hat man als erstes eine nicht funktionierende Katze in den Händen.“

0
767 Beiträge seit 2005
vor 13 Jahren

Die Klasse Mitarbeiter behinhaltet Mitarbeiter, Angestellte, Vorgestzte, Chefs , Putze, Hilfskraft, Azubi etc.
Es gibt wohl hoffentlich eine Basisklasse Mitarbeiter von der die anderen erben?

Sieht für mich eher so aus, als wäre gemeint, dass die Benutzer die Mitarbeitertypen anlegen und einem Mitarbeiter dann einen Typ zuweisen. Daher ist zur Compilezeit nicht bekannt welche Typen es gibt...

Was ich sagen will, unter dem Begriff "Typ" muss man nicht gleich System.Type verstehen.

Aber vielleicht ist auch beides möglich:


class Mitarbeiter {}
class Chef : Mitarbeiter {}
class Putze : Mitarbeiter {}
// und
class UserdefinedType : Mitarbeiter {}

loop:
btst #6,$bfe001
bne.s loop
rts

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo wickedcsharper,

separate Listenklassen sollten durchaus Sinn machen, wenn sie etwas mehr machen als nur die Liste der Objekte selbst zu halten.

In System.Collection.Generic kann jede Klasse mehr als nur die Objekte zu halten. Das was dein Beispiel zeigt kann genauso gut mit List<T> erreicht werden. Warum das selbst machen?

Im get des Indexer würde ich nicht null zurückgeben wenn der Index negativ ist sondern eine IndexOutOfRangeException werfen.

Das Feld persList sollte auch nicht öffentlich zugreifbar sein. Dafür gibts Eigenschaften - und hier sollte die Eigenschaft nur eine read-only Liste zurückgeben, da für das Hinzufügen, Entfernen, etc. eigene Methoden vorhanden sind => Kapselung.

Hallo 0815Coder,

Sieht für mich eher so aus, als wäre gemeint, dass die Benutzer die Mitarbeitertypen anlegen und einem Mitarbeiter dann einen Typ zuweisen. Daher ist zur Compilezeit nicht bekannt welche Typen es gibt...

Das sollte aber schon bekannt sein da zu den entsprechenden Mitarbeitertypen auch eine jeweils angepasste Logik vorhanden sein müsste (Lohn, Urlaub, Boni, etc.) und eine unüberschaubare Art von Mitarbeitern gibts ja nicht.
Einer (späteren) Erweiterung steht ja nichts im Wege. Das könnte auch über Plug-Ins erfolgen 😉

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

0
767 Beiträge seit 2005
vor 13 Jahren

Ok, jetzt hol ich vielleicht ein bisschen weit aus, vielleicht auch aus der Luft gegriffen.

Angenommen es gibt verschiedene Logiken für Lohn, Urlaub, Boni, Arbeitszeit, etc. Eine bestimmte Kombination dieser macht einen Mitarbeitertyp aus. Die Benutzer können neue Kombinationen anlegen und dadurch neue Mitarbeitertypen erstellen. Für den Mitarbeitertyp selber brauchts dann keine eigene Logik

Per Addons können weitere Logiken für Lohn, Urlaub, Boni, Arbeitszeit, etc. erstellt werden.

loop:
btst #6,$bfe001
bne.s loop
rts