Frage zu Parametern

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von River_S0ng.

    Frage zu Parametern

    Hallo zusammen,
    zuerst einmal ich bin neu hier und auch noch recht unerfahren mit VB.NET.
    Ich arbeite seit ein paar Monaten an einem Projekt, bei dem ich ein Programm von einer Monolith-Struktur (das Programm hat jemand anders geschrieben) in eine vernünftige Architektur umstelle. Das verteilen der Subroutinen/Funktionen habe ich grob so gemacht:
    Eine Solution mit den Projekten "Gui", "Logic", "Data" und "Shared". Gui kann auf alles zugreifen, Logic kann auf Data und Shared zugreifen, Data kann nur auf Shared zugreifen und Shared kann auf gar nix zugreifen.

    So weit, so gut. Probleme gibt es jetzt aber, wenn Subroutinen in Logic und Data mit Werten arbeiten, die in Gui generiert werden (z.B. will Sub1 aus Data mit einem SelectedListViewItem aus Gui arbeiten).
    Ich kann hier ja mit Parametern arbeiten (also Sub1 in Data arbeitet mit Parameter1 und wenn in Gui Sub1 ausgeführt wird, wird der Wert dann dort übergeben), aber das wurde mir jetzt ziemlich schnell ziemlich unübersichtlich. Wenn Sub1 aus Data Parameter1 benutzt, Sub1 aber nur in Sub2 aus Logic benötigt wird und Sub2 dann in Sub3 in Gui benutzt wird muss ich den Parameter1 bis zu Gui mitschleppen. Packt noch ein paar Subs und Parameter dazu und die Fehler werden mehr statt weniger.

    Ich hoffe, das hat man jetzt verstanden. Ich möchte wissen, ob ich wirklich den/die Parameter bis zu Gui mit schleppen muss oder ob es eine bessere Lösung gibt.

    Dankeschön und Viele Grüße

    River_S0ng schrieb:

    recht unerfahren mit VB.NET (...)

    (...)in eine vernünftige Architektur umstelle(...)


    Sorry, aber das hört sich irgendwie nicht sinnvoll an. Um die Architektur eines Programms sinnvoll umstellen zu können muss man schon fit sein...
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Ich komm nicht mehr ganz hinterher. Zuviele allgemeine Namen. Gib mal ein konkretes Beispiel aus dem Code, vielleicht ist da nur ein Architektur-Denkfehler drin. Klar ist es anfangs schwierig, nicht alles in die GUI-Klasse zu packen, sondern die Aufgaben auf einzelne Klassen zu verteilen, während die GUI-Klasse die einzelnen Objekte "nur" managed. Aber vielleicht wird's klarer, wenn Du konkret(er) wirst.
    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, ich versuchs mal:

    Diese Sub befindet sich in dem Projekt Data:

    VB.NET-Quellcode

    1. Public Shared Function CreateView_sql_zr_fragen_daten(ByVal SelectedItemsCreateView_sql_zr_fragen_daten As ListView.SelectedListViewItemCollection) As Boolean
    2. Dim intAnzahlDS As Integer = 0
    3. intAnzahlDS = CInt(SelectedItemsCreateView_sql_zr_fragen_daten(0).SubItems(3).Text)
    4. If intAnzahlDS <= 0 Then
    5. Return False
    6. End If
    7. End Sub


    Sie wird wiederum im Projekt Logic benutzt:

    VB.NET-Quellcode

    1. Public Shared Sub ChangeZeitreihenGruppierung(ByVal SelectedItemsCreateView_sql_zr_fragen_daten As ListView.SelectedListViewItemCollection)
    2. If Data.Main.ProgramData.CreateView_sql_zr_fragen_daten(SelectedItemsCreateView_sql_zr_fragen_daten) Then
    3. Data.Main.ProgramData.CreateView_sql_zr_frage_01()
    4. lblZeitreiheAusgewertetWurdeFolgende.Text = "Zeitreihe - Ausgewertet wurde folgende Einheit:"
    5. Data.Main.ProgramData.FillDiagrammVergleichNachFragen()
    6. End If
    7. End If
    8. End Sub


    Welches wiederum von dem Event in Gui (in der Klasse "Zeitreihe", die sich im gleichen Projekt wie "Auswertung" befindet) benutzt wird:

    VB.NET-Quellcode

    1. Private Sub optAuswertungZeitreihengruppierungTag_CheckedChanged(sender As Object, e As EventArgs) Handles optAuswertungZeitreihengruppierungTag.CheckedChanged
    2. If Me.Visible And optAuswertungZeitreihengruppierungTag.Checked Then
    3. Logic.ProgramLogic.Zeitreihe.ChangeZeitreihenGruppierung(SelectedItemsCreateView_sql_zr_fragen_daten := Auswertung.lstFragenEinheiten.SelectedItems)
    4. End If
    5. End Sub


    In der Klasse "Auswertung" ist also eine Liste, deren SelectedItem in Data gebraucht wird. Und jetzt schleppe ich die Parameter bis Gui, aber das hier ist nur ein Ausschnitt, die Verknüfung werden mehr und komplizierter. Deshalb wollte ich wissen, ob das überhaupt so Sinn macht und ob es einen besseren Weg gibt.
    Willkommen im Forum. :thumbup:

    River_S0ng schrieb:

    VB.NET-Quellcode

    1. intAnzahlDS = CInt(SelectedItemsCreateView_sql_zr_fragen_daten(0).SubItems(3).Text)
    Was passiert, wenn da "Roulade mit Klößen" drinne steht?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Klar. Aus der GUI kommen Werte die irgendwo verarbeitet werden. Diese müssen im schlimmsten Fall durch ettliche Klassen und Methoden geschoben werden. Man kann zwar mit „globalen Variablen und Methoden“ arbeiten (Stichworte: Shared, Modul), jedoch wird dies auch irgendwann unübersichtlich und ist auch nicht mehr so schön gekapselt wie man dies in der OOP gerne hätte. Evtl lsäst auch sich mit DataBinding was machen.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Das ist schon der vermutete Architektur- bzw. Design-Fehler.

    VB.NET-Quellcode

    1. Public Shared Function CreateView_sql_zr_fragen_daten(ByVal SelectedItemsCreateView_sql_zr_fragen_daten As ListView.SelectedListViewItemCollection) As Boolean
    2. '...
    3. intAnzahlDS = CInt(SelectedItemsCreateView_sql_zr_fragen_daten(0).SubItems(3).Text)
    4. '...

    Die Projekte Logic und Data sollten eben nicht irgendwelche GUI-Pakete bekommen und diese auseinanderpuhlen, sondern mit allgemeinen Daten arbeiten. Stell Dir vor, dass jemand entscheidet, dass aus dem ListView ein DGV wird. Oder dass eine Datenspalte dazukommt. Was sollte geändert werden? Nur die GUI-Klasse. Aber was must Du ändern? Unter anderen auch die Data-Klasse. Und das sollte man vermeiden. Denn sonst bekommt man wirre Abhängigkeiten, die man nicht mehr managen kann. Von daher: Wenn Du eh nur von all den SelectedListViewItems nur einen winzigen Teil von einem brauchst, dann übergibt doch den gleich von der Logic-Klasse an die Data-Klasse:
    CreateView_sql_zr_fragen_daten(SelectedItemsCreateView_sql_zr_fragen_daten(0).SubItems(3).Text)
    Und davor natürlich den ListView-unabhängigen Teil von der GUI-Klasse an die Logic-Klasse.
    Dass die Logic-Klasse das GUI verändert, ist m.E. auch verkehrt. Dafür wäre die GUI-Klasse zuständig. Aus gleichem Grund. Ein Label umbenannt, schon muss man in der Logic-Klasse rumfuhrwerken.
    Snippet#2 ist unvollständig, da es einen If-Block, aber 2 End Ifs gibt. Aber wurscht.
    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 für die schnelle Antwort.
    Du hast recht, Logic und Data sollten nicht mit Daten aus Gui arbeiten, deshalb hab ich versucht, die Parameter als "Platzhalter" zu benutzen. Ich versteh das so, dass in Logic und Data in den Subroutinen Platzhalter für die Werte stehen und wenn die Sub in Gui benutzt wird, wird dort der Platzhalter durch den tatsächlichen Wert ersetzt.

    Nur zum Verständnis, ich habe ca. 30.0000 LOC und es geht nicht nur um SelectedItems, sondern auch um ganze Listen, aktivierte Buttons, angegebene Zahlenwerte, etc. Also bräuchte ich da eine "globalere" Lösung.

    Und ja, ich denke auch, dass die Logic-Klasse die Gui nicht verändern dürfen sollte. Dass das so ist, ist leider der ursprünglichen Monolith-Struktur geschuldet, da muss ich mir auch noch was einfallen lassen...
    Falls Du das nicht hauptberuflich machst: richte Dich darauf ein, dass eine ganze Zeit vergehen wird, bis Du durch bist. Ein Komplettumbau ist hart. Und wenn kein Neuanfang möglich ist, umso schwieriger, da man immer wieder testen muss, ob der Alt-Neu-Hybrid noch so läuft wie gewollt. Noch übler wird's, wenn Dein aktuelles Projekt im Einsatz ist, während Du Veränderungen daran vornimmst. Ich dachte bei meinen Projekten auch, dass das in vergleichsweise kurzer Zeit machbar ist. Haha :( Von wegen. Also rechne mal lieber mit "vermuteter Zeit mal 10", um einen realistischen Wert zu bekommen.
    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.
    @River_S0ng Da war noch eine Frage offen:

    RodFromGermany schrieb:

    Was passiert, wenn da "Roulade mit Klößen" drinne steht?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    @River_S0ng Da war noch eine Frage offen


    Tut mir leid, die Frage versteh ich nicht so ganz. Was von der Zeile willst du mit "Roulade mit Klößen" (ich krieg grad Hunger) ersetzen?

    @VaporiZed:
    Ich mach das zum Glück nicht hauptberuflich, mein Chef hat gefragt, ob ich das kann und ich hab gesagt, da krieg ich irgendwie hin... Blöd, ich weiß. Naja jetzt hab ich mir das eingebrockt, nun muss ichs auch durchziehen.

    *Vollzitat entfernt* ~NoFear23m

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Nofear23m“ ()

    River_S0ng schrieb:

    die Frage versteh ich nicht so ganz.
    Du konvertierst dort mit CInt(xx) einen String zu einem Integer.
    Wenn in diesem String zufällig "Roulade mit Klößen" drinne steht, knallt es gewaltig.
    Möglicherweise hast Du ja Vorsorge getroffen, dass da nur Zahlen drinne stehen können, aber auch "keine Zahl" knallt dann.
    Deswegen gibt uns .NET Methoden, die dies verhindern:
    Integer.TryParse(...) => docs.microsoft.com/de-de/dotne…e?view=netframework-4.7.2
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Du konvertierst dort mit CInt(xx) einen String zu einem Integer.
    Wenn in diesem String zufällig "Roulade mit Klößen" drinne steht, knallt es gewaltig.


    Ah ok, diesen Code hat der geschrieben, der den Monolith zu verantworten hat, nicht ich. Aber danke für den Hinweis, da muss ich wohl was korrigieren.

    *Vollzitat entfernt*
    Bitte @River_S0ng versuche die Vollzitate zu unterlassen. Danke ~NoFear23m

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

    River_S0ng schrieb:

    Deshalb wollte ich wissen, ob das überhaupt so Sinn macht und ob es einen besseren Weg gibt.
    Jo, aber das läüft evtl. auf Neu-Schreiben hinaus.

    Was bei dir höchst bedenklich ist, ist, dass zB ListViewItem - eine Gui-Klasse - bis hinunter in die Daten-Ebene verschleppt werden, und dann damit herumzufuchteln.
    Tatsächlich passiert da ja garnix - die LVIs werden durchgeguckt, und wenn was bestimmtes gefunden wird, wird True returnt.
    Das kann ja wohl nicht Sinn eines Data-Layers sein.

    Wie dem auch sei: Mir scheint, in deinem Programm gibt es kein Datenmodell. Folge dieses Mangels ist, dass Daten auf mehr oder weniger beliebige Weise in iwelche Controls gesteckt werden, wo sie nicht richtig hineinpassen.
    Etwa ein Person-Datensatz sollte Name (String), Geburtstag (Date), Gechlecht (ein Enum), ... enthalten.
    Stopfst du sowas in ein Listview, degenerieren alle Properties zu String, denn Listview kann nur String.

    Ich empfehle immer typisiertes Dataset als Datenmodell - da kann man die Datenklassen so anlegen, wie es der Wirklichkeit entspricht.
    Das mit den Datentypen ist ja nur das kleinste Problem, in Wirklichkeit hat eine Person ja eine oder mehrere Addressen. Wie willst du denn mehrere Addressen in deim Listview darstellen??
    Im typDataset ist solch kein Problem, im Gegenteil: dafür ist es da.

    Zum Datenmodell dazu gehört Databinding. Das ist eine Art Magie, mit der man es hinbekommt, dass die Controls immer den aktuellen Zustand der Datensätze anzeigen.
    Also ändere ich im Datensatz den Namen - wups! - wird auch im Datagridview der neue Name angezeigt.
    Und auch annersrum: Schreibe ich einen neuen Namen ins DGV - so ist er eingegeben, und man bekommt den neuen Namen heraus, wenn man ihn vom typDataset abruft.
    Databinding eben: Daten und Controls sind aneinander gebunden.

    Jetzt erst kannst du sinnvoll Daten und Oberfläche trennen, und dich drauf konzentrieren, mit den Daten zu arbeiten - ganz ohne an die Controls zu denken (die hopfen dann schon hinterher).

    Also für mich hat der Begriff "Schichten-Architektur" überhaupt erst Sinn bekommen, seit ich databinding-getrieben entwickel.
    Vorher waren alle Schichtungs-Versuche nur ein Krampf - siehst ja: deine "DatenSchicht" hampelt mit ListviewItems rum - also da lass die "Logik" lieber inne Gui-Schicht, dann ist wenigstens das LVI da wo es hingehört.

    Jo - ich hab ein Tut auf Deutsch mit viele Filme, um Eindruck zu schinden: vier Views-Videos

    Dasselbe Thema, aber auf englisch, und wesentlich sorgfältiger aufbereitet: codeproject.com/Articles/10309…l-Datamodel-for-Beginners
    Beachte, dass es sich um eine "Serie" von 3 Artikeln handelt.