Laden...

Wie baue ich eine Klasse auf, deren Felder noch nicht 100% sicher sind?

Erstellt von BeZi vor 7 Jahren Letzter Beitrag vor 7 Jahren 1.706 Views
B
BeZi Themenstarter:in
153 Beiträge seit 2007
vor 7 Jahren
Wie baue ich eine Klasse auf, deren Felder noch nicht 100% sicher sind?

Guten morgen,

ich habe eine Frage zu einem Aufbau einer Klasse deren Felder noch nicht 100% sicher ist.

Wenn ich ja eine Klasse "Mitarbeiter" erstellen würde würde diese ja vielleicht so aussehen:



class Mitarbeiter
{
   private string _vorname;
    private string _nachname;
    private int _alter;
    private Abteilug _abteilung;
    // etc...

    public Mitarbeiter(string Vorname, string Nachname, int Alter, Abteilung Abteilung)
    {
        _vorname = Vorname;
        _nachName = Nachname
        // etc... wird ja jedem klar sein
    }

    // Methoden.....
}


Das ganze könnte ich dann in einer Datenbank (Tabelle Mitarbeiter) speicherm mit den jeweiligen Feldern..... (ID, Vorname, Nachname,.... )

So jetzt zu meiner Eigentlichen Frage:

Was ist wenn ich eine Klasse erzeugen will von der noch nicht bekannt ist was für einen Inhalt/ Eigenschaften hat.
Der Inhalt der Klasse Eigenschaft kommt teils aus einer Datenbank. Was vielleicht auch noch erwähnenswert wäre.... Von der Klasse Dinge wird es später über 50.000 Objekte geben....



class Eigenschaft
{
    private object _Eigenschaft = new object();

    public Eigenschaft()
    {

    }

    // Methoden.....
}

class Ding
{
    private List<Eigenschaft> EigenschaftenListe = new List<Eigenschaft>();

    public Ding()
    {

    }

    // Methoden.....
}


Erstelle ich dann solch ein Konstrukt ? Ist das kompletter Mist oder wie würdet ihr vorgehen.

Bin für alle Ideen offen..

Vielen Dank

C
2.121 Beiträge seit 2010
vor 7 Jahren

Viel anderes wird dir gar nicht übrig bleiben als die Eigenschaften dynamisch zu halten.
Ob du eine Liste mit eigenen Objekten brauchst oder die Eigenschaften in einem Dictionary<string, string> hältst oder was auch immer, hängt vom genauen Aufbau der Eigenschaften ab.
Mach das so unkompliziert wie möglich, aber so erweiterbar wie evtl. nötig.

Ich würde vielmehr überlegen ob du tatsächlich 50.000 Objekte gleichzeitig benötigst. Massenverarbeitung von Daten kannst du evtl. direkt in der Datenbank ausführen, ohne alles extra in Objekte laden zu müssen.
Möglicherweise ist es sinnvoller immer nur die paar wenigen Objekte zu laden die du für die aktuelle Aktion gerade brauchst.
Und der User wird sowieso nicht 50.000 Datensätze gleichzeitig angezeigt haben wollen.

B
BeZi Themenstarter:in
153 Beiträge seit 2007
vor 7 Jahren

Merci für die Antwort,

leider ist es so das die Anzahl der Objekte benötigt werden. Auch wenn ein Benutzer des Programms nicht alle Objekte auf einmal sieht so werden dennoch Operationen damit innerhalb des Tools ausgeführt. Leider haben die Objekte eine gewisse Abhängigkeit.

Die Felder der Datenbank gibt eigentlich MINDESTENS (also eher mehr) die Felder der Klasse vor.
Um das ganze zu vereinfachen gebe ich der Datenbank (die Dynamisch erzeugt wird beim ersten starten des Programms) nur die Möglichkeit von (Int, double, boolean, Datetime, text) vor. Diese Info kommt aus einer serialisierten "Spaltenklasse" (--> Spaltenname, Typ, evtl. Länge)

Die Frage ist halt nun ob "Object" das richtige ist.

2.079 Beiträge seit 2012
vor 7 Jahren

Also eine Unterstützung seitens Kompiler wirst Du nicht bekommen.
Die einzige Möglichkeite ist eine Liste zu haben, wo Du alle benötigten Infos hältst. Ich würde da Name, Typ und Wert nehmen.
Hier bietet sich auch ein Dictionary an, mit dem Namen der Property als Key. Das Dictionary ist auch schön schnell, bei sehr vielen dynamischen Properties.

Beachte dabei aber auch, dass Du dir überlegen musst, wie Du die Daten in der Datenbank hältst.
Eventuell bietet sich hier an, die Daten als String zu halten, dann muss die Daten-Schicht das entsprechend richtig konvertieren können. Damit das funktioniert, muss zusätzlich zu den Daten auch der Typ gehalten werden.

Wie das mit der Performance aussieht:
Also schnell ist das nicht, aber das Problem hast Du immer bei dynamischen Inhalten, dass das langsamer ist, als "normale" Properties.
Ich kann aber aus Erfahrung sagen, dass das nicht in's Gewicht fällt, wenn Du dir genau überlegst, was Du wirklich abfragst und in Objekte holst.
Ein paar Tipps:*Wenn Du viele Daten bearbeiten musst, die aber nicht angezeigt werden, kannst Du StoreProcedures nutzen. Klug angewendet kann man damit viel Zeit raus holen. Übertreibe es aber nicht, die Frage der Wartbarkeit ist mindestens so wichtig wie die Performance. *Lade niemals mehr als Du anzeigst, dann lieber bei jedem Klick nach laden, was Du brauchst und weg werfen, was Du nicht mehr brauchst. In dem Projekt, bei dem ich das gesehen habe, waren das meist nur 10 Datensätze, das fällt gar nicht auf. *Das Klonen von Objekten und dann neu befüllen ist schneller als neu Erzeugen von Objekten. Es bietet sich also an, ein leeres Dummy-Objekt zu erzeugen und das für jedes weitere Objekt zu klonen. *Bei sehr vielen Daten kann es deutlich schneller sein, wenn Du eventuell direkt auf die Datenbank gehst. Ob das lohnt, müsstest Du dann entsprechend austesten.

Ich hab schon gesehen, wie die Arbeit mit mehreren 100 Tausend Datensätzen, die so aufgebaut sind, annehmbar schnell geht.

leider ist es so das die Anzahl der Objekte benötigt werden. Auch wenn ein Benutzer des Programms nicht alle Objekte auf einmal sieht so werden dennoch Operationen damit innerhalb des Tools ausgeführt. Leider haben die Objekte eine gewisse Abhängigkeit.

Dann lade nur, was Du brauchst. Wenn Du ein paar Daten aus jedem Datensatz brauchst, aber nicht die dynamischen Inhalte, dann lade die dynamischen Inhalte nachträglich, erst wenn sie abgefragt werden.

Die Frage ist halt nun ob "Object" das richtige ist.

Ja
Je nach Typ sollte das dann in das passende Objekt konvertiert werden. Wie das auf der Datenbank gehalten wird, musst Du dir dann konkret überlegen. String oder Blob dürfte denke ich am ehesten in Frage kommen.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

16.835 Beiträge seit 2008
vor 7 Jahren

Und Generics sind nichts für Dich?

public class Eigenschaft<T>
{
  public String Name {get;set;}
  public T Value {get;set;}
}

Es geht in meinen Augen immer besser als object.

Und dahin gehend würde ich das dann auch noch mit nem Interface verbinden, alá

public interface IEigenschaft {}

public interface IExtendable
{
   List<IEigenschaft> CustomFields {get;set;}
}

public abstract class Extendable : IExtendable
{
   public List<IEigenschaft> CustomFields {get;set;}
}

public class CustomClass : IExtendable
{

}

PS: hunderttausende von Objekten zu laden und dann noch hohe Performance erwarten wird nicht funktionieren.
Das funktioniert ja rein rechnerisch von der verfügbaren Bandbreite gar nicht. Du kannst zB nicht 500 MB an Daten aus der DB in wenigen Millisekunden laden, wenn die theoretische Bandbreite 10MB/s beträgt.
Da wird man sich also nen intelligentes Nachladesystem überlegen müssen.

B
BeZi Themenstarter:in
153 Beiträge seit 2007
vor 7 Jahren

Ich bin für alles offen....

Das mit der Performance passt alles für mich.... Es gibt bestimmte Algorithmen, die alle Objekte beachten müssen. Da gibt es kein Problem ob der User kurz warten muss. Das ist in diesem Fall ok.

Ich wollte nur Fragen was in diesem Fall die Beste Lösung ist bzw. was Ihr verwendet würdet.

"Object" finde ich auch nicht so geschickt wenn man es mit Generics vergleicht.... also schon besser

Dictionary noch nie eingesetzt.

2.079 Beiträge seit 2012
vor 7 Jahren

Generics sind schön, aber wie sollen die sinnvoll genutzt werden, wenn die Daten dynamisch aus der Datenbank kommen?
Beim Erstellen im Code kann man ja mit Generics arbeiten, wenn das dann aber in einer Liste landet, dann darf es nicht generisch sein oder es muss ein nicht generisches Interface geben. Allerdings finde ich dann auch nicht, dass es lohnt, das generisch aufzubauen, da man am Ende ja sowieso nur mit dem nicht generischen Interface arbeiten kann, da ja alles aus der selben Liste bzw. von der Datenbank kommt.

Es gibt bestimmte Algorithmen, die alle Objekte beachten müssen.

Und wenn das auf der Datenbank geschieht?
Als Beispiel:
Wenn Du automatisch einen neuen eindeutigen Namen für ein Objekt möchtest, dann muss dabei jeder andere Datensatz beachtet werden, damit der Name eindeutig bleibt.
Ich sehe da zwei Optionen:*Ich frage bei der Datenbank nach allen aktuell verwendeten Namen und muss dann nur die Liste von Strings entgegen nehmen und verarbeiten. *Das Generieren des neuen Namens passiert auf der Datenbank

Bei sehr großen Datenmengen würde ich das auf die Datenbank verlegen.

Das lässt sich dann natürlich auf jeden Anwendungsfall übertragen.
Wenn die Daten, die für den Algorithmus benötigt werden, leichter sind, als der normal abgefragte Datensatz, dann lohnt es sich bei großen Datenmengen, auch nur das Benötigte abzufragen. Vielleicht kannst Du die Daten auch schon auf der Datenbank vorbereiten
Wenn der Algorithmus zwar zeitaufwendig ist, sich aber auch annehmbar wartbar in Form von SQL umsetzen lässt, kann es sinnvoll sein, das auf der Datenbank zu erledigen.
Du solltest aber immer im Hinterkopf behalten, dass SQL (zumindest meiner Meinung nach) deutlich unschöner zu handhaben und zu warten ist, als C#/VB.NET. Da musst Du dann abwiegen, was schwerer wiegt.

Und wegen dem Dictionary:
Schau es dir mal an. Der Key ist eindeutiges Objekt, über den Du den Wert sehr performant abfragen kannst.
Wenn der Key der Name jeder dynamischen Eigenschaft ist und Du davon sehr viele hast, dann dürfte das einen spürbaren Unterschied machen, ob Du ein Dictionary nutzt oder beim Abrufen einer Eigenschaft jedes mal aufs neue eine Liste durchsuchen muss.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

P
1.090 Beiträge seit 2011
vor 7 Jahren

I Es gibt bestimmte Algorithmen, die alle Objekte beachten müssen.

An der Stelle solltest du zumindest ein Interface oder eine Basis Klasse haben. Damit du deinen Algorithmus anwenden kannst. Von denen sollte dann deine Konkreten Klasse erben.

Mit den Klassen kannst du dann auch Anständig arbeite. In der Oberfläche kannst du dann die Benötigten Felder Anzeige, wie soll sonst ein Kunde wissen was er eingeben muss. Du kannst die Werte Validieren u.s.w.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

B
BeZi Themenstarter:in
153 Beiträge seit 2007
vor 7 Jahren

Also erstmal vielen Dank das ihr euch das alles durchgelesen habt.

Das was ich schreiben will existiert schon in Version 1. Ich will das ganze jetzt nur noch "pimpen" indem ich wie ich schon sagte bei der Klasse Flexible sein will, mehr nicht.

Die Sache mit den anzahl der Objekten der Klasse kann ich in diesem Fall nicht umgehen. Darauf brauche/wollte ich auch keine Antwort. Trotzdem danke 😉

Das einzige was ich wissen wollte ist die Sache mit der "flexiblen" Klasse.

Object wäre ok....
Den Unterschied zwischen Generics und Dictionary... habe weder mit dem einen noch dem anderen gearbeitet... Genau das ist ja das was ich wissen wollte.
Ich muss halt flexible sein.

Die Klasse könnte 5 aber genauso 30 "Felder" enthalten... Ja gut und dann davon halt dann 50000 Objekte.
Bzgl. Performance.... bei der Anzahl der Objekte darf Berechnungen immer länger dauern. Performance heißt für mich in diesem Fall wie gut ich mit der Anzahl umgehe. Aber wie ich schon sagte das ist 2. Ranging.

Was interessant ist, ist die Performance aus dem die Klasse (oder das Objekt) besteht....

16.835 Beiträge seit 2008
vor 7 Jahren

Deine Argumentation ist weder schlüssig noch zielführend.
Nur weil Du eine bestehende Codebasis hast, heisst das nicht, dass diese für Dein Vorhaben überhaupt geeignet ist.

Mir ehrlich gesagt ist etwas schleierhaft, wie Du 2016 eine DAL-Version #1 entwickelt hast, ohne dabei mit Generics in Kontakt gekommen zu sein.
Du bist seit 2007 - also rund 10 Jahre - hier angemeldet und kennst weder Dictionaries noch Generics..? Das ist soweit aber nicht schlimm; aber nimm doch den Rat der Helfer hier an oder höre ihn Dir zumindest an, statt zu sagen "brauche ich nicht".

Die Angabe, dass es performant ist, ist relativ.
Das mag evtl. auf Deiner Maschine so sein - Produktivanwendungen haben aber i.d.R. ganz andere Anforderungen an sowas.
Rein rechnerisch (50000 Objekte + Eigenschaften) reden wir alleine vom Laden von mehreren Sekunden.

Ich will damit nur sagen, dass das Vorhaben von Custom Fields in Datenbanken viel viel komplizierter ist in der Anwendung des Ganzen, als nur Key-Value zu speichern.
In größeren Anwendungen werden damit ganze Teams beauftragt; extra Datenbank-Engines für solch eine Anforderung entwickelt.

B
BeZi Themenstarter:in
153 Beiträge seit 2007
vor 7 Jahren

??? 🤔

Also erstens wie ich was und wo einsetze bleibt ja eigentlich mir überlassen. Wenn ich eine Klasse "Benutzer" habe und dessen Felder jetzt dynamisch gestalten will, aber das so noch nie gemacht habe und vorher waren diese Felder fest definiert, dann finde ich das eine vollkommen berechtigte Frage. - Dachte eigentlich dafür ist ein Forum da... Fragen stellen zu können, bzw. zu helfen zu können wenn ich kann. Wird mir jetzt ein Vorwurf gemacht das ich eine bestimmte Sache noch nicht eingesetzt habe ? WOW.

Und welche Argumentation? Für was? Wieso zielführend?

Wenn ich nur 1, 10 , 100 Objekte als Max. definiert hätte, hätte das eigentlich KEINE Auswirkung auf die Gestaltung der Klasse haben dürfen (sollte)... das macht in meinen Augen gute Programmierung aus. Die Objekte sollten eigentlich bei 1 , bei 1000 oder eben 100.000 Objekten gut aufgebaut/sein (und dann wenn nötig gut skalieren).

Den Rat der Helfer in Bezug auf die DB brauche ich an dieser Stelle nicht (Und ich weiß das es gut gemeint ist und das ist auch gut so). Dennoch war das nicht meine Frage. (Was in keinster Weiße aber abwerten klingen soll). Wo ich was und wie von meinen Algorithmen berechne auch nicht. Ich habe lieber eine gezielte Antwort auf eine gezielte Frage. Und meine Frage war jawohl gezielt. Ich will nicht den Leuten ihr wertvolle Zeit klauen....

@Abt: Es ist fast schon ironisch das man sich Gedanken macht, wie kann ich was besser machen, tüftelt ein wenig, und dann fragt man in einem Forum nach....und dann solch eine Antwort .... krass.

Zurück zu meinem Post: Ich lasse meine Datenbankfelder dynamisch erstellen aus meinem Programm. Diese (Spalten) - Felder möchte ich dann in meiner Klasse nutzen. Und da ich das eine dynamisch erzeuge und nicht fest definiert ist, möchte ich das ganze auch in der Klasse dynamisch halten. Mehr wollte ich nicht wissen. Und darüber wollte ich mich informieren / reden.

16.835 Beiträge seit 2008
vor 7 Jahren

Kein Mensch hat gesagt, dass Du nicht fragen darfst oder sollst - im Gegenteil. Ich habe gesagt, dass Du gerade den Helfern auch gern zuhören darfst, wenn Du es noch nicht gemacht hast.
Du hast aber gesagt

Darauf brauche/wollte ich auch keine Antwort.

Und genau das macht halt in einem Forum keinen Sinn.

Zudem hören Helfer nicht gerne "Danke für die Antwort, aber Deine Antwort interessiert mich nicht" 😃

Zusammen mit dem Satz

Ich will das ganze jetzt nur noch "pimpen" indem ich wie ich schon sagte bei der Klasse Flexible sein will, mehr nicht.

.. ist das eben eine Argumentation, die nicht so wirklich zielführend ist.
Das "mehr nicht" beachtet gar nicht, ob Du eine Basis des Codes hast, mit der Du überhaupt in der Form flexibel agieren kannst. Es gibt ja bewährte Konzepte, die sich von Deiner Basis völlig unterscheiden können.
Du redest ja hier von einer konzeptionellen Anforderung. Nicht davon, dass der rote Button Grün sein soll.

In meinen Augen wäre es für Dich zielführender zu fragen, wie man ein flexibles Schema im Allgemeinen angeht. Genau in der Form bzw Richtung haben das ja auch Palin und Palladin007 beantwortet.
Du hast jetzt aber schon eine Code-Basis, die Du auch schon in manchen Dingen flexibel hast; für mich aber danach anhört, dass Du das jetzt "irgendwie" hinbekommen willst.

Aus Erfahrung hier im Forum wollten die Leute ihr Problem gelöst haben statt das Problem.
Und so scheint es mir hier auch zu sein 😉 Es war nie eine Aussage hier gegen Deine Person.

Thema:
Dass Du bei der Form - die ich zB. als konzeptionell sehr altmodisch bezeichnen würde - aber gar keine Typisierung haben kannst, sollte logisch sein.
Das ist das was ich meinte, dass Du es eben "irgendwie" angegangen bist ohne bewährte Konzepte zu evaluieren. Du wolltest eben nicht das Problem, sondern Dein Problem lösen 😉

Die Basis passt natürlich nicht auf neuere Konzepte wie eben Generics - oder weiter gesponnen, was mit Nicht-relationalen Datenbanken möglich wäre.

5.658 Beiträge seit 2006
vor 7 Jahren

Hi BeZi,

Was ist wenn ich eine Klasse erzeugen will von der noch nicht bekannt ist was für einen Inhalt/ Eigenschaften hat.

Der von dir vorgeschlagene Weg (der im Prinzip einem KeyValueStore entspricht) hat einige Nachteile. Hast du schonmal darüber nachgedacht, den EntityFramework zu verwenden? Damit könntest du per Migrations Datenbankschema und Klassen auf geänderte Anforderungen anpassen, neue Felder hinzufügen oder entfernen, etc.

Weeks of programming can save you hours of planning