Hallo Leute,ich bin jetzt soweit, dass ich die Funktionsweise meines Frameworks erläutern und ein funktionstüchtiges Beispiel liefern kann.
Folgende grundlegende Kenntnisse sind erforderlich:
- Unterscheidung von Klassen, Modules, Structures, etc.
- Vererbung und abstrakte Basisklassen
- SQL-Syntax
- System.Reflections
- MSSQL-Server (wird für das angehängte Projekt vorausgesetzt)
Außerdem werden folgende Punkte behandelt:
- Cryptography
- SQL-Adapter
- DataModelling
- Borderless Formdesign & Control-Design
- JSON / XML-Serialisierung
Auf vielfachen Wunsch eines Einzelnen selbstverständlich mit Option Strict On (kann sein, dass ich das manchmal vergessen habe, aber an den relevanten Stellen müsste ich das überall berücksichtigt haben). Ich werde in diesem Thread allerdings nicht auf den Code im Einzelnen eingehen, sondern nur das Programmverhalten erläutern. Alles weitere dann in der darauf folgenden Diskussion.
Anders als zuvor angekündigt, lade ich nicht mein eigenes Framework hoch, da das einfach den Rahmen sprengen würde. Ich habe ein komplett neues sehr schlichtes Framework geschrieben und allen für die Erklärung unnötigen Code weggelassen (beispielsweise Custom-Buttons im FunctionPanel, Interfaces, komplexe Vererbungsstrukturen, aufwendige Designs, Serverkomponente, etc.).
Okay, let's go.
Kommen wir zunächst einmal zur Klassenstruktur (Abbildung 1). In der Grafik seht ihr die Zugriffshierarchie der einzelnen Klassentypen untereinander. Jedem Klassentyp liegt eine Basisklasse zugrunde, die das generelle einheitliche Programmverhalten enthält, sodass die geerbte Klasse ausschließlich die Kernaufgaben übernimmt für die sie zuständig ist. Allgemein formuliert: Ich programmiere ungern eine Funktion zweimal wenn ich sie auch in die Basisklasse schieben und an zwei Masken vererben kann. Ein Beispiel zur Aufteilung der Arbeit findet ihr in Abbildung 2.
Form
Die Aufgabe der Form beschränkt sich auf das direkte Control-Handling. Die Maske selbst enthält keine Business-Logik. Die Idee ist letztendlich Anzeige, Daten und Data-Handling strikt zu trennen. Generelle Funktionen und Controls werden in der Basisform definiert. Das FunctionPanel kann natürlich um weitere Funktionen erweitert werden, wie beispielsweise eine Suchfunktion oder verschiedene Aufrufe anderer Masken (Im Projekt der Einfachheit halber weggelassen).
Viewmodel
Das Viewmodel enthält die freie, maskenbezogene Business-Logik. Datengebundene Businesslogik wird wiederrum in eine BusinessIntelligence-Klasse (im Projekt nicht implementiert, da nicht benötigt) ausgelagert, damit sie in mehreren Masken unabhängig verfügbar ist. Generelles Programmverhalten wird aus der Basisklasse des Viewmodels vererbt. Hierzu zählen Navigation und generelle Maskenfunktionen wie Speichern, Löschen und Neuerstellen, sowie die Rechte um die Buttons im Viewmodel nötigenfalls zu sperren.
ViewElement
Das ViewElement enthält eine 1:1 Abbildung der Maske in Form von einer Property die den Wert des Controls enthält. Für das Databinding ist es erforderlich das Control und Property denselben Namen haben. Das Binding wird in der Basisklasse des Viewmodels gesetzt und beim Wechsel des ActiveElements entfernt und neu gesetzt.
Access-Klassen
Access-Klassen enthalten die Logik für das Datahandling einer SQL-Tabelle mittels bestimmter Filter, die als Parameter an die Methoden übergeben werden.
DataModel
Ein Datamodel ist eine 1:1 Abbildung einer SQL-Tabelle und stellt die SQL-Tabelle als Objekt in der Application zur Verfügung. Dieses kann beliebig modifiziert werden, ändern die Produktivdaten auf dem SQL aber erst dann, wenn der User auf Speicher klickt.
Sonstiges
Cryptography
Wie bereits mehrfach hier im Forum gelesen, wird häufig die Frage gestellt, wohin mit dem Private Key oder dem Kennwort, wenn ich Daten chiffriert habe. Ich habe hier eine Methode drin, die einen PrivateKey generiert und zur Aufbewahrung in einen RSA-Container verschiebt. Dieser kann dann durch die Applikation ausgelesen, gelöscht und neu generiert werden. Für das Abspeichern der SQL-Verbindungsdaten nutze ich die Generierung eines Private Keys den ich dann aus Kennwort für eine TripleDES-Verschlüsselung verwende.
SQL-Adapter
Die Projektmappe enthält auch eine SQL-Adapterklasse, die mir einen schnellen Zugriff auf einen MSSQL-Server ermöglicht. Beispiele für die Nutzung des Servers findet ihr beispielsweise in den Accessklassen.
Borderless Form-Design
Ich habe ein Beispiel beigefügt wie man eine Form mit
Control-Design
Mit dem Control-Design verhält es sich ähnlich. Er gibt eine Basisklasse, von der geerbt wird und die die von Control zu Control wiederkehrende Logik enthält. Das eigentliche Control enthält dann nur noch eine eigenes Design und Controlspezifisches Verhalten.
XML-Serialisierung
Hierzu habe ich bereits ein Tutorial verfasst, bedarf also keiner weiteren Erklärung. Ein Beispiel für die serialisierbare Klasse findet ihr in der RSAKeyValue-Klasse.
Ich freue mich auf eine muntere Diskussion und eine rege Beteiligung eurerseits, natürlich den Forenregeln konform hier nur in direktem Bezug auf das Tutorial. Bei Bedarf schreibt mich an dann eröffne ich ggf. einen eigenen Thread dafür wo wir sonstige Ideen diskutiert werden können.
Gruß Yanbel
EDIT: @ErfinderDesRades hat mich noch auf eine wichtige Sache aufmerksam gemacht: Ihr müsst Datenbankseitig nichts erstellen, konfigurieren oder einpflegen. Das macht das Programm alles von alleine. Danke für den Hinweis.
die Farbe Rot ist der Moderation vorbehalten und wurde ersetzt ~VaporiZed
Folgende grundlegende Kenntnisse sind erforderlich:
- Unterscheidung von Klassen, Modules, Structures, etc.
- Vererbung und abstrakte Basisklassen
- SQL-Syntax
- System.Reflections
- MSSQL-Server (wird für das angehängte Projekt vorausgesetzt)
Außerdem werden folgende Punkte behandelt:
- Cryptography
- SQL-Adapter
- DataModelling
- Borderless Formdesign & Control-Design
- JSON / XML-Serialisierung
Auf vielfachen Wunsch eines Einzelnen selbstverständlich mit Option Strict On (kann sein, dass ich das manchmal vergessen habe, aber an den relevanten Stellen müsste ich das überall berücksichtigt haben). Ich werde in diesem Thread allerdings nicht auf den Code im Einzelnen eingehen, sondern nur das Programmverhalten erläutern. Alles weitere dann in der darauf folgenden Diskussion.
Anders als zuvor angekündigt, lade ich nicht mein eigenes Framework hoch, da das einfach den Rahmen sprengen würde. Ich habe ein komplett neues sehr schlichtes Framework geschrieben und allen für die Erklärung unnötigen Code weggelassen (beispielsweise Custom-Buttons im FunctionPanel, Interfaces, komplexe Vererbungsstrukturen, aufwendige Designs, Serverkomponente, etc.).
Okay, let's go.
Kommen wir zunächst einmal zur Klassenstruktur (Abbildung 1). In der Grafik seht ihr die Zugriffshierarchie der einzelnen Klassentypen untereinander. Jedem Klassentyp liegt eine Basisklasse zugrunde, die das generelle einheitliche Programmverhalten enthält, sodass die geerbte Klasse ausschließlich die Kernaufgaben übernimmt für die sie zuständig ist. Allgemein formuliert: Ich programmiere ungern eine Funktion zweimal wenn ich sie auch in die Basisklasse schieben und an zwei Masken vererben kann. Ein Beispiel zur Aufteilung der Arbeit findet ihr in Abbildung 2.
Form
Die Aufgabe der Form beschränkt sich auf das direkte Control-Handling. Die Maske selbst enthält keine Business-Logik. Die Idee ist letztendlich Anzeige, Daten und Data-Handling strikt zu trennen. Generelle Funktionen und Controls werden in der Basisform definiert. Das FunctionPanel kann natürlich um weitere Funktionen erweitert werden, wie beispielsweise eine Suchfunktion oder verschiedene Aufrufe anderer Masken (Im Projekt der Einfachheit halber weggelassen).
Viewmodel
Das Viewmodel enthält die freie, maskenbezogene Business-Logik. Datengebundene Businesslogik wird wiederrum in eine BusinessIntelligence-Klasse (im Projekt nicht implementiert, da nicht benötigt) ausgelagert, damit sie in mehreren Masken unabhängig verfügbar ist. Generelles Programmverhalten wird aus der Basisklasse des Viewmodels vererbt. Hierzu zählen Navigation und generelle Maskenfunktionen wie Speichern, Löschen und Neuerstellen, sowie die Rechte um die Buttons im Viewmodel nötigenfalls zu sperren.
ViewElement
Das ViewElement enthält eine 1:1 Abbildung der Maske in Form von einer Property die den Wert des Controls enthält. Für das Databinding ist es erforderlich das Control und Property denselben Namen haben. Das Binding wird in der Basisklasse des Viewmodels gesetzt und beim Wechsel des ActiveElements entfernt und neu gesetzt.
Access-Klassen
Access-Klassen enthalten die Logik für das Datahandling einer SQL-Tabelle mittels bestimmter Filter, die als Parameter an die Methoden übergeben werden.
DataModel
Ein Datamodel ist eine 1:1 Abbildung einer SQL-Tabelle und stellt die SQL-Tabelle als Objekt in der Application zur Verfügung. Dieses kann beliebig modifiziert werden, ändern die Produktivdaten auf dem SQL aber erst dann, wenn der User auf Speicher klickt.
Sonstiges
Cryptography
Wie bereits mehrfach hier im Forum gelesen, wird häufig die Frage gestellt, wohin mit dem Private Key oder dem Kennwort, wenn ich Daten chiffriert habe. Ich habe hier eine Methode drin, die einen PrivateKey generiert und zur Aufbewahrung in einen RSA-Container verschiebt. Dieser kann dann durch die Applikation ausgelesen, gelöscht und neu generiert werden. Für das Abspeichern der SQL-Verbindungsdaten nutze ich die Generierung eines Private Keys den ich dann aus Kennwort für eine TripleDES-Verschlüsselung verwende.
SQL-Adapter
Die Projektmappe enthält auch eine SQL-Adapterklasse, die mir einen schnellen Zugriff auf einen MSSQL-Server ermöglicht. Beispiele für die Nutzung des Servers findet ihr beispielsweise in den Accessklassen.
Borderless Form-Design
Ich habe ein Beispiel beigefügt wie man eine Form mit
FormBorderStyle = None
funktionsbereit macht. Sie ist sehr schlicht gehalten und kann an einigen Stellen (Resizing) durchaus verbessert werden. Seht es nur als Beispiel, das ich auf die Schnelle nachgezogen habe, denn die Forms die ich normalerweise designe, sind geringfügig aufwendiger. Die kann ich hier allerdings nicht implementieren, da die Designklassen zu umfangreich sind und das zentrale Thema dadurch verfehlt wird. Das wäre etwas für ein weiteres Tutorial. Control-Design
Mit dem Control-Design verhält es sich ähnlich. Er gibt eine Basisklasse, von der geerbt wird und die die von Control zu Control wiederkehrende Logik enthält. Das eigentliche Control enthält dann nur noch eine eigenes Design und Controlspezifisches Verhalten.
XML-Serialisierung
Hierzu habe ich bereits ein Tutorial verfasst, bedarf also keiner weiteren Erklärung. Ein Beispiel für die serialisierbare Klasse findet ihr in der RSAKeyValue-Klasse.
Ich freue mich auf eine muntere Diskussion und eine rege Beteiligung eurerseits, natürlich den Forenregeln konform hier nur in direktem Bezug auf das Tutorial. Bei Bedarf schreibt mich an dann eröffne ich ggf. einen eigenen Thread dafür wo wir sonstige Ideen diskutiert werden können.
Gruß Yanbel
EDIT: @ErfinderDesRades hat mich noch auf eine wichtige Sache aufmerksam gemacht: Ihr müsst Datenbankseitig nichts erstellen, konfigurieren oder einpflegen. Das macht das Programm alles von alleine. Danke für den Hinweis.
die Farbe Rot ist der Moderation vorbehalten und wurde ersetzt ~VaporiZed
Ein Computer wird das tun, was du programmierst - nicht das, was du willst.
Dieser Beitrag wurde bereits 19 mal editiert, zuletzt von „Yanbel“ ()