Neuerstellen eines umfangreichen Projektes - aus schlechtem Code mach guten Code

  • VB.NET

Es gibt 213 Antworten in diesem Thema. Der letzte Beitrag () ist von DerSmurf.

    Neuerstellen eines umfangreichen Projektes - aus schlechtem Code mach guten Code

    Guten Morgen ihr lieben
    In den letzten ca. anderthalb Jahren habe ich ein Programm erstellt, welches ich für alles verwenden kann, was man bei mir (und meiner Schwester) im Zooladen mit dem PC machen kann.
    Da der genaue Funktionsumfang für diesen Post nicht relevant ist, lade ich nur mal ein Bild mit hoch (von einem der 4 Programme innerhalb der Solution), außerdem lade ich noch ein Bild des aktuellen DataSets hoch.
    Das Problem ist, dass dieses Projekt eines meiner ersten war. Die Ausführung des Programmes ist zwar zu meiner vollsten Zufriedenheit, der Code aber leider nicht.
    Ein Blick aufs DataSet verrät z.B. meine grauenvolle Bennenung, und es gibt sinnlose DataTables (die ArticleSupplier z.B. ist komplett sinnbefreit - das könnten auch die Supplier übernehmen).
    3 DataSets habe ich rangeschmissen - 2 davon sind aber wohl sinnbefreit.
    Da aber nun das Programm in 2 Läden im Einsatz ist und ich tierische Angst vor Datenverlust bei großen Änderungen habe, habe ich mich entscheiden, das gesamte Projekt neu zu erstellen.
    Dazu stelle ich nun Vorüberlegungen an. Damits gescheit wird, teile ich das mit euch.

    1. aktuell nutze ich (auf meinem Programmier PC VisualStudio 2020 - meinen ArbeitsPC habe ich letztens neu aufgesetzt und gesehen, dass es VS2022 gibt.
    Spielt es eine Rolle mit welcher VS Version ich das Projekt erstelle?

    2. die Bennenung
    Spricht etwas dagegen die DataTables, deren Rows, Variablen, Forms und Buttons in Deutsch zu bennen?

    3.wie ihr auf dem Screenshot seht, gibt es eine Mainform. Dort befindet sich ein TabControl mit versteckten Reitern. Hiermit wird die Anzeige entsprechend umgeschaltet.
    Das möchte ich auf ein mdiChild Modell umstellen (da habt ihr mir ja mal in einem anderen Thread erklärt wie das gescheit funktioniert).
    So bekomme ich glaube ich automatisch eine schönere Sortierung des Codes (bisher ist fast alles in der Mainform).
    Hier ist nur die Frage, wie übergebe ich dann am besten die Datenquellen der Bindingsources?
    Mache ich das "händisch" bei der Instanzierung der neuen Form (geht das überhaupt bei MDI Child)?
    also NewForm.Bindingsource.Datasource = Me.Dts
    oder nehme ich da die Empfehlung vom @ErfinderDesRades . Von ihm gibts ja eine Methode mit der irgendwie automatisch jede neue Form auf das gleiche DataSet zugreifen kann?

    4. bleibe ich bei meinem DataSet Modell (mit dem ich mehr als zufrieden bin), oder lohnt vielleicht doch der Umstieg auf eine Datenbank?
    Bilder
    • frmMain.png

      207 kB, 2.880×1.920, 191 mal angesehen
    • Dts.png

      370,13 kB, 2.880×1.920, 181 mal angesehen
    1. Es gibt VS 2017, 2019, 2022. VS 2020 kenn ich nicht, aber bis auf wechselnde Studio-Bugs sehe ich kein Problem in dem Wechsel.
    2. Das ist Deine Entscheidung. Das Problem dürfte das Dateneinlesen sein, da in den XML-Daten bestimmte Namen drin sind. Steht also in den XML-Daten: »hier sind Daten für das FooTds«, aber es gibt in Deinem Programm kein FooTds, sondern nur ein OldFooTds, dann werden die Daten nicht importiert. Genauso mit umbenannten Tabellen oder Tabellenspalten. Das Umbenennen ist also mit Datenmanipulations-Aufwand verbunden. Alternativ könntest Du ein richtig benanntes tDS zum bestehenden erstellen und die Daten zur Laufzeit rüberkopieren. Vielleicht gibt es auch andere Möglichkeiten, aber mir fällt auf Anhieb keine ein.
    3. Wenn jede TabPage ein UserControl statt ein Form beherbergt, wäre es ähnlich wie bei MDI klassengetrennt. Zum Thema Datenübergabe gibt es ja mehrere Ansätze. Meine ist: auf jedem Form/UserControl gibt es eine MainBindingSource. Die bekommt als Datenquelle bei Dir die formeigene-tDS-Instanz. Alle anderen BindingSources binden nicht an die tDS-Instanz, sondern an die MainBS. Und wenn dann das Form aufgerufen wird, wird nur die DataSource der MainBS neu gesetzt (NewForm.MainBindingsource.Datasource = Me.Dts) und das war's. Die anderen BindingSources wissen dann bescheid.
    4. Eine Datenbank wird m.E. erst dann für Dich interessant, wenn Mehr-gleichzeitig-Benutzer die Daten verwenden. Ansonsten bleib bei Deiner Variante.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    zu 2.
    Imo spricht in diesem Fall nichts gegen muttersprachliche Benamung.
    Aber auch das Englische verstehe ich bis auf einige Worte (Purchase, Retail) ganz gut - ist also (für mich zumindest) von den Begriffen her kein allzu schwieriges Dataset.
    Allerdings von Prefixe wie clmArticle, oder pluralisierte Tabellennamen rate ich dringend ab.

    zu 3.
    Von MDI haltich nix. Weil was MDI leistet, können Tabs ebensogut/besser.
    Eine tabbed Anwendung kann man sehr gut modularisieren durch UserControls.
    Ein UserControl ist genau dasselbe wie ein Form, was man aber nicht öffnen, sizen, verschieben kann. Stattdessen ist es dafür vorgesehen, als Control auf einem Form plaziert zu werden.
    Mach auf jedem deiner Tabs ein UserControl, und du hast dieselbe Modularisierung, wie wenn du mehrere MDIChild-Forms basteln würdest.
    Und sparst dir dabei das Gehampel mit der MDI-Ver(ge)walt(i)gung.
    Eine Modularisierung in UserControls (oder MDI-Childs) erfordert ein global zugreifbares Dataset. Und alle Bindings müssen zur Laufzeit darauf umgestöpselt werden. Da kannste entweder meine Register-Extension für nehmen, oder in Designer und Code jeweils bischen mehr Aufwand treiben und AdlerAuge walten lassen.

    zu 4.
    Einen "Umstieg auf Datenbank" gibts nicht.
    Eine Datenbank zu hinterlegen ist eine Erweiterung - vom Dataset wird dabei nix weggenommen.
    Edit: sorry, habe am Handy getippt.
    Autokorrektur ist an, wiean sieht...

    Zu 1. @VaporiZed ja du hast Recht.
    VS2019 hab ich drauf. Aber dann kann ich's ja aktualisieren, wenn ich Lust hab. Oder ich lasse es sein.

    Zu 2. @VaporiZed
    Ich habe vor ein komplett neues Programm zu erstellen, da ich zuviel Angst vor Datenverlust habe und jederzeit am alten weiter ändern möchte, wenn nötig. Wenn das neue Programm das fertig ist bastel ich mir einen Import und fertig.
    Dann werde ich es Deutsch benennen. Wahrscheinlich ist nur wichtig, dass ich konsequent bleibe und nicht Mal deutsch und Mal Englisch. Ich finde das Englisch jetzt auch nicht schwer, aber manche Wörter wirken unnatürlich.

    Zu 3. Da ihr mir beide statt MDI zu Usercontrols ratet, nehm ich das so an.
    Ich dachte nur MDI wäre ähnlich sauber (Klassengetrennt) wie Usercontrols.
    Und ich habe Mal einen Ansatz bekommen (weiß aber nicht mehr von wem) der mir dass ganze rumgehampel abnimmt. Dann wäre ja die Bearbeitung des Codes etwas schöner

    Aber ich habe gelernt, wenn die zwei mit Ahnung abraten, lass es sein.

    4. OK. Ich bleibe bei Dataset. Zwar arbeiten durchaus mehrere PCs mit dem Programm.
    Aber nie mit der gleichen XML.
    Mein Bestellprogramm z.B. erstellt für jede Firma eine XML. Diese können automatisiert auf mein NAS geschoben werden, damit beliebig viele bestellen können.
    Das ginge wohl eleganter, funktioniert aber in der Praxis gut.

    @ErfinderDesRades deine Kritik an der Benennung der Dataset Tables (die ich ja nicht zum ersten Mal höre) ist mit einer der Gründe für das Neumachen.

    Ich werde die Tage einfach Mal anfangen und mein Adressbuch einbauen (das ist so ziemlich das einfachste) und meinen Ansatz Mal hochladen .
    Dann könnt ihr mir sagen, ob ich in die richtige Richtung unterwegs bin.

    Eine Frage noch:
    Wie würdet ihr ein solches Programm, mit dem ihr letztlich alles in eurem Laden macht benennen? Bisher heißt es "Das Programm", denn das ist es letztlich für mich.
    Aber ein anderer Name wäre ja ( wegen der Parallelen Bearbeitung) sehr hilfreich.
    Die Programmbenennung ist Auslegungssache. Meine Programme machen je eine Sache im Groben und bekommen daher nüchterne Namen wie Bestellerinnerung oder Gerätverleihprogramm. Wenn es eine Programmsammlung ist, kannst Du ruhig so kreativ werden wie Du willst. AngelSuite. Zooonator. TiZoBeWaWi (Tier- und Zoobedarfs-Warenwirtschaft), …
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich finde all diese abkürzenden Namen irgendwie schlimm. Wobei mir Zooonator auch gefällt.
    Aber ich habe das Projekt nun Theo genannt. Wofür das steht muss ich mir noch überlegen, aber den Namen finde ich schön :)

    Ich habe nun einen allerersten Ansatz (ohne große Optik und Funktion).
    Eine Frage zum Usercontrol habe ich aber noch. Wenn ihr beide sagt ich soll ein TabControl mit UCs bestücken, dann ja wahrscheinlich im Designer (ich male das UC nun aus der Not heraus im Code auf die Form).
    Warum hier nicht einfach die UCs erstellen und wieder schließen, also ohne TabControl?
    Wie übergebe ich denn dann (bei UCs die ich im Designer auf die Form packe) die Datenquelle der Bindingsource auf dem UC?
    Edit: Mir ist bewusst, dass das Erstellen der UC auf einer TabPage (so wie ich es jetzt gemacht habe) nicht soviel Sinn ergibt.
    Und was meinst du @VaporiZed mit "MainBindingSource"? Eine BS bindet doch immer an EINE DataTable. Greife ich auf der UC auf mehrere DataTables zu, brauche ich doch mehrere Bindingsources?

    Bitte schaut mal über meinen Ansatz, besonders in Punkto Sortierung des Zeugs in der Solution, Benennung, Datenmodell / Übergabe, und eben dem "Einsatz" der UC.
    Dateien
    • Theo00.zip

      (26,25 kB, 82 mal heruntergeladen, zuletzt: )

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

    DerSmurf schrieb:

    Warum hier nicht einfach die UCs erstellen und wieder schließen, also ohne TabControl?

    Weil ein UCL eben keine Form ist sondern ein Control. Soweit ich weiß kannst du ohne Form kein Control anzeigen lassen.
    vb-paradise.de/index.php/User/27263-DerSmurf/

    DerSmurf schrieb:

    Wie übergebe ich denn dann (bei UCs die ich im Designer auf die Form packe) die Datenquelle der Bindingsource auf dem UC?

    und da wär schon mein Problem. Wenn ich das richtig beurteile hast du dann Zich Bindingsources im Designer auf der MainForm rumfliegen, die Liste unten würde wohl endlos lang werden. Für jede Tabelle gibt's ne Bindingsource, wenn man dann noch Comboboxen hat, die gebunden sind
    gibt's dazu dann noch eine usw... das ist bei Mdi schöner, auf der Form (dem Child) hat man nur die Bindingsources, die dort auch gebraucht werden.



    Das Rüberschieben der Daten von einem alten in das neue DataSet funktioniert. Vorausgesetzt du kennst die Spalten und deren Datentypen ganz genau,
    dann kannst du dein altes Programm als Projekt mit in die Mappe schmeißen. Du musst dann dein altes DataSet greifbar machen Dim dtsold = New Altes_Projekt.Datasetname und dann musst du
    Tabelle für Tabelle durchcoden.

    Also sowas wie

    VB.NET-Quellcode

    1. For Each rw in dtsold.tabelle
    2. dtsnew.tabelle.addtabellerow(rw.parameter,....)
    3. Next


    Ist sehr aufwändig, aber funktioniert. Beim Durchtesten hab ich das immer so gemacht, dass ich vor dem ganzen Import das neue DataSet leergemacht hab mit
    dtsnew.clear() und danach abspeichern. An den alten Daten machst du in dem Moment ja nix, zur Sicherheit ein Backup der XML-Datei machen

    Also ich hab den ganzen Aufwand durch, als ich meine 2.0-Version meines Programms mit saubererem Code und bereinigtem DataSet damals gebaut hab ;)
    Und ich war auch der Typ mit dem TabbedMdi-Gedöns. Gefällt mir persönlich besser als TabControl mit UserControls drauf, aber ist wohl Geschmackssache. Die Logik wäre
    soweit durchprogrammiert bis auf einen kleinen Bug den ich momentan noch habe, dürfte bei dir aber weniger relevant sein. Der Bug taucht nur auf wenn ich nen Dialog innerhalb des Childs öffne,
    dann switcht er im Hintergrund auf das zuerst geöffnete Child - kann man zur Not auch mit leben
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

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

    DerSmurf schrieb:

    Und was meinst du @VaporiZed mit "MainBindingSource"? Eine BS bindet doch immer an EINE DataTable. Greife ich auf der UC auf mehrere DataTables zu, brauche ich doch mehrere Bindingsources?
    Eine BS bindet an eine Datenquelle. Das kann eine DataTable sein, kann aber auch ein tDS oder was anderes sein. Meine MainBS bindet an ein tDS, weitere BindingSources binden an die MainBS (-> weitereBS.DataSource = MainBS) und wählen dann den Teil der MainBS/des tDS aus, den die weitereBS anzeigen soll (indem man den DataMember festlegt). So wird alles automatisch umgestöpselt, sobald man die DataSource der MainBS neu setzt.
    Solution schau ich mir am Samstag an.

    tragl schrieb:

    Wenn ich das richtig beurteile hast du dann Zich Bindingsources im Designer auf der MainForm rumfliegen, die Liste unten würde wohl endlos lang werden. Für jede Tabelle gibt's ne Bindingsource, wenn man dann noch Comboboxen hat, die gebunden sind
    Nö. Im Idealfall gibt's nur eine MainBS, die das tDS als DataSource hat. Und die wird ans UC weitergegeben. Jedes UC hat dann genau die BindingSources, die stellvertretend für die anzuzeigende(n) Tabellle(n) da sind.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    tragl schrieb:

    hast du dann Zich Bindingsources im Designer auf der MainForm rumfliegen
    nö - genau das nicht.
    Die BindingSources sind da, wo sie gebraucht werden: Entweder auf den UserControls oder auf den MdiChildForms - wenn man damit arbeiten will.
    Also in diesem wesentlichen Punkt verhalten sich alle Ansätze gleich, ob nu Usercontrols oder MdiChilds, ob nu mit 1 MainBindingSource pro MdiChild/UC, oder mit Registrierungs-Extension.
    @DerSmurf: Wirf mal n Blick auf das Testprojekt, vielleicht ist dann klar, was ich meine. Beim Aufruf der SubForms werden nur MainBS und tDS des SubForms gesetzt, die anderen BindingSources bleiben unangetastet, weil sie an die MainBS gebunden sind und damit automatisch aktualisiert werden. Würde man gar das direkte Zugreifen auf das tDS beim Anlegen neuer Datensätze über die MainBS laufen lassen, müsste man noch nicht mal die tDS-Instanz an die SubForm-tDS-Variable übergeben. Dann wäre die SubForm-tDS-Instanz nur für den Designer da. Aber auch das könnte man sogar überspringen, indem man in der SubForm-Designer.vb die DataSource der MainBS selber festlegt, siehe Datenweitergabe V2. Dann haben die SubForms gar keine eigene tDS-Instanz mehr und man läuft nicht Gefahr, mit der falschen tDS-Instanz zu hantieren. Legt man ein neues Form an, kann man einfach die MainBS aus einem anderen Form rüberkopieren/übernehmen und dann hat man auch das Editieren der NeuesForm.Designer.vb nicht.
    Dateien
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Danke @VaporiZed
    Ich glaube ich habs kapiert. Hier zur Sicherheit nochmal mit meinen Worten.
    Auf der SubForm erstelle ich eine MainBS, ohne, dass ich (im Designer) DataMember und DataSource angebe.null
    Das passiert in deinem Code (Datenweitergabe V2) in Zeile 39: Me.BsTds.DataSource = GetType(Datenweitergabe.Tds)
    Dann erstelle ich die Bindingsources, die ich brauche - deren DataSource ist meine MainBS und der DataMember ist das, was eben angezeigt werden soll.
    Beim Aufruf von Form oder UC - oder WasAuchImmer - weise ich dann der dort liegenden MainBS als Datenquelle das DataSet zu. Fertig.
    Das habe ich nun auf meinem UserControl so gemacht. Ich musste aber der MainBS erstmal manuell eine DataSource zuweisen, damit der Eintrag in der UCAdressenDesigner.vb auftaucht.
    Die automatisch erzeugte DtsHaupt Instanz? (das was da unten automatisch erzeugt wird, wenn man das Dts als DataSource auswählt), habe ich dannach gelöscht.

    Wenn das so stimmt habe ich noch eine (zwei :) ) Verständnissfrage(n):
    Auf der SubForm weist du der MainBS eine DataSource zu: [tt]Me.BsTds.DataSource = GetType(Datenweitergabe.Tds)[/tt] nämlich das DataSet der Anwendung. (aus dem Grund den ich oben erwähnt habe?)
    Beim Aufruf dieser Sub, weist du der dortigen MainBS auch eine DataSource zu Dialog.BsTds.DataSource = Tds nämlich das DataSet auf der frmMain.
    Aber das DataSet auf der FrmMain ist doch das gleiche, wie das DataSet der Anwendung. Warum bleibt das DGV auf der SubForm leer, wenn ich Dialog.BsTds.DataSource = Tds auskommentiere?
    Der Verweis aufs DataSet ist doch (eigentlich) im SubFormDesigner vorhanden.

    Ich habe in meiner Demoanwendung jetzt die UCAdressen im Designer auf die TabPage geschmissen.
    Aufgerufen wird das ganze dann wie folgt:

    VB.NET-Quellcode

    1. UcAdressen.BSMain.DataSource = DtsDaten
    2. Me.TCHaupt.SelectedTab = TPAdressen

    Meint ihr das so?

    Und da es ja jetzt Sinn macht sich meine Solution anzuschauen, nochmal die Bitte:

    DerSmurf schrieb:

    Bitte schaut mal über meinen Ansatz, besonders in Punkto Sortierung des Zeugs in der Solution, Benennung, Datenmodell / Übergabe, und eben dem "Einsatz" der UC.


    Edit: und dann noch einmal die Frage nach UserControl, oder MdiChild.
    Also was ich nun glaube zu wissen ist, dass es in jedem Fall schonmal besser ist, den Code Klassenweise zu sortieren, als einfach alles in die frmMain zu schmeißen.
    Also ist sowohl eine Lösung mit USerControls (eingebaut in einem TabControl), als auch eine MDIChild Lösung besser, als eine TabControl und aller Code in die Mainform.
    Die UserControl Lösung lässt sich relativ leicht umsetzen, beim MDIChild Modell habe ich halt MDIChild Gedöns (oder ich lebe mit hunderten Fenstern in Fenstern - was wohl eine Qual wäre). Das würde mir ja aber @tragls Code abnehmen.
    Hat dann nicht MDI den Vorteil, dass ich die Forms die ich gerade nicht brauche, dispose?
    Also wenn ich mir ne Adresse suche und dann einen Artikel bearbeite, ist es doch bei MDI so, dass ich die AdressenForm nach nicht mehr brauchen quasi "schließe".
    Bei UserControls habe ich doch (wie bei meiner Erstlösung jetzt - mit aller Code in die MainForm), quasi den gesamten Code offen?

    Und worfür ist MDIChild gedacht? Wenn ich eine Lösung von @tragl benötige, um es einsetzen zu können?
    Gibt es tatsächlich Anwendungen mit Fenstern in Fenstern um Fenster hinter Fenstern unter Fenstern?
    Dateien
    • Theo01.zip

      (26,4 kB, 70 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DerSmurf“ ()

    DerSmurf schrieb:

    Meint ihr das so?
    Jou, so meinte ich das. Ja, bei der ersten MainBS muss man selber die DataSource festlegen. Man kann das entweder flink in der ersten Form.Designer.vb machen (und später diese MainBS zu neuen Forms rüberkopieren) oder umständlich über den Designer mit zig Klicks (DataSource [v] -> Projektdatenquelle hinzufügen … -> Objekt -> Theo-Theo-DtsDaten)

    DerSmurf schrieb:

    Hat dann nicht MDI den Vorteil, dass ich die Forms die ich gerade nicht brauche, dispose?
    Ich glaube nicht, dass das eine große Performancerelevanz hat. Aber probier es und berichte. Da ich (noch?) SubForm-Dialog-Erzeuger-Programmierer bin, kann ich mich dazu aber nicht qualifiziert mit Erfahrung äußern.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    Ich glaube nicht, dass das eine große Performancerelevanz hat. Aber probier es und berichte.

    Nunja. Aktuell habe ich auf der FrmMain ein TabControl und ca. 5.500 Zeilen Code in dieser Form.
    Performance Probleme gibt es keine. Also vermute ich, dass ich keinen Unterschied feststellen kann, bzw. der Unterschied so marginal ist, dass er in der Praxis irrelevant ist.
    Mir geht es um die Sauberkeit des Codes.
    Zwar habe ich ihn mit UCs Klassenweise getrennt, aber getrennt habe ich ihn jetzt (mit #Regions) auch.
    Wo ist dann der Vorteil einer UC Lösung?
    Ich habe vor mein Programm neu zu erstellen, weil man Code halt trennen sollte. (Lese ich zumindest immer wieder). Aber ich verstehe nicht so ganz wozu.
    Regions ist für mich Augenwischerei.
    Du bist nun beim SRP. Stell Dir vor, dass Du an Deinem Adresseditor irgendwas machen musst. Wenn Du alles in einem Form hast, musst Du alle Stellen im Form durchsuchen, die da relevant sein könnten. Wenn Du Verkaufsartikel bearbeiten müsstest (Darstellung, Zusatzinfos, …) das gleiche Spielchen. Wenn Du die Angelegenheiten der Adressdaten in eine eigene Klasse auslagerst, musst Du nur diese Klasse nachbearbeiten. Der Rest bleibt unberührt. Das mit der Aufteilung in UCs/MDI-Children usw. ist aber nur der Anfang. Ziel sollte eigentlich sein, dass die UCs/Forms nur die Datenweitergabe organisieren, also Usereingaben verarbeiten (Daten gehen vom User über das GUI and die Datenklasse) und Daten darstellen (Datenklasse->User). Die Datenklassen selber sollten sich um die Datenverarbeitung und sog. Geschäftslogik (business logic) kümmern. Ein Ziel, um das zu erreichen wäre, diese Geschäftslogik in eine DLL auszulagern. Das würde 2 Dinge fördern: Man muss sich ernsthafte Gedanken um die Entkopplung zwischen Daten und GUI machen und man könnte (rein diuretisch) ein anderes GUI (Konsole? WPF?) an die Datenklassen/-DLL koppeln und so flexible Programme erstellen, die unabhängig von einem GUI-System sind. Dann hast Du einen sehr großen Schritt geschafft. Solange aber viel business logic in Formklassen drinsteckt, bleibt man da ein stückweit hängen und man wird sich gar nicht der klaren Aufräummöglichkeiten bewusst.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    OK das leuchtet mir ein.
    Rätst du mir denn eher bei meinem Vorhaben zu bleiben. Also den Code (mit einigen - notwendingen - Verbesserungen am Code selbst) in UCs Auslagern, aber (erstmal) einen großen Teil der Business Logik in eben diesen UCs zu lassen.
    Dann aber mit dem Ziel die SRP Richtlinien? später zu erfüllen.
    Oder das ganze von Anfang an "korrekt" zu machen?
    Mein Ziel ist es am Ende ein Programm zu haben, welches ich für Geld anbieten könnte (was ich in keinster Weise vorhabe). Es soll nur "gescheit" sein. Dabei mit dem Hintergrund möglichst viel bei der Erstellung zu lernen.
    Dabei habe ich überhaupt keine Eile, denn das Programm was ich hier erstelle gibt es ja bereits und es läuft 1A. Hier wird nur die Weiterentwicklung (wegen komischer Benennung und teils merkwürdigem DataSet) schwierig.
    Und wenn ich immer weiter komsicchen Code erweitere, wirds ja nicht sauberer...

    Und könntest du bitte nochmal über meinen Post Nr. 12 schauen? Ich glaube ich habe ein bisschen viel rum editiert. Da sind ein Paar Fragen untergegangen:
    Spoiler anzeigen
    Wenn das so stimmt habe ich noch eine (zwei ) Verständnissfrage(n):
    Auf der SubForm weist du der MainBS eine DataSource zu: Me.BsTds.DataSource = GetType(Datenweitergabe.Tds) nämlich das DataSet der Anwendung. (aus dem Grund den ich oben erwähnt habe? - Auswählbarkeit der Folgenden BS)
    Beim Aufruf dieser Sub, weist du der dortigen MainBS auch eine DataSource zu Dialog.BsTds.DataSource = Tds nämlich das DataSet auf der frmMain.
    Aber das DataSet auf der FrmMain ist doch das gleiche, wie das DataSet der Anwendung.
    Warum bleibt das DGV auf der SubForm leer, wenn ich Dialog.BsTds.DataSource = Tds auskommentiere?
    Der Verweis aufs DataSet ist doch (eigentlich) im SubFormDesigner vorhanden.

    Spoiler anzeigen
    Und worfür ist MDIChild gedacht? Wenn ich eine Lösung von @tragl benötige, um es einsetzen zu können?Gibt es tatsächlich Anwendungen mit Fenstern in Fenstern um Fenster hinter Fenstern unter Fenstern?

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

    Ein Stolpern nach dem anderen. Dass Du Deine Codes jetzt in UCs aufteilst, ist ein guter Anfang. Das mit den DLLs ist ein (weiter entferntes mögliches) Ziel für später.

    DerSmurf schrieb:

    Auf der SubForm weist du der MainBS eine DataSource zu: nämlich das DataSet der Anwendung.
    Nein! Das ist nicht die tDS-Instanz, sondern (GetType!) der Datentyp. Aber noch keine konkrete Instanz selbst. Mit dieser Typzuweisung weiß aber erstmal die BS und der FormDesigner, was da später für eine Sache drinstecken soll. Welche tDS-Instanz dann drinsteckt, musst Du später selbst festlegen, eben mit UcAdressen.BSMain.DataSource = DtsDaten.
    Aus Textblock#2 ziehe ich mir mal die Frage raus:

    DerSmurf schrieb:

    worfür ist MDIChild gedacht?
    m.E. für ein Programm, welches mit mehreren Dokumenten gleichzeitig arbeitet. Also Paint.NET, welches mehrere Bilddateien "gleichzeitig" anzeigt. Ich glaub auch: frühere MS-Office-Apps. Aber MS ist davon weg. Jedes neue Word-Dokument wird in einer eigenen Word-Instanz geöffnet. Genauso bei Excel.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    (GetType!) der Datentyp

    Ouch. Sorry! Ich hab ja die Antwort auf meine Frage mit "GetType" selbst in den Code geschrieben :)

    Also befasse ich mich jetzt erstmal ernsthaft mit CCD (da kann ich ja bestimmt trotzdem schon was mitnehmen) und halte an meinem Plan fest.
    Ich kann ja evtl. schonmal anfangen aufwendige Aufgaben (z.B. das Exportieren auswählbarer Spalten aus dem Dts) "auszulagern". Aber das wird sich ja beim Programmieren ergeben.

    Hattest du schon Zeit über meine Solution zu schauen? Und gibt es da was zu meckern?

    Edit: und würdest du mir das auf CCD empfohlene Buch ebenfalls empfehlen?
    Deine Solution hatte ich angesehen.

    VB.NET-Quellcode

    1. If Not Directory.Exists(My.Application.Info.DirectoryPath & "\Daten") Then
    2. 'Wenn nicht - erstellen
    3. Directory.CreateDirectory(My.Application.Info.DirectoryPath & "\Daten")
    4. End If

    Lass die Bedingung weg und schau Dir die Quickinfo von CreateDirectory nochmal an ;)

    Ein anderer CCD-Teil sagt: In einer Methode entweder Methodenaufrufe oder Anweisungen. Dein FormLoad ist vermischt. Schieb den TCHaupt-Manipulierteil in eine Methode namens z.B. HideTabControlHeaders oder so. Denn ansonsten könntest Du die eine Codezeile von DTSLaden auch in den EventHandler verfrachten. Ich bin ein Fan von: Tell what, not how. Keine Ahnung, ob diese Worte schon jemand Berühmtes bzgl. Code gesagt hat oder ob sie überhaupt englisch-korrekt sind, aber ich will damit sagen: Der Code-Leser sollte wissen, was passiert, nicht sofort wie. Wenn er sich für die Details interessiert, kann er sich die entsprechend benannte Methode HideTabControlHeaders ansehen. Oder er weiß: »Ok, laut dem Methodennamen werden die TabControlHeader irgendwie versteckt. Das reicht mir schon zu wissen, interessiert mich nicht weiter.«

    Sonst passiert ja im Projekt nicht viel. Daher keine weiteren Aussagen.

    Najut: Den ewigen Disput zwischen denjenigen, die Tabellen im Singular und denjenigen, die Tabellen im Plural benennen, setze ich nicht nochmal fort. Die einen so, die anderen so.

    DerSmurf schrieb:

    das auf CCD empfohlene Buch
    8| Bei CCD wird viel Literatur empfohlen. Oder meinst Du Clean Code von Uncle Bob? Das hab ich bei mir stehen. Ist schon ziemlich interessant und hilfreich. Obwohl ich bis heute nicht durch den praktischen Refactoring-Teil durchgestiegen bin. Vielleicht nochmal ein Grund, den mir reinzuziehen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    OK, alles kapiert. Ich mach mich mal ans Werk.
    Wenn meine Adressverwaltung fertig ist gebe ich laut, und dann darf gemeckert werden :)

    Allerdings habe ich mir - nach dem Lesen der CCD Seite - (in Gedanken) das orangene Armbändchen mal wieder in die Schublade gelegt und mir das rote angelegt - Stichwort IOSP...

    VaporiZed schrieb:

    Oder meinst Du Clean Code von Uncle Bob

    das meine ich. Finds ganz angenehm echte Bücher - ohne beleuchteten Hintergrund - in der Hand zu haben.
    Ich glaube das könnte mir sehr weiterhelfen.