Dataset driven Development

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Dataset driven Development

    @ErfinderDesRades

    Ich arbeite noch deinen Code durch. Notiere mit erstmal alles was ich nicht nachvollziehen kann und stelle dann Fragen ^^

    Zur Erklärung des "Stationen"
    In dem "Daten-DataTable" "Messwerte" haben die in der Tat nur eine Nummer. (Integer) weil man damit besser weiter arbeiten kann als mit (String). Wartbarer, wurde mir mal gesagt.

    In dem "Programm-DataTable" "Settings" werden dann neben anderen Programmeinstellungen, die Realnamen für die Stationen vergeben. Diese dienen dann dazu folgendes mit dem "Namen" zu benennen.
    • Die TabPage-Reiter ===> "Daten Wohnraum" ===> "Diagramm Wohnraum"
    • Die DataGridViws ===> "DgvWohnraum"
    • Die Charts ===> "ChartWohnraum"

    Das war, glaube ich, in dem Beispiel Code nicht ersichtlich, weil ich die da noch "hardcodiert" hatte. Wegen der Einfachheit. ;)

    Das Setting-DataTable
    Spoiler anzeigen

    XML-Quellcode

    1. <DesignColumnRef Name="ID" />
    2. <DesignColumnRef Name="BackUpDrive" />
    3. <DesignColumnRef Name="NameStation1" />
    4. <DesignColumnRef Name="NameStation2" />
    5. <DesignColumnRef Name="NameStation3" />
    6. <DesignColumnRef Name="SensorCalibration" />
    7. <DesignColumnRef Name="LastCalibration" />
    8. <DesignColumnRef Name="AlarmTemp1" />
    9. <DesignColumnRef Name="AlarmTemp2" />
    10. <DesignColumnRef Name="AlarmTemp3" />
    11. <DesignColumnRef Name="AlarmHumidity1" />
    12. <DesignColumnRef Name="AlarmHumidity2" />
    13. <DesignColumnRef Name="AlarmHumidity3" />
    14. <DesignColumnRef Name="AllowNegativeTemp1" />
    15. <DesignColumnRef Name="AllowNegativeTemp2" />
    16. <DesignColumnRef Name="AllowNegativeTemp3" />
    17. <DesignColumnRef Name="CalibratedStation1" />
    18. <DesignColumnRef Name="CalibratedStation2" />
    19. <DesignColumnRef Name="CalibratedStation3" />



    *Topic verschoben*
    Bilder
    • StationName1.jpg

      155,4 kB, 1.136×183, 46 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Hi!

    Lass uns die anhängende Sample-App "ClimaSenceE02" zum Ausgangspunkt nehmen, damit wir von etwas reden, was beide haben, und was funktioniert.



    Ich stell nochma kurz die Prinzipien von DDD voran:

    Bei DDD gehts um GUI (Forms, UserControls), Datenmodell (typDataset), BusinesLogik (BL), Helpers.
    Das sind die 4 Bereiche, denen etwas zuzuordnen ist. (und "Sonstiges", weil das gibts ja immer)
    BusinesLogik wird als Partial Classes der typisierten Table- und Row-Klassen ausgeführt.
    Deshalb sind die BL-Files meines Code-Beispiels auch zusammen mit dem Dataset im "Dataset"-Ordner.
    Die BL-Files führen im Namen den Dataset-Namen zuzüglich einer Zuständigkeits-Bezeichnung.
    Die erste BL-Datei kriegt als Anhängsel einfach "BL", und da kommt zunächstmal alle BusinesLogik rein.
    Wenn sie dann zu gross wird, lagere ich Sachen aus: so ist die Datei "DsClima.PrintMesswerte" entstanden.

    Hingegen was du "Calculations" genannt hast, habe ich bislang in "DsClima.BL" belassen - ist ja noch nicht so viel.
    Aber wenn da noch mehr von der Sorte kommt, wirds natürlich auch ausgelagert.



    Es gibt deutliche Ähnlichkeiten zwischen DDD und MVVM (wenn auch in Umsetzung extrem unterschiedlich):
    • Model-Klassen
    • zentrale Mainmodel-Instanz
    • Trennung von GUI und Daten
    • Verknüpfung von GUI und Daten via Databinding


    Von meiner Warte aus würde ich die Umarbeitung fortsetzen, etwa dass es für "Settings" ein eigenes Dataset geben soll scheint mir eine unnütze Verkomplizierung.
    Jetzt hab ich auch mal reingeguckt in deine "Settings" - das sind ja garkeine Settings - das sind ja hauptsächlich Daten.
    Nämlich es ist der Versuch eines Station-Datenmodells, was mir im "richtigen" Dataset ja gefehlt hat.
    Mit Name (je Station), AlarmTemperatur (je Station), AlarmHumidity (je Station), AllowNegativeTemp (je Station)

    Das Datenmodell deiner "Settings-Stationen" ist aber komplett schief, weil in deiner Tabelle gibts je Station-Eigenschaft eine Spalte: NameStation1, NameStation2, NameStation3 , AlarmTemp1, AlarmTemp2, AlarmTemp3, AlarmHumidity1, AlarmHumidity2, AlarmHumidity3, AllowNegativeTemp1, AllowNegativeTemp2, AllowNegativeTemp3.
    Dadurch beschreibt jeder Datensatz 3 Stationen, was Unfug ist.
    Jeder Datensatz soll eine Station beschreiben, und wenn drei Stationen da sind, dann werden eben drei Datensätze angelegt.
    Korrekt wäre also:
    Tabelle Station
    ID, Name, AlarmTemp, AlarmHumidity, AllowNegativeTemp
    Was ja auch gleich viel übersichtlicher ist.

    Kann ich übrigens gleich einbasteln ins dsClima - 5 min.



    Wo du so gerne liest: https://www.codeproject.com/Articles/1030969/Relational-Datamodel-for-Beginners
    Ein Tutorial in 3 Teilen, welches Schritt für Schritt aufbaut von Grundlagen der Datenmodellierung über die Konzepte und Klassen des typisierten Datasets hin zu einer schnuckeligen Beispiel-Anwendung.

    Grade das: Datenmodellierung und Konzepte und Klassen des typisierten Datasets täte ich dir ans Herz legen. Weil du bist grad in diesen Themen unterwegs, aber noch mit deutlichen Unsicherheiten/Lücken.
    Dateien
    • ClimaSenceE02.zip

      (191,54 kB, 45 mal heruntergeladen, zuletzt: )
    • ClimaSenceE03.zip

      (192,2 kB, 82 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hallo

    Habe nun nochmal bissel nachgedacht und das DataSet und die DataTables geändert bzw neu erstellt, so in dem Sinne wie es besser zusammenpasst. :)

    Im oberen DGV kann ich nun den StationsNamen vergeben / ändern. Der Name ändert sich dann auch im unteren.
    Desweiteren kann ich im obenen DGV bestimmte Grenzwerte vergeben.

    Im unteren DGV ist nur der "Anpassungswert" für jede Station einstellbar.

    @ErfinderDesRades
    Dein Code muss ich noch lange studieren, NOCH sehr verwirrend für mich.
    Bilder
    • newDSDT.jpg

      284,21 kB, 766×593, 35 mal angesehen
    • newDSDT2.jpg

      319,02 kB, 900×522, 37 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Hast du eigentlich den Solution-Explorer?
    Weil damit kann man mit einem Klick ein Backup machen.
    Das ist sehr wichtig, wenn man am Dataset Veränderungen vornimmt.
    Weil Veränderungen am Dataset können bewirken, dass die Daten nicht mehr kompatibel sind, oder Databindings fehlschlagen.
    Wenn sowas passiert ist man sehr froh, wenn man auf ein Backup zurückgreifen kann, wo es noch funktionierte.

    Zum Datenmodell:
    Sieht mir einigermassen sinnvoll aus, was du grad machst.
    "Adjustment" scheint mir aber kein guter Name.
    Weil was ich da in der Tabelle sehe, sind doch Datensätze, die je einen Sensor beschreiben.
    Daher würde ich diese Tabelle Sensor nennen.

    Amelie schrieb:

    Dein Code muss ich noch lange studieren, NOCH sehr verwirrend für mich.
    So eine Aussage bringt nix.
    Deine Verwirrung wird sicher nicht weniger, wenn du mir das mitteilst.
    Du müsstest also schon genauer erklären, welches Detail du nicht verstehst. Die Ordner-Struktur? Die partialen Klassen? Das Helpers-Projekt? Ja, was?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Moin moin

    Ich mache Backups von den Sachen, aber wie ich schon erwähnte, fange ich oft einfach neu an, wenn es alles zu verzettel und aufgebläht ist.
    Gestern z.B. Habe ich gemerkt, das man echt haufen Probleme bekommt die Textfelder in einem DGV so zu gestalten, das nur bestimmte eingaben möglich sind.
    Da war ich soweit, das ich kaum Code in der Form-Class hatte und dann...
    Überlege nun das mit den DGV wieder zu verwerfen und wieder Mask-Textboxen zu verwenden.

    Also als erstes verwirrten mich diese 2 User-Contorls. Haben so garnichts mit dem wie ich mir die "GUI" vorstellte. Aber das ist wohl eher von weniger belang.

    Partial Class DSClima
    Public Shared ReadOnly Dts As New DSClima

    Wo ist denn das ganze Bindingzeugs usw.?
    Ich sehe da etwas in dem "Helper-Teil" kann das aber noch Null zurodnen.

    Public Module ObjectX
    ....
    Damit kann ich noch garnichts anfangen.

    Zu dem Namen "Adjustment" bin ich gekommen, weil ich da ja die Werte der einzelnen Stationen "anpassen, angleiche ..."
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Ja, so kann ich anfangen, was zu erklären.

    Helpers:
    Das ist fortgeschrittener Code, den ich in vielen Projekten brauche: In einem Projekt dies, im anderen das.
    Daraus folgt, dass da immer auch Zeug drin rumfährt, was im aktuellen Projekt garnet gebraucht wird.
    Beides macht das Helpers-Projekt für sich extrem unverständlich.
    Aber brauchst du ja auch nicht zu verstehen. Verstehen musste das Haupt-Projekt.
    Allenfalls interessant könnte sein, wenn du hin und wieder im Haupt-Projekt auf einen Aufruf stösst, der in die Helpers führt.
    Das lohnt sich dann evtl., nachzufragen.

    die 2 UserControls:
    Du meinst, du willst das GUI anders haben?
    Aber beachte immerhin, dass es funktioniert, und zwar ziemlich pfiffig.
    Du brauchst nicht 3 Tabs, um Messwerte dreier Stationen anzugucken, sondern das geht im selben Tab, indem du mit der Station-Auswahl-Combobox die Station auswählst, deren Messwerte du angucken willst.
    Zusätzlich kannste sogar "Alle" anwählen - und das alles ohne einen zusätzlichen Tab!

    Übrigens tun die beiden Ucls dasselbe. Nur uclMesswerte2 hat ein besser gestaltetes DGV:
    Nämlich in uclMesswerte ist die Tabelle einfach so zu sehen, wie sie ist.
    Hingegen in uclMesswerte2 ist die ID entfernt, weil mit der Information kann kein User was anfangen.
    Und die Spalte Station ist als ComboboxColumn ausgeführt, und zeigt daher Station.Name an, was doch viel besser ist, als wie es auf uclMesswerte ist - oder?

    Ja, und den Print-Button hab ich vom MainForm weggeholt und ins ucl verlagert. Weil das wäre doch unlogisch, beim Angucken eines Charts, und dann "Print" drücken, und dann kommt eine Tabelle raus statt des Charts, was man grad anguckt.
    Daher den Print-Button aufs UserControl, dann druckt er das, was man auch sieht.
    Hast du den UserControl-CodeBehind eiglich schon gefunden? Es ist genauso wie bei einem Form: zB Doppelklick im Designer auf den Button bringt dich in die UserControl-Codebehind-Datei zu seinem Click-Eventhandler.

    Insgesamt aber finde ich, sieht das GUI dem GUI deiner anfänglichen Anwendung doch sehr ähnlich, oder irre ich?
    Also zumindest TabMesswerte, die anderen Tabs waren ja noch ohne Funktion.

    Amelie schrieb:

    Habe ich gemerkt, das man echt haufen Probleme bekommt die Textfelder in einem DGV so zu gestalten, das nur bestimmte eingaben möglich sind.
    Welche Eingabe in uclMesswerte2 möchtest du in welcher Weise einschränken?
    Da kann man überlegen, ob das im dgv möglich ist, oder ob man das dgv readonly macht, und editieren, Zufügen, löschen nur zulässt über einen neu zu schaffenden Edit-Dialog (das ist Standard-Verfahren).

    Amelie schrieb:

    Wo ist denn das ganze Bindingzeugs usw.?
    Das ist auf den UserControls.
    So ist das von Microsoft vorgesehen, dass man diese Dinge aufs Form/UserControl zieht, und im Designer in geeigneter Weise einrichtet.
    Mpin mopin

    Ich werde weiter mit deinem Code üben, versuchen zu verstehen und dann Fragen stellen :) :thumbup:

    Über den Aufbau der GUI lässt sich ja nicht streiten.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Über den Aufbau der GUI lässt sich ja nicht streiten.
    Verstehe nicht, was du damit meinst.
    Natürlich ist man da unterschiedlicher Meinung, und darüber kann man ins Gespräch kommen.
    Ich könnte etwa mit Leichtigkeit aus dem bestehenden ucl ein ein weiteres ucl basteln ohne Station-AuswahlCombo, und dann - wie gehabt - ucls auf je ein Tab aufs TabControl tun.
    Sieht dann genauso aus wie dein ursprüngliches Design.
    Vielleicht wäre das auch für dich gut zu wissen, wie das geht: Ein ucl duplizieren, um die Kopie dann weiterzuentwickeln, ohne das vorherige aus der Solution rauswerfen zu müssen.

    Du musst es aber sagen, was du möchtest:

    Möchtest du im GUI für jede Station ein Tab?
    Dann sind die Stationen hardcoded, und wenn eine Station hinzukommt, muss man neuen tab hinmachen und recompilieren.
    Bei nur einem Tab fügt man den Daten eine Station hinzu, und kann diese sofort in der Combobox auswählen.

    Möchtest du lernen, wie man ucls dupliziert?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hallo ;)

    Lernen möchte ich viel; Aber eins nach dem anderem.
    Wird grad alles bissel viel. Muss erstmal etwas sacken lassen und mir einige Übungsbeispiele machen, befor ich wieder an das eigentliche Projekt gehe.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Hallo

    ​Dann sind die Stationen hardcoded, und wenn eine Station hinzukommt,

    Das ist natürlich eine Überlegung wert. Tatsächlich hatte ich schon überlegt, wie man evtl zur Laufzeit bis zu 3 Tabs mit DGV und Chart hinzufügen kann.
    Das habe ich aber irgendwann verworfen, das wohl zuviel programmieraufwand???

    Ich spiele noch mit ein paar Ideen herum, versuche dein Code zu verstehen...
    Mich treib ja keiner.. ( noch nicht ) :D
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Tatsächlich hatte ich schon überlegt, wie man evtl zur Laufzeit bis zu 3 Tabs mit DGV und Chart hinzufügen kann.
    Das habe ich aber irgendwann verworfen, das wohl zuviel programmieraufwand???
    Man kann es machen, aber nicht mit Databinding.
    Quasi müsste man für die TabPages all das nachprogrammieren, was bei Databinding mit Daten automatisch geht. Meist programmiert man nur einen Teil davon nach, und muss später nachlegen..., und dann sind Fehler drin..., Wartung bei Konzept-Änderungen...

    Also ich empfehle sehr, erstmal überhaupt ein funktionierendes GUI zu erstellen, möglichst rein DDD.
    Wenn man später noch so Extra-Würste braucht, kann man immer noch überlegen.
    DDD ist sehr offen für Extra-Würste.
    Weil prinzipiell gehts ja darum, Datenverarbeitung aus dem GUI-CodeBehind in (partiale) Datenklassen zu verlagern.
    Aber es bleibt im CodeBehind doch ein kleines bischen übrig (zB Click-Handler sind immer im GUI-CodeBehind).
    Wenn mans nun drauf anlegt, kann man den CodeBehind auch wieder zuballern mit lauter Logik - das geht dann wieder in Richtung Kuddelmuddel, wies vorher war, ohne DDD.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()