kh-blazor-razor #66
@@ -5,10 +5,12 @@ gitea: none
|
||||
|
||||
## 1. Einleitung des individuellen Teils
|
||||
|
||||
In diesem Abschnitt wird meine persönliche Aufgabenstellung im Rahmen des Projektes (`Alumnihub`) beschrieben.
|
||||
In diesem Abschnitt wird meine persönliche Aufgabenstellung im Rahmen des Projektes (`Alumnihub`) beschrieben.
|
||||
|
|
||||
|
||||
### Auftrag / persönliche Aufgabenstellungen
|
||||
|
||||
Meine Zuständigkeiten und Verantwortlichkeiten:
|
||||
|
||||
- Product Owner
|
||||
- Infrastruktur
|
||||
- Entwicklung
|
||||
@@ -25,56 +27,61 @@ Lernen von ASP.NET und der Entwicklung mit Blazor und Oqtane. Ich habe Interesse
|
||||
- Use Cases
|
||||
|
||||
|
gitea-actions
commented
Stil/Grammatik: Kein Komma vor 'sowie'. 'Einfach' wirkt zudem etwas umgangssprachlich. Stil/Grammatik: Kein Komma vor 'sowie'. 'Einfach' wirkt zudem etwas umgangssprachlich.
```suggestion
Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module sowie das Bereitstellen der Services. Als Betriebssystem habe ich mich für Linux entschieden, da ich mit Linux im Serverumfeld die meisten und besten Erfahrungen gemacht habe.
```
|
||||
## 3. Technische Grundlagen
|
||||
Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, sowie das Bereitstellen des Services. Als Betriebssystem habe ich mich für Linux entschieden, einfach, da ich mit Linux im Serverumfeld die meisten und besten Erfahrungen gemacht habe.
|
||||
|
||||
(Diese Entscheidung wurde gemeinsam getroffen:)
|
||||
Auch steht die Wahl der Programmiersprache und des CMS an. Nachdem wir im Unterricht fast ausschließlich mit C# entwickelt haben und nicht in eine komplett unbekannte Entwicklungsumgebung abdriften wollten, haben wir uns für Webentwicklung mit ASP.NET Core 9 und (Upgrade im Lauf der Diplomarbeit auf .NET Core 10) dem CMS Oqtane entschieden. Auch hier gab es einige Kandidaten:
|
||||
Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, sowie das Bereitstellen des Services. Als Betriebssystem habe ich mich für Linux entschieden, einfach, da ich mit Linux im Serverumfeld die meisten und besten Erfahrungen gemacht habe.
|
||||
|
gitea-actions
commented
Grammatik und Stil: 'im Lauf' -> 'im Laufe'. '.NET Core 10' wird offiziell nur noch '.NET 10' genannt. Grammatik und Stil: 'im Lauf' -> 'im Laufe'. '.NET Core 10' wird offiziell nur noch '.NET 10' genannt.
```suggestion
Nachdem wir im Unterricht fast ausschließlich mit C# entwickelt haben und nicht in eine komplett unbekannte Entwicklungsumgebung abdriften wollten, haben wir uns für Webentwicklung mit ASP.NET Core 9 und (Upgrade im Laufe der Diplomarbeit auf .NET 10) dem CMS Oqtane entschieden. Auch hier gab es einige Kandidaten:
```
gitea-actions
commented
Grammatik/Stil: 'Laufe' statt 'Lauf'. 'Abdriften' ist sehr umgangssprachlich. Grammatik/Stil: 'Laufe' statt 'Lauf'. 'Abdriften' ist sehr umgangssprachlich.
```suggestion
Auch steht die Wahl der Programmiersprache und des CMS an. Nachdem wir im Unterricht fast ausschließlich mit C# entwickelt haben und nicht in eine komplett unbekannte Entwicklungsumgebung wechseln wollten, haben wir uns für Webentwicklung mit ASP.NET Core 9 und (Upgrade im Laufe der Diplomarbeit auf .NET Core 10) dem CMS Oqtane entschieden.
```
|
||||
|
||||
Auch steht die Wahl der Programmiersprache und des CMS an. Nachdem wir im Unterricht fast ausschließlich mit C# entwickelt haben und nicht in eine komplett unbekannte Entwicklungsumgebung abdriften wollten, haben wir uns für die Webentwicklung mit ASP.NET Core 9 (Upgrade im Lauf der Diplomarbeit auf .NET Core 10) und dem CMS Oqtane entschieden. Auch hier gab es einige Kandidaten:
|
||||
|
||||
- Piranha CMS
|
||||
|
gitea-actions
commented
Rechtschreibung: 'großen und ganzen' wird großgeschrieben. Rechtschreibung: 'großen und ganzen' wird großgeschrieben.
```suggestion
Viel Arbeit mit Partials, welche in der Admin Oberfläche geschieht, aber sehr gut dokumentiert. Im Großen und Ganzen wirkt Umbraco nicht so flexibel.
```
gitea-actions
commented
Rechtschreibung: 'Großen und Ganzen' wird großgeschrieben. Rechtschreibung: 'Großen und Ganzen' wird großgeschrieben.
```suggestion
Viel Arbeit mit Partials, welche in der Admin Oberfläche geschieht, aber sehr gut dokumentiert. Im Großen und Ganzen wirkt Umbraco nicht so flexibel.
```
|
||||
>Piranha erscheint auf den ersten Blick nicht so flexibel wie Oqtane, basiert auf .NET 8.0 und wird nicht so aktiv gewartet.
|
||||
> Piranha erscheint auf den ersten Blick nicht so flexibel wie Oqtane, es basiert auf .NET 8.0 und wird nicht so aktiv gewartet.
|
||||
- Umbraco
|
||||
|
gitea-actions
commented
Grammatik und Stil: 'Und ein Windows Server würde ich ich...' ist umgangssprachlich und enthält ein doppeltes Wort. 'kostet' ist redundant zu 'Lizenzkosten'. Grammatik und Stil: 'Und ein Windows Server würde ich ich...' ist umgangssprachlich und enthält ein doppeltes Wort. 'kostet' ist redundant zu 'Lizenzkosten'.
```suggestion
Platzhirsch. Bekannt, wird von der DNN Foundation gewartet. Arbeitet mit dem .NET Framework, welches nicht unter Linux läuft. Einen Windows-Server würde ich nicht einfach so im Internet betreiben, abgesehen von den anfallenden Lizenzkosten.
```
gitea-actions
commented
Grammatik/Syntax: 'einen Windows Server' (Akkusativ), Wortwiederholung 'ich ich' und ein fehlendes Verb wie 'stellen'. Grammatik/Syntax: 'einen Windows Server' (Akkusativ), Wortwiederholung 'ich ich' und ein fehlendes Verb wie 'stellen'.
```suggestion
Platzhirsch. Kennt man, wird von der DNN Foundation gewartet. Arbeitet mit dem Dotnet Framework, welches nicht unter Linux läuft. Und einen Windows Server würde ich nicht einfach so ins Internet stellen, abgesehen von den Lizenzkosten, die anfallen würden.
```
|
||||
>Viel Arbeit mit Partials, welche in der Admin Oberfläche geschieht, aber sehr gut dokumentiert. Im großen und ganzen wirkt Umbraco nicht so flexibel.
|
||||
> Viel Arbeit mit Partials, welche in der Admin Oberfläche geschieht, aber sehr gut dokumentiert. Im Großen und Ganzen wirkt Umbraco nicht so flexibel.
|
||||
- DNN / Dot Net Nuke
|
||||
>Platzhirsch. Kennt man, wird von der DNN Foundation gewartet. Arbeitet mit dem Dotnet Framework, welches nicht unter Linux läuft. Und ein Windows Server würde ich ich nicht einfach so ins Internet, abgesehen von den Lizenzkosten, die das kosten würde.
|
||||
> Platzhirsch. Kennt man, wird von der DNN Foundation gewartet. Arbeitet mit dem Dotnet Framework, welches nicht unter Linux läuft. Und ein Windows Server würde ich ich nicht einfach so ins Internet, abgesehen von den Lizenzkosten, die das kosten würde.
|
||||
- Oqtane
|
||||
|
gitea-actions
commented
Grammatik: Genitiv 'des Oqtane Frameworks'. Grammatik: Genitiv 'des Oqtane Frameworks'.
```suggestion
Am Ende haben wir uns für das Oqtane Framework trotz seiner schlechten Dokumentation entschieden.
```
|
||||
>Schlecht dokumentiert, auf den ersten Blick sehr modular und flexibel.
|
||||
> Oqtane wirkt auf den ersten Blick sehr modular und flexibel, die schlechte Dokumentation ist erst im Nachhinein aufgefallen.
|
||||
|
||||
Am Ende haben wir uns für das Oqtane Framework trotz seiner schlechten Dokumentation entschieden.
|
||||
Aufgrund seiner sehr hohen Flexibilität, haben wir uns am Ende für Oqtane entschieden.
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'implementiereung' -> 'Implementierung'. Rechtschreibung: 'implementiereung' -> 'Implementierung'.
```suggestion
2. Mit welcher speziellen Implementierung bekommen wir Support und haben Wissen im Team?
```
gitea-actions
commented
Rechtschreibung: 'Implementierung' großschreiben und korrekte Endung. Rechtschreibung: 'Implementierung' großschreiben und korrekte Endung.
```suggestion
2. Mit welcher speziellen Implementierung bekommen wir Support und haben Wissen im Team?
```
|
||||
Im Bereich der Datenbanken musste ich mir ein paar Fragen stellen.
|
||||
1. Auf welche Art Datenbank setzen wir? SQL, NoSQL, Graph, ...
|
||||
2. Mit welcher speziellen implementiereung bekommen wir Support und haben Wissen im Team?
|
||||
3. Ist das auserkorene System kompatibel mit dem CMS auf dem wir aufbauen?
|
||||
Im Bereich der Datenbanken musste ich mir ein paar Fragen stellen:
|
||||
|
||||
Es war von Anfang an klar, dass es ein SQL basiertes System wird, da wir im Team nur mit SQL-basierten Systemen erfahrungen haben. Außerdem unterstützt unser CMS (Oqtane) nur SQL basierte Systeme. In der Linuxwelt kommen jetzt nur noch ein paar Datenbanken in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem DBMS, welche ich im Nebenjob errungen habe.
|
||||
1. Auf welche Art Datenbank setzen wir? SQL, NoSQL, Graph, ...
|
||||
|
gitea-actions
commented
Rechtschreibung/Grammatik: 'erfahrungen' -> 'Erfahrungen', 'SQL basiertes' -> 'SQL-basiertes'. Rechtschreibung/Grammatik: 'erfahrungen' -> 'Erfahrungen', 'SQL basiertes' -> 'SQL-basiertes'.
```suggestion
Es war von Anfang an klar, dass es ein SQL-basiertes System wird, da wir im Team nur mit SQL-basierten Systemen Erfahrungen haben. Außerdem unterstützt unser CMS (Oqtane) nur SQL-basierte Systeme. In der Linuxwelt kommen jetzt nur noch ein paar Datenbanken in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem DBMS, welche ich im Nebenjob errungen habe.
```
gitea-actions
commented
Rechtschreibung: 'Erfahrungen' großschreiben. 'SQL-basiert' mit Bindestrich. Rechtschreibung: 'Erfahrungen' großschreiben. 'SQL-basiert' mit Bindestrich.
```suggestion
Es war von Anfang an klar, dass es ein SQL-basiertes System wird, da wir im Team nur mit SQL-basierten Systemen Erfahrungen haben. Außerdem unterstützt unser CMS (Oqtane) nur SQL-basierte Systeme. In der Linuxwelt kommen jetzt nur noch ein paar Datenbanken in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem DBMS, welche ich im Nebenjob errungen habe.
```
|
||||
2. Mit welcher speziellen Implementierung bekommen wir Support und bei welcher haben wir Vorwissen im Team?
|
||||
3. Ist das auserkorene System kompatibel mit dem CMS, auf dem wir aufbauen?
|
||||
|
||||
Es war von Anfang an klar, dass es ein SQL-basiertes System wird, da wir im Team nur mit SQL-basierten Systemen Erfahrungen haben. Außerdem unterstützt unser CMS (Oqtane) nur SQL-basierte Systeme. In der Linuxwelt kommen jetzt nur noch ein paar Datenbankmanagementsysteme in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem Datenbankmanagementsystem, welche ich in meinem Nebenjob errungen habe.
|
||||
|
||||
|
gitea-actions
commented
Stil: 'Webseiten' bezieht sich meist auf einzelne Seiten, 'Websites' oder 'Webauftritte' auf das gesamte System. Stil: 'Webseiten' bezieht sich meist auf einzelne Seiten, 'Websites' oder 'Webauftritte' auf das gesamte System.
```suggestion
Oqtane ist ein Framework und CMS zur Entwicklung von Websites mithilfe von ASP.NET und Blazor. [^5] Ein Oqtane-System besteht aus mehreren Komponenten.
```
|
||||
# Technologie
|
||||
|
||||
## Was ist Oqtane? Architektur von Oqtane?
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: Im Deutschen schreibt man eher 'Webseite'. Rechtschreibung: Im Deutschen schreibt man eher 'Webseite'.
```suggestion
Ein `Module` (Modul) soll neue Funktionalitäten in das CMS hinzufügen und ein `Theme` soll die ganze Gestaltung der Webseite (die Shell) festlegen. [^6]
```
|
||||
Oqtane ist ein Framework und CMS zur Entwicklung von Webseiten mithilfe von ASP.NET und Blazor. [^5] Ein Oqtane-System besteht aus mehreren Komponenten.
|
||||
|
||||
In dieser Diplomarbeit fokussieren wir uns hauptsächlich auf `Themes` und `Modules`, aber es gibt auch `Language Packs` und `Pure Extensions`. [^6]
|
||||
|
||||
Ein `Module` (Modul) soll neue Funktionalitäten in das CMS hinzufügen und ein `Theme` soll die ganze Gestaltung der Website (die Shell) festlegen. [^6]
|
||||
Ein `Module` (Modul) soll neue Funktionalitäten in das CMS hinzufügen und ein `Theme` soll die ganze Gestaltung der Webseite (die Shell) festlegen. [^6]
|
||||
|
||||
[^5]: https://www.oqtane.org/#about
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'Inferfaces' -> 'Interfaces', 'Client-Staruplogik' -> 'Client-Startuplogik'. Rechtschreibung: 'Inferfaces' -> 'Interfaces', 'Client-Staruplogik' -> 'Client-Startuplogik'.
```suggestion
Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startuplogik, Client-Services (+ Interfaces dafür, die Services hier sollen lediglich die Server-Services über HTTP aufrufen), Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul.
```
gitea-actions
commented
Stil: 'Quellcode' statt 'Sourcecode' (optionaler Stilvorschlag für Deutsch). Stil: 'Quellcode' statt 'Sourcecode' (optionaler Stilvorschlag für Deutsch).
```suggestion
Im Server-Projekt liegt der Quellcode, welcher serverseitig ausgeführt werden soll. In der Praxis bedeutet das: alle Repositories, Controller, Manager, Migrationen und Server-Services (entwickelt nach einem Interface definiert im Client) und Server-Startuplogik.
```
|
||||
[^6]: https://docs.oqtane.org/dev/extensions/index.html
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: Tippfehler in 'Startuplogik' und 'Interfaces'. Rechtschreibung: Tippfehler in 'Startuplogik' und 'Interfaces'.
```suggestion
Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startuplogik, Client-Services (+ Interfaces dafür, die Services hier sollen lediglich die Server-Services über HTTP aufrufen), Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul.
```
|
||||
### Architektur eines Moduls
|
||||
Ein Modul in Oqtane besteht aus 4 Projekten. Server, Client, Shared und Package.
|
||||
|
||||
Im Server-Projekt liegt Sourcecode, welcher serverseitig ausgeführt werden soll. In der Praxis bedeutet das: alle Repositories, Controller, Manager, Migrationen und Server-Services (entwickelt nach einem Interface definiert im Client) und Server-Startuplogik.
|
||||
Ein Modul in Oqtane besteht aus vier Projekten:
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'Package Projekt' -> 'Package-Projekt'. Rechtschreibung: 'Package Projekt' -> 'Package-Projekt'.
```suggestion
Im Package-Projekt findet man Skripte zum Debuggen und Releasen eines Moduls. Und die NuGet-Spezifikation.
```
|
||||
Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Staruplogik, Client-Services (+ Inferfaces dafür, die Services hier sollen lediglich die Server-Services über HTTP aufrufen), Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul.
|
||||
- Im Server-Projekt liegt Sourcecode, welcher serverseitig ausgeführt werden soll. Dazu gehören unter anderem alle Repositories, Controller, Manager, Migrationen und Server-Services und Server-Startuplogik.
|
||||
|
||||
Im Shared-Projekt wird geteilter Sourcecode abgelegt, der server- und clientseitig verwendet wird. In der Praxis bleibt es hierbei bei den EntityFramework-Modellen zum Speichern der Daten im Arbeitsspeicher.
|
||||
- Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startuplogik, Client-Services, Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul.
|
||||
|
||||
Im Package Projekt findet man Skripte zum Debuggen und Releasen eines Moduls. Und die NuGet-Spezifikation.
|
||||
- Beim Debug werden die DLLs, PDBs und statischen Assets wie Skripte und Stylesheets der 3 anderen Projekte in den bereits gebauten Oqtane.Server `oqtane.framework/oqtane.server/bin/debug/net10.0/...` kopiert.
|
||||
- Beim Release wird ein NuGet-Paket erstellt und unter oqtane.framework/oqtane.server/Packages abgelegt. Dort abgelegte NuGet-Pakete werden beim nächsten Start des Oqtane Servers installiert (DB Migrationen werden gemacht und die Pakete entpackt).
|
||||
- Im Shared-Projekt wird geteilter Sourcecode abgelegt, der server- und clientseitig verwendet wird. In der Praxis bleibt es hierbei bei den EntityFramework-Modellen zum Speichern der Daten im Arbeitsspeicher.
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'mitels' -> 'mittels', 'Challanges' -> 'Challenges'. 'NginX' -> 'Nginx'. Rechtschreibung: 'mitels' -> 'mittels', 'Challanges' -> 'Challenges'. 'NginX' -> 'Nginx'.
```suggestion
In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen. Wir verwenden Nginx als Reverse Proxy, welcher bei uns die SSL Terminierung macht. Das Zertifikat, welches verwendet wird, wird von Let's Encrypt bereit gestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert und verwaltet. Oqtane selber läuft als Systemd-Service im Kestrel Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server "Kestrel") hört auf der Loopback IP und Port 5000. Damit ist Oqtane nur durch Nginx erreichbar. PostgreSQL ist die Datenbank in dem System: Sie hört wieder auf der Loopback IP und Port 5432.
```
gitea-actions
commented
Grammatik/Rechtschreibung: Komma nach 'erkläre ich'. 'bereitgestellt' zusammen, 'mittels' mit zwei t, 'Challenges' korrigiert. Grammatik/Rechtschreibung: Komma nach 'erkläre ich'. 'bereitgestellt' zusammen, 'mittels' mit zwei t, 'Challenges' korrigiert.
```suggestion
In diesem Kapitel erkläre ich, wie die ausgewählten Komponenten zusammenspielen. Wir verwenden Nginx als Reverse Proxy, welcher bei uns die SSL-Terminierung macht. Das Zertifikat, welches verwendet wird, wird von Let's Encrypt bereitgestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert und verwaltet. Oqtane selbst läuft als Systemd-Service im Kestrel-Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server 'Kestrel') hört auf der Loopback-IP und Port 5000. Damit ist Oqtane nur durch Nginx erreichbar. PostgreSQL ist die Datenbank im System: Sie hört wieder auf der Loopback-IP und Port 5432.
```
|
||||
- Im Package Projekt findet man Skripte zum Debuggen und Releasen eines Moduls und die NuGet-Spezifikation.
|
||||
- Beim Debug werden die DLLs, PDBs und statischen Assets wie Skripte und Stylesheets der drei anderen Projekte in den bereits gebauten Oqtane.Server `oqtane.framework/oqtane.server/bin/debug/net10.0/...` kopiert.
|
||||
- Beim Release wird ein NuGet-Paket erstellt und unter oqtane.framework/oqtane.server/Packages abgelegt. Dort abgelegte NuGet-Pakete werden beim nächsten Start des Oqtane Servers installiert (Datenbank Migrationen werden gemacht und die Pakete entpackt).
|
||||
|
||||
## Systemarchitektur (Postgres / Oqtane / Nginx)
|
||||
|
||||
In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen. Wir verwenden NginX als Reverse Proxy, welcher bei uns die SSL Terminierung macht. Das Zertifikat, welches verwendet wird, wird von Let's Encrypt bereit gestellt und mitels HTTP-Challanges und dem Certbot auf dem Server aktualisiert und verwaltet. Oqtane selber läuft als Systemd-Service im Kestrel Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server "Kestrel") hört auf der Loopback IP und Port 5000. Damit ist Oqtane nur durch NginX erreichbar. PostgreSQL ist die Datenbank in dem System: Sie hört wieder auf der Loopback IP und Port 5432.
|
||||
In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen. Wir verwenden NginX als Reverse Proxy, welcher bei uns die SSL Terminierung macht. Das Zertifikat, welches verwendet wird, wird von Let's Encrypt bereit gestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert und verwaltet. Oqtane selber läuft als Systemd-Service im Kestrel Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server "Kestrel") hört auf der Loopback IP und Port 5000. Damit ist Oqtane nur durch NginX erreichbar. PostgreSQL ist die Datenbank in dem System: Sie hört wieder auf der Loopback IP und Port 5432.
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
@@ -83,29 +90,32 @@ architecture-beta
|
||||
service db(database)[PostgreSQL] in server
|
||||
service oqtane(server)[Oqtane] in server
|
||||
service nginx(server)[NginX] in server
|
||||
|
||||
service internet(cloud)[Internet]
|
||||
|
||||
service internet(cloud)[Internet]
|
||||
|
gitea-actions
commented
Rechtschreibung: 'High-Port' statt 'Hight-Port'. Rechtschreibung: 'High-Port' statt 'Hight-Port'.
```suggestion
Zusätzlich gab es einen Administrationszugang zu den Servern, welcher über SSH möglich war. Dieser wurde für die Installation und Konfiguration der einzelnen Komponenten verwendet. Bei Hetzner war dieser Zugang nur über eine Wireguard VPN erreichbar. Bei der Schule war dieser Zugang direkt (über einen High-Port) möglich. Und bei LiveDesign war dieser Zugang wieder über eine VPN geregelt. Anfänglich mit SSL VPN, später mit einem IPSEC / Strongswan.
```
|
||||
|
||||
internet:R <--> L:nginx
|
||||
nginx:R <--> L:oqtane
|
||||
oqtane:R <--> L:db
|
||||
|
gitea-actions
commented
Rechtschreibung: 'Möglich' -> 'möglich', 'and' -> 'und' (Sprachmix), 'teil' -> 'Teil'. Rechtschreibung: 'Möglich' -> 'möglich', 'and' -> 'und' (Sprachmix), 'teil' -> 'Teil'.
```suggestion
Blazor ist ein kostenloses und quelloffenes Web-Framework, welches es möglich macht, Benutzeroberflächen für Web-Browser basierend auf C# und HTML zu erstellen. Es wird von Microsoft als Teil des ASP.NET Core Frameworks entwickelt.
```
gitea-actions
commented
Rechtschreibung/Stil: 'möglich' kleinschreiben (Adjektiv). 'und' statt 'and'. 'Teil' großschreiben. Rechtschreibung/Stil: 'möglich' kleinschreiben (Adjektiv). 'und' statt 'and'. 'Teil' großschreiben.
```suggestion
Blazor ist ein kostenloses und quelloffenes Web-Framework, welches es möglich macht, Benutzeroberflächen für Web-Browser basierend auf C# und HTML zu erstellen. Es wird von Microsoft als Teil des ASP.NET Core Frameworks entwickelt.
```
|
||||
```
|
||||
|
||||
Zusätzlich gab es einen Administrationszugang zu den Servern, welcher über SSH möglich war. Dieser wurde für die Installation und Konfiguration der einzelnen Komponenten verwendet. Bei Hetzner war dieser Zugang nur über eine Wireguard VPN erreichbar. Bei der Schule war dieser Zugang direkt (über einen Hight-Port) möglich. Und bei LiveDesign war dieser Zugang wieder über eine VPN geregelt. Anfänglich mit SSL VPN, später mit einem IPSEC / Strongswan.
|
||||
Zusätzlich gab es einen Administrationszugang zu den Servern, welcher über SSH möglich war. Dieser wurde für die Installation und Konfiguration der einzelnen Komponenten verwendet. Bei Hetzner war dieser Zugang nur über eine Wireguard VPN erreichbar. Bei dem Schulserver war dieser Zugang direkt (über einen Hight-Port) möglich. Und bei LiveDesign war dieser Zugang wieder über eine VPN geregelt. Anfänglich mit SSL VPN, später mit einem IPSEC / Strongswan.
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'gerenderet' -> 'gerendert', 'dasder' -> 'das ist der'. Rechtschreibung: 'gerenderet' -> 'gerendert', 'dasder' -> 'das ist der'.
```suggestion
- Static Server: Die Komponente wird serverseitig "gerendert" und besitzt keine Interaktivität. Das ist der Default `RenderMode`
```
gitea-actions
commented
Rechtschreibung: Fehlendes Leerzeichen in 'ist der'. Rechtschreibung: Fehlendes Leerzeichen in 'ist der'.
```suggestion
- Static Server: Die Komponente wird serverseitig "gerendert" und besitzt keine Interaktivität. Das ist der Default `RenderMode`
```
|
||||
## Entwicklung mit ASP.NET (Was ist Blazor? / Was ist Razor? / Kestrel)
|
||||
|
gitea-actions
commented
Rechtschreibung: 'Interative' -> 'Interactive'. Rechtschreibung: 'Interative' -> 'Interactive'.
```suggestion
- Interactive Server: Die Komponente wird serverseitig "gerendert", diesmal ist sie jedoch interaktiv. Das bedeutet: Man kann mithilfe von C# den Zustand der Seite dynamisch bearbeiten. Diese Zustandsänderungen werden serverseitig bearbeitet. Hierbei kommunizieren Server und Client mithilfe von SignalR über WebSockets miteinander.
```
|
||||
|
||||
### Blazor [^7]
|
||||
|
gitea-actions
commented
Kontext: 'Modul' -> 'Modus' (bezieht sich auf Render-Modi). Kontext: 'Modul' -> 'Modus' (bezieht sich auf Render-Modi).
```suggestion
- Interactive Auto: Im `Interactive Auto` Modus wird bei dem initialen Besuch der Website der `Interactive Server` Modus gewählt und im Hintergrund wird der WebAssembly-Build heruntergeladen, damit bei weiteren Besuchen der Seite der `Interactive WebAssembly` Modus gewählt werden kann.
```
|
||||
Blazor ist ein kostenloses und quelloffenes Web-Framework, welches es Möglich macht, Benutzeroberflächen für Web-Browser basierend auf C# and HTML zu erstellen. Es wird von Microsoft als teil des ASP.NET Core Frameworks entwickelt.
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'Nativen' -> 'nativen', 'Funktioniert' -> 'funktioniert'. Rechtschreibung: 'Nativen' -> 'nativen', 'Funktioniert' -> 'funktioniert'.
```suggestion
- Hybrid: Dieser Modus ist der einzige, welcher nicht innerhalb einer Blazor Web App läuft, sondern in einem WebView einer nativen App. Dabei wird innerhalb des Mutterprozesses, ganz ohne Webserver, gearbeitet. Das Ganze funktioniert in WPF und WinForms Apps und in nativen mobilen Apps für Android und iOS mithilfe von .NET MAUI.
```
gitea-actions
commented
Rechtschreibung: Adjektiv 'nativen' kleinschreiben. 'Das Ganze funktioniert' groß/klein. Rechtschreibung: Adjektiv 'nativen' kleinschreiben. 'Das Ganze funktioniert' groß/klein.
```suggestion
- Hybrid: Dieser Modus ist der einzige, welcher nicht innerhalb einer Blazor Web App läuft, sondern in einem WebView einer nativen App. Dabei läuft dies innerhalb des Mutterprozesses, ganz ohne Webserver. Das Ganze funktioniert in WPF- und WinForms-Apps und in nativen mobilen Apps für Android und iOS mithilfe von .NET MAUI.
```
|
||||
Blazor ist ein kostenloses und quelloffenes Web-Framework, welches es möglich macht Benutzeroberflächen für Web-Browser, basierend auf C# and HTML, zu erstellen. Es wird von Microsoft als teil des ASP.NET Core Frameworks entwickelt.
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung/Grammatik: 'Dateil' -> 'Datei', 'seperaten' -> 'separaten', 'benutzer' -> 'Benutzung'. Rechtschreibung/Grammatik: 'Dateil' -> 'Datei', 'seperaten' -> 'separaten', 'benutzer' -> 'Benutzung'.
```suggestion
Razor-Komponenten (in dieser Arbeit, sowie umgangssprachlich, auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von Inline C# beeinflusst werden kann. Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor Datei liegen, oder in einer separaten Code-Behind-Datei und der Benutzung einer partiellen Klasse. Inline C# Code wird mithilfe von dem `@`-Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter:
```
gitea-actions
commented
Rechtschreibung: 'sich' statt 'sicher'. 'Datei' statt 'Dateil'. 'separaten' statt 'seperaten'. 'Benutzung' statt 'benutzer'. 'mithilfe des' (Genitiv). Rechtschreibung: 'sich' statt 'sicher'. 'Datei' statt 'Dateil'. 'separaten' statt 'seperaten'. 'Benutzung' statt 'benutzer'. 'mithilfe des' (Genitiv).
```suggestion
Razor-Komponenten (in dieser Arbeit sowie umgangssprachlich auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches durch die Verwendung von Inline-C# beeinflusst werden kann. Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor-Datei liegen oder in einer separaten Code-Behind-Datei unter Benutzung einer partiellen Klasse. Inline-C#-Code wird mithilfe des `@`-Zeichens markiert. Hier ist ein Beispiel für einen einfachen Counter:
```
|
||||
Blazor hat mehrere Hosting-Modelle:
|
||||
- Blazor Web App: Hier wird die Web App als Teil einer ASP.NET Core Anwendung bereitgestellt. Hier gibt es mehrere Render Modi:
|
||||
- Static Server: Die Komponente wird serverseitig "gerenderet" und besitzt keine Interaktivität. Das istder Default `RenderMode`
|
||||
- Interative Server: Die Komponente wird serverseitig "gerendert", diesmal ist sie jedoch interaktiv. Das bedeutet: Man kann mithilfe von C# den Zustand der Seite dynamisch bearbeiten. Diese Zustandsänderungen werden serverseitig bearbeitet. Hierbei kommunizieren Server und Client mithilfe von SignalR über WebSockets miteinander.
|
||||
- Interactive WebAssembly: Die Komponente wird clientseitig, also im Browser, "gerendert". Damit der Blazor C# Code auch im Browser ausgeführt werden kann wird dieser in WebAssembly kompiliert.
|
||||
- Interactive Auto: Im `Interactive Auto` Modul wird bei dem initialen Besuch der Website der `Interactive Server` Modus gewählt und im Hintergrund wird der WebAssembly-Build heruntergeladen, damit bei weiteren Besuchen der Seite der `Interactive WebAssembly` Modus gewählt werden kann.
|
||||
- Hybrid: Dieser Modus ist der einzige, welcher nicht innerhalb einer Blazor Web App läuft, sondern in einem WebView einer Nativen App. Dabei wird innerhalb des Mutterprozesses, ganz ohne WebServer. Das ganze Funktioniert in WPF und WinForms Apps und in nativen mobilen Apps für Android und iOS mithilfe von .NET MAUI.
|
||||
|
||||
Razor-Komponenten (in dieser Arbeit, sowie Umgangssprachlich, auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von inline C# beeinflusst werden kann. Das Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sicher der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor Dateil liegen, oder in einer seperaten Code-Behind-Datei und der benutzer einer partiellen Klasse. Inline C# Code wird mithilfe von dem `@`- Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter:
|
||||
- Blazor Web App: Hier wird die Web App als Teil einer ASP.NET Core Anwendung bereitgestellt. Dabei gibt es mehrere Render Modi:
|
||||
- Static Server: Die Komponente wird serverseitig gerendert und besitzt keine Interaktivität. Es ist der standardmäßige `RenderMode`
|
||||
- Interactive Server: Die Komponente wird serverseitig gerendert, diesmal ist sie jedoch interaktiv. Das bedeutet, man kann mithilfe von C# den Zustand der Seite dynamisch bearbeiten. Diese Zustandsänderungen werden serverseitig bearbeitet. Hierbei kommunizieren Server und Client mithilfe von SignalR über WebSockets miteinander.
|
||||
- Interactive WebAssembly: Die Komponente wird clientseitig, also im Browser, gerendert. Damit der Blazor C# Code auch im Browser ausgeführt werden kann, wird dieser in WebAssembly kompiliert.
|
||||
- Interactive Auto: Im `Interactive Auto` Modul wird bei dem initialen Besuch der Website der `Interactive Server` Modus gewählt und im Hintergrund wird der WebAssembly-Build heruntergeladen, damit bei weiteren Besuchen der Seite der `Interactive WebAssembly` Modus gewählt werden kann.
|
||||
- Hybrid: Dieser Modus ist der Einzige, welcher nicht innerhalb einer Blazor Web App läuft, sondern in einem WebView in einer Nativen App. Dabei wird innerhalb des Mutterprozesses, ganz ohne WebServer, der C# und Razor-Code ausgeführt. Das Ganze funktioniert in WPF und WinForms Apps und in nativen mobilen Apps für Android und iOS mithilfe von .NET MAUI.
|
||||
|
||||
Razor-Komponenten (in dieser Arbeit, sowie umgangssprachlich, auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von inline C# beeinflusst werden kann. Das Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor Datei liegen, oder in einer seperaten Code-Behind-Datei. Inline C# Code wird mithilfe von `@`- Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter:
|
||||
|
||||
```razor
|
||||
<h1>Counter</h1>
|
||||
@@ -114,7 +124,7 @@ Razor-Komponenten (in dieser Arbeit, sowie Umgangssprachlich, auch oft nur Kompo
|
||||
|
||||
<button @onclick="Increment">Increment</button>
|
||||
|
||||
@code
|
||||
@code
|
||||
{
|
||||
|
gitea-actions
commented
Grammatik: 'welcher dieser Komponente' -> 'welcher diese Komponente'. Fehlende Leerzeichen bei Code-Referenzen. Grammatik: 'welcher dieser Komponente' -> 'welcher diese Komponente'. Fehlende Leerzeichen bei Code-Referenzen.
```suggestion
Mit `@count` in Zeile 3 wird der Wert der Variablen count in den `<p>` Tag eingebaut. Mit `@onclick="Increment"` in Zeile 5 wird die onclick Property vom `<button>` Tag auf die Increment Methode im C# Code gemappt. Der `@code` Block in Zeile 7 ist der C# Code, welcher diese Komponente dynamisch macht. Hier ist die Variable count definiert und die Methode Increment, welche diese Komponente interaktiv macht.
```
gitea-actions
commented
Grammatik: 'welche diese Komponente' (Akkusativ). 'onclick-Property des -Tags'. Grammatik: 'welche diese Komponente' (Akkusativ). 'onclick-Property des <button>-Tags'.
```suggestion
Mit `@count` in Zeile 3 wird der Wert der Variablen 'count' in den `<p>`-Tag eingebaut. Mit `@onclick="Increment"` in Zeile 5 wird die onclick-Property des `<button>`-Tags auf die Increment-Methode im C#-Code verwiesen. Der `@code`-Block in Zeile 7 ist der C#-Code, welcher diese Komponente dynamisch macht. Hier ist die Variable 'count' definiert und die Methode 'Increment', welche diese Komponente interaktiv macht.
```
|
||||
private int count = 0;
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'Beipsiel' -> 'Beispiel', 'Auszugsweise' -> 'auszugsweise'. Rechtschreibung: 'Beipsiel' -> 'Beispiel', 'Auszugsweise' -> 'auszugsweise'.
```suggestion
Razor hat auch eine Reihe an Keywords wie zum Beispiel (nur auszugsweise, bzw. jene, die wir verwendet haben):
```
gitea-actions
commented
Rechtschreibung: 'Beispiel' statt 'Beipsiel'. Rechtschreibung: 'Beispiel' statt 'Beipsiel'.
```suggestion
Razor hat auch eine Reihe an Keywords wie zum Beispiel (nur auszugsweise bzw. die, die wir verwendet haben):
```
|
||||
@@ -125,29 +135,34 @@ Razor-Komponenten (in dieser Arbeit, sowie Umgangssprachlich, auch oft nur Kompo
|
||||
}
|
||||
|
gitea-actions
commented
Rechtschreibung: 'verzweigungen' -> 'Verzweigungen'. Rechtschreibung: 'verzweigungen' -> 'Verzweigungen'.
```suggestion
- if: Für Verzweigungen im Markup
```
gitea-actions
commented
Rechtschreibung: 'Verzweigungen' großschreiben. Rechtschreibung: 'Verzweigungen' großschreiben.
```suggestion
- if: Für Verzweigungen im Markup
```
|
||||
```
|
||||
|
||||
Mit`@count` in Zeile 3 wird der Wert der Variablen count in den `<p>` Tag mit eingebaut. Mit `@onclick="Increment"` in Zeile 5 wird die onclick Property vom `<button>`Tag auf die Increment Methode im C# Code. Der `@code` Block in Zeile 7 ist der C# Code, welcher diese Komponente dynamisch macht. Hier ist die Variable count definiert und die Methode Increment, welche dieser Komponente interaktiv macht.
|
||||
Mit`@count` in Zeile 3 wird der Wert der Variablen count in den `<p>` Tag mit eingebaut. Mit `@onclick="Increment"` in Zeile 5 wird die onclick Property vom `<button>`Tag auf die Increment Methode im C# Code gesetzt. Der `@code` Block in Zeile 7 ist der C# Code, welcher diese Komponente dynamisch macht. Hier ist die Variable count und die Methode Increment definiert, welche dieser Komponente interaktiv macht.
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'Kommunikation' statt 'Kommunikations'. Rechtschreibung: 'Kommunikation' statt 'Kommunikations'.
```suggestion
### Kommunikation zwischen Front- und Backend
```
|
||||
Razor hat auch eine Reihe an Keywords wie zum Beipsiel (nur Auszugsweise, bzw. die die wir verwendet haben):
|
||||
- namespace: Gibt den aktuellen Namespace in der Razor Datei ein
|
||||
Razor hat auch eine Reihe an Keywords, wie zum Beipsiel (nur Auszugsweise, bzw. die die wir verwendet haben):
|
||||
|
||||
- namespace: Gibt den aktuellen Namespace in der Razor Datei an.
|
||||
|
gitea-actions
commented
Rechtschreibung: 'injection' -> 'Injection' (Überschrift). Rechtschreibung: 'injection' -> 'Injection' (Überschrift).
```suggestion
## Dependency Injection
```
|
||||
- inherits: Gibt die Superklasse der generierten C# Klasse an.
|
||||
|
gitea-actions
commented
Rechtschreibung/Stil: 'Library'. 'Kommunikation'. 'verwendet wird' doppelt gemoppelt. Rechtschreibung/Stil: 'Library'. 'Kommunikation'. 'verwendet wird' doppelt gemoppelt.
```suggestion
SignalR ist eine Library für das ASP.NET Framework, welche es möglich macht, Server-zu-Client-Kommunikation zu betreiben. Oqtane verwendet diesen Dienst im `Interactive Server (SignalR)`-Render-Modus.
```
|
||||
- using: Gibt die im C# Code benutzen/verfügbaren Namespaces an
|
||||
- foreach: Für Wiederholungen im Markup
|
||||
- if: Für verzweigungen im Markup
|
||||
- if: Für Verzweigungen im Markup
|
||||
|
||||
[^7]: https://en.wikipedia.org/wiki/Blazor
|
||||
|
||||
### Kommunikations zwischen Front und Backend
|
||||
Wie Front- und Backend miteinander interagieren hängt hauptsächlich vom Render Modus ab. Oqtane kann auf verschiedene Arten betrieben werden. Hierbei ist es dem Modulentwickler ziemlich egal, welche Art der Kommunikation (WebSockets, HTTP Long-Polling, REST) verwendet wird.
|
||||
### Kommunikation zwischen Front- und Backend
|
||||
|
||||
Wie Front- und Backend miteinander interagieren hängt hauptsächlich vom Render Modus ab. Oqtane kann auf verschiedene Arten betrieben werden. Hierbei ist es dem Modulentwickler ziemlich egal, welche Art der Kommunikation (WebSockets, HTTP Long-Polling, REST) verwendet wird.
|
||||
|
||||
#### SignalR
|
||||
SignalR ist eine Libary aus für das ASP.NET Framework, welche es möglich macht Server zu Client komminikation zu betreiben. Oqtane verwendet im `Interactive Server (SignalR)` Render-Modus verwendet wird.
|
||||
|
||||
## Dependency injection
|
||||
SignalR ist eine Library aus dem ASP.NET Framework, welche es möglich macht, Server zu Client Kommunikation zu betreiben. Oqtane verwendet SignalR im `Interactive Server (SignalR)` Render-Modus.
|
||||
|
||||
## Dependency Injection
|
||||
|
||||
### Dependency Inversion Principle [^1]
|
||||
|
||||
Das Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines von den fünf `SOLID` Prinzipien in der Softwareentwicklung.
|
||||
|
||||
Das DIP unterscheidet zwischen high-level und low-level Modulen.
|
||||
|
||||
- Die High-Level-Module beschreiben die Applikations- / Businesslogik, ohne direkt mit den Low-Level-Modulen zu interagieren, sondern lediglich auf Abstraktionen. [^3]
|
||||
- Die Abstraktionen sollen nicht von Implementierungsdetails abhängig sein, sondern die Low-Level-Implementierung sollen gemäß der Abstraktionsschicht implementiert werden. [^3]
|
||||
|
||||
@@ -155,26 +170,29 @@ Ausgangslage ist eine Softwarearchitektur im Direct-Dependency-Graph-Modell.
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
service a(mdi:package-variant-closed)[Klasse A]
|
||||
service a(mdi:package-variant-closed)[Klasse A]
|
||||
service b(mdi:package-variant-closed)[Klasse B]
|
||||
|
||||
a:R --> L:b
|
||||
```
|
||||
|
||||
Bei diesem Beispiel ist die Klasse A ein high-level Modul, welches direkt auf die Klasse B referenziert, was das DI-Prinzip verbietet.
|
||||
Das Problem dabei: Die einzelnen Klassen sind eng gekoppelt, was das Austauschen von B mit einer anderen Klasse unmöglich macht. Genau dieses Problem wird vom DIP gelöst.
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
service a(mdi:package-variant-closed)[Klasse A]
|
||||
service a(mdi:package-variant-closed)[Klasse A]
|
||||
service b(mdi:package-variant-closed)[Klasse B]
|
||||
|
gitea-actions
commented
Rechtschreibung: 'dannach' -> 'danach'. Rechtschreibung: 'dannach' -> 'danach'.
```suggestion
Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt, bzw. selbst instanziiert und danach bereitgestellt. [^4]
```
|
||||
service ib(mdi:car-clutch)[Interface B]
|
||||
|
||||
a:B --> T:ib
|
||||
|
gitea-actions
commented
Rechtschreibung: 'danach' statt 'dannach'. Rechtschreibung: 'danach' statt 'dannach'.
```suggestion
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden Instanzen erstellt oder wieder entsorgt (sofern der Service nicht mehr gebraucht wird). Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt bzw. selbst instanziiert und danach bereitgestellt. [^4]
```
|
||||
ib:R <-- L:b
|
||||
```
|
||||
|
||||
Das High-Level-Modul ruft lediglich eine Abstraktion eines Low-Level-Moduls auf, welche von einem, oder mehreren Low-Level-Modulen implementiert wurde. Für das High-Level-Modul ist es hier egal, welches Low-Level-Modul die Implementierung bereitstellt. Dadurch erhält man einen viel modulareren Aufbau in der Software. Die einzelnen Module sind auch leichter austauschbar und testbar. Genau diese Modularität macht Dependency Injection möglich.
|
||||
|
||||
### Microsoft Dependency Injection Framework
|
||||
|
||||
Dependency Injektion ist in .NET genau so wie Konfiguration, Protokollierung und das Optionsmuster ins Framework integriert. [^4]
|
||||
|
||||
Alle Dependencies werden in einem `Service-Container` zur Verwaltung registriert. .NET hat einen eingebauten `Service-Container` (eine Implementierung des `IServiceProvider`). [^4]
|
||||
@@ -182,6 +200,7 @@ Alle Dependencies werden in einem `Service-Container` zur Verwaltung registriert
|
||||
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden Instanzen erstellt, oder wieder entsorgt (sofern das Service nicht mehr gebraucht wird). Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt, bzw. selbst instanziiert und dannach bereitgestellt. [^4]
|
||||
|
||||
Hier ein Beispiel aus der Dokumentation von Microsoft: [^4]
|
||||
|
||||
```c#
|
||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
@@ -217,9 +236,10 @@ public sealed class Worker(IMessageWriter messageWriter) : BackgroundService
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Das ist ein simples Beispiel, welches Teile des DI Frameworks zeigt. Wir haben einen Service (Klasse Worker), ein Dependency (Klasse MessageWriter) und eine Abstraktionsebene, von dem Dependency (Interface IMessageWriter).
|
||||
|
||||
Bei Programmstart wird zuerst manuell der `Service-Container` erstellt, dannach alle Module registriert (entweder als HostedService, oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
|
||||
Bei Programmstart wird zuerst manuell der `Service-Container` erstellt, dannach alle Module registriert (entweder als HostedService, oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
|
||||
|
||||
Mit dem Aufruf von `builder.Build()` wird intern ein Dependency Graph erstellt und mit `host.Run()` wird versucht die Klasse Worker zu instanziieren und zu starten. Nachdem Worker ein Dependency auf IMessageWriter hat, wird über den zuvor erstellten Dependency-Graph die Implementierung von IMessageWriter gesucht. Jetzt wird MessageWriter instanziiert und dem Konstruktor von Worker übergeben, damit seine Dependencies befriedigt werden.
|
||||
|
||||
@@ -227,7 +247,7 @@ So sieht der Abhängigkeitsgraph bei diesem Beispiel aus.
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
service a(mdi:package-variant-closed)[Worker]
|
||||
service a(mdi:package-variant-closed)[Worker]
|
||||
service b(mdi:package-variant-closed)[MessageWriter]
|
||||
|
gitea-actions
commented
Grammatik: 'ein Continuous-Integration-System' (Neutrum). Grammatik: 'ein Continuous-Integration-System' (Neutrum).
```suggestion
## Automatisierter Build und Release Prozess mithilfe von Gitea Actions.
Gitea, das Versionskontrollsystem dieser Diplomarbeit, hat ein Continuous-Integration-System eingebaut.
```
|
||||
service ib(mdi:car-clutch)[IMessageWriter]
|
||||
|
||||
@@ -266,10 +286,15 @@ Anwendungen von Gitea Actions bei dieser Diplomarbeit:
|
||||
> Zum automatischen Überprüfen der Dokumente, unter anderem, mithilfe von KI, wie zum Beispiel Gemini.
|
||||
|
||||
# Projektmanagement
|
||||
|
||||
|
gitea-actions
commented
Rechtschreibung: 'vollkommen', 'Hälfte', 'Unterschreiben', 'Zeitplan'. Rechtschreibung: 'vollkommen', 'Hälfte', 'Unterschreiben', 'Zeitplan'.
```suggestion
Nachdem ich mich von Anfang an vollkommen in das Deploymentproblem von Oqtane gestürzt habe, habe ich meine Rolle als Teamleitung etwas schleifen gelassen. Dadurch fehlte bei einigen Teammitgliedern initial die Identifikation mit dem Projekt und in weiterer Folge auch die Motivation, an diesem Projekt mitzuarbeiten. Nachdem im Verlauf des Frühlings und über den Sommer von der Hälfte des Teams trotz Besprechungen und Mahnungen keine Beiträge zu dem Projekt kamen, haben Hr. Prof. Gürth und ich uns dazu entschieden, uns von 2 Personen vor dem Unterschreiben des Projektantrages zu trennen. Grund dazu war die Angst, die mangelnde Motivation zieht das restliche Team mit hinunter. Wir wollten uns trotz des Downsizings nicht an Funktionalitäten sparen und haben uns für das nächste halbe bis dreiviertel Jahr einen ziemlich strikten Zeitplan vorgenommen.
```
|
||||
## Scrum
|
||||
|
||||
## YouTrack
|
||||
|
||||
## Gitea (mit Issues)
|
||||
|
||||
## Git
|
||||
|
||||
## Kommunikation
|
||||
|
||||
# Learnings
|
||||
@@ -287,20 +312,21 @@ Nachdem ich mich von Anfang an volkommen in das Deploymentproblem von Oqtane ges
|
||||
Ein wesentliches Learning aus dem Projektverlauf war die Diskrepanz zwischen der initialen Planung und dem tatsächlichen Aufwand. Ursprünglich wurde der Zeitaufwand für das Aufsetzen der Infrastruktur und die Einarbeitung in das Oqtane-Framework auf etwa drei Wochen geschätzt. In der Realität nahm dieser Prozess jedoch mehrere Monate in Anspruch.
|
||||
|
||||
Es gibt mehrere Gründe dafür:
|
||||
|
||||
- `Fehlende oder nur schlechte Dokumentation von Oqtane`: Einige Probleme im Deployment wurden in langer und mühseliger Arbeit auseinander gebrochen und in weitere immer kleinere Probleme unterteilt. Dadurch, dass wir alle keine Erfahrung mit der Entwicklung und dem Deployment von ASP.NET Code Anwendungen hatten und die Dokumentation doch schlecht war, blieb uns manchmal nichts anderes übrig als mit WireShark den Netzwerktraffic mit zu schneiden und nebenbei im Git Repository die geloggten Zeilen Code zu finden und so das Framework von innen heraus kennen zu lernen. Dadurch hatte ich dann nach einer Einarbeitungszeit von 4 Monaten ziemlich jede Stelle im Sourcecode von Oqtane gesehen und finde mich um das schneller zurecht.
|
||||
- `Team-Konsolidierung`: Durch das notwendige Downsizing des Teams mussten Aufgaben neu verteilt werden, was die individuelle Arbeitslast erhöhte und die Konzentration auf die Kernentwicklung zeitweise verzögert hat.
|
||||
- `Abhängigkeit von der Infrastruktur`: Dadurch, dass wir bis in den Oktober / November hinein nicht wussten, ob wir weiter bei Oqtane bleiben können, haben die anderen Teammitglieder nicht mit der sinnvollen Entwicklung ihrer Module starten können. Zitat: "Und was wenn wir am Ende doch noch das CMS umstellen müssen?" => Auch wenn der Auftrag war, mit der Modulentwicklung zu starten war die Motivation meiner Teammitglieder nicht so hoch. Selbst wenn sie nicht direkt von der Infrastruktur mit der Ausführung ihrer Aufgaben abhängig waren, motiviert waren sie wegen der Umstände auch nicht.
|
||||
|
||||
|
||||
Reaktion auf den Verzug:
|
||||
Um das Projektziel dennoch zu erreichen, wurde der Zeitplan im Herbst 2025 massiv gestrafft. Durch die Umstellung auf einen strikteren 14-tägigen Sprint-Rhythmus und die Priorisierung von Core-Funktionalitäten (MVP-Ansatz) konnte der Rückstand teilweise aufgeholt werden.
|
||||
|
||||
|
||||
> Fazit: Die Erfahrung zeigt, dass gerade bei "Nischen-Frameworks" wie Oqtane ein deutlich höherer Puffer für die Einarbeitungs- und Infrastrukturphase (Faktor 2 bis 3 der ursprünglichen Schätzung) eingeplant werden muss.
|
||||
|
||||
`90% fertig, oder fertig?`: Es gibt einige "Regeln", wie: das `Paretoprinzip`, `Hofstadter’s Law` und die `90-90 Regel`. Letztere wurde im Jahr 1985 von Jon Bentley in einer Kolumne "Programming pearls" veröffentlicht. Ausgeschrieben lautet sie:
|
||||
|
||||
> [Rule of Credibility] The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.
|
||||
(Jon Bentley. 1985. Programmimg pearls. Commun. ACM 28, 9 (Sept. 1985), 896–901. https://doi.org/10.1145/4284.315122) [^8]
|
||||
Diese Diplomarbeit liefert weitere Evidenz, dass diese Faustregel stimmt.
|
||||
> (Jon Bentley. 1985. Programmimg pearls. Commun. ACM 28, 9 (Sept. 1985), 896–901. https://doi.org/10.1145/4284.315122) [^8]
|
||||
> Diese Diplomarbeit liefert weitere Evidenz, dass diese Faustregel stimmt.
|
||||
|
||||
[^8](https://dl.acm.org/doi/10.1145/4284.315122)
|
||||
|
||||
@@ -313,6 +339,7 @@ Ein zentrales Problem in unserer ursprünglichen Arbeitsweise war die Kopplung v
|
||||
- Ineffizienz: Lange Präsenz-Meetings blockierten wertvolle Entwicklungszeit, ohne die technische Qualität zu steigern.
|
||||
|
||||
Lösungsansatz: Meetings und Besprechungen asynchron zueinander setzen.
|
||||
|
||||
- Asynchrone Daily-Updates: Statusberichte erfolgen schriftlich (z. B. in Gitea Issues oder YouTrack), nicht mehr in stundenlangen Call-Marathons. Das nimmt den zeitlichen Druck vom einzelnen Entwickler. Oder zumindest in kurzen Commitnachrichten, welche am Ende des Tages automatisch an alle Teammitglieder zum überblick gesendet werden (eventuell mit @username tagging, um eine Person nochmal genau anzusprechen)
|
||||
- Review-First-Policy: Ein Feature gilt erst dann als „fertig“, wenn es einen asynchronen Code-Review-Prozess durchlaufen hat. Das Meeting dient nur noch der Klärung von Blockern, nicht der Präsentation von Code. Das war eigentlich schon von Anfang an in unserer `Definition of Done` festgelegt worden.
|
||||
- Entkoppelung von Meeting und Deadline: Meetings sollten der Synchronisation dienen, während die Abgabe von Arbeitspaketen kontinuierlich (Continuous Integration) erfolgen muss, um Lastspitzen (in der [Gitea Actions](#Continuous Integration) Pipeline) am Tag der Besprechung zu vermeiden.
|
||||
@@ -338,10 +365,11 @@ Für den tatsächlichen Versand der E-Mails nutzen wir den Cloud-Dienst Brevo. D
|
||||
Das Token Lifetime Modul wurde geschrieben, um die Token-Lebenszeit konfigurierbar zu machen. Notwendig war das, um die Passwort Reset Links im initialen Mail versand länger gultig sein zu lassen. Durch das `Batch Processing` war es Möglich, dass eine Mail erst Tage nach erstellen des Links hinaus geschickt wird und bei einer Standard Ablaufdauer von 2 Tagen sind machne Links schon ungültig, bis sie den Mail Server erreichen. Ziel war es, die Änderung der Lebenszeit für Administratoren im User Interface im Admin Bereich möglich zu machen.
|
||||
|
||||
Es gibt 2 Möglichkeiten, wie man dieses Problem Lösen kann:
|
||||
- `der Workarround`: Ein eigenes Modul, welches in seiner `Server/Startup.cs` die benötigten Werte korrekt setzt. Das hat den Vorteil, dass wir keine Änderungen im CMS selbst haben, sondern nur unsere eigene Erweiterung dafür schreiben. Andererseits könnte durch die undeterminischte Ladereihenfolge eine `race-condition` auftreten. Darüberhinaus haben wir keinen gleichzeitigen Zugriff auf appsettings.json und den IServiceProvider in dem wir die Konfiguration setzen müssen. => Nachdem wir in der Konfigurationsphase auch noch keinen Datenbankzugriff haben, können wir die Werte nicht aus der DB Laden, sondern müssen auf eine Text Datei zurückgreifen.
|
||||
- `die saubere Lösung`: Eine Änderung im Kern von Oqtane. Also implementieren wir in unserem Fork von Oqtane die Konfigurationslogik für die Tokenlifetime. Hier könnte die Konfigurationslogik direkt in `OqtaneServiceCollectionExtensions.cs` hinzufügen, hier werden auch alle anderen Oqtane Spezifischen Configurationen gesetzt. Das hat den Vorteil, dass der Code aufgeräumter und sauberer ist und die `race-condition` verhindert werden kann. Der initiale Grund dagegen ist, dass wir ein weiteres Git Repository zum warten haben (den Fork vom Oqtane.Framework), welches jetzt nicht mehr mit Upstream Commit-gleich ist.
|
||||
|
||||
`Der Workarround` ist die Möglichkeit für die wir uns zuerst entschieden haben, allerdings haben wir uns im Nachhinein noch umentschlossen und wollen `die saubere Lösung` implementieren.
|
||||
- `der Workarround`: Ein eigenes Modul, welches in seiner `Server/Startup.cs` die benötigten Werte korrekt setzt. Das hat den Vorteil, dass wir keine Änderungen im CMS selbst haben, sondern nur unsere eigene Erweiterung dafür schreiben. Andererseits könnte durch die undeterminischte Ladereihenfolge eine `race-condition` auftreten. Darüberhinaus haben wir keinen gleichzeitigen Zugriff auf appsettings.json und den IServiceProvider in dem wir die Konfiguration setzen müssen. => Nachdem wir in der Konfigurationsphase auch noch keinen Datenbankzugriff haben, können wir die Werte nicht aus der DB Laden, sondern müssen auf eine Text Datei zurückgreifen.
|
||||
- `die saubere Lösung`: Eine Änderung im Kern von Oqtane. Also implementieren wir in unserem Fork von Oqtane die Konfigurationslogik für die Tokenlifetime. Hier könnte die Konfigurationslogik direkt in `OqtaneServiceCollectionExtensions.cs` hinzufügen, hier werden auch alle anderen Oqtane Spezifischen Configurationen gesetzt. Das hat den Vorteil, dass der Code aufgeräumter und sauberer ist und die `race-condition` verhindert werden kann. Der initiale Grund dagegen ist, dass wir ein weiteres Git Repository zum warten haben (den Fork vom Oqtane.Framework), welches jetzt nicht mehr mit Upstream Commit-gleich ist.
|
||||
|
||||
`Der Workarround` ist die Möglichkeit für die wir uns zuerst entschieden haben, allerdings haben wir uns im Nachhinein noch umentschlossen und wollen `die saubere Lösung` implementieren.
|
||||
|
||||
((Quellen einfügen: Configure Token for Email versand und Race Conditions beschreiben.))
|
||||
|
||||
@@ -350,6 +378,7 @@ Es gibt 2 Möglichkeiten, wie man dieses Problem Lösen kann:
|
||||
Eine weitere Anforderung der Diplomarbeit war es Einträge in Modulen wie der `Hall of Fame`, dem `Schwarzen Brett` und dem Premium Bereich (`Engineer Applications`) melden zu können. Am Anfang war es wichtig, dass jeder schnell vorrankommt, allerdings haben wir die Kommunikation Teamintern ein wenig verschlafen und dadurch ein paar Funktionen doppelt geschrieben. Dadurch kam es zu inkonsistenzen in der Verwendung der unterschiedlichen Reporting Systeme. Deswegen haben wir uns am Ende für eine globales Reporting System entschieden.
|
||||
|
||||
Angestrebt wurde folgender Ablauf für das Melden eines Eintrags:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Module
|
||||
@@ -358,12 +387,12 @@ sequenceDiagram
|
||||
participant ReportingHandler
|
||||
User->>+Module: View: Entity
|
||||
User->>+ReportingComponent: Report current Entity
|
||||
|
||||
|
||||
rect rgba(0, 0, 0, 0)
|
||||
ReportingComponent->>+User: Ask for reason
|
||||
User->>-ReportingComponent: Enters Reason
|
||||
end
|
||||
|
||||
|
||||
ReportingComponent->>+ReportingHandler: New Report (includes entity and reason)
|
||||
ReportingComponent->>-User: Done
|
||||
```
|
||||
@@ -387,4 +416,5 @@ Die Implementierung des IReportingComponents stellt nur eine Property (`ReportTy
|
||||
Die Bereitstellund des Moduls geschieht im `AdminModules` Modul.
|
||||
|
||||
## Event Registration
|
||||
## Schwarzes Brett
|
||||
|
||||
## Schwarzes Brett
|
||||
|
||||
Grammatik: Genitiv von 'Projekt' ist im förmlichen Kontext vorzugsweise 'Projekts' oder 'Projektes'.