New: Dependency Injection Grundlagen & Einleitung
All checks were successful
Word Count / count-words (pull_request) Successful in 33s

This commit is contained in:
2026-03-18 10:54:01 +00:00
parent 169a085a73
commit 20df216b08

View File

@@ -73,7 +73,7 @@ Ein Modul in Oqtane besteht aus vier Projekten:
## Systemarchitektur (Postgres / Oqtane / Nginx) ## 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 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. 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. In der folgenden Grafik ist das System Schematisch dargestellt.
```mermaid ```mermaid
architecture-beta architecture-beta
@@ -90,7 +90,15 @@ architecture-beta
oqtane:R <--> L:db oqtane:R <--> L:db
``` ```
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. 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. Der SSH Service ist in jeder Umgebung anders erreichbar gewesen.
| Umgebung | Administrationszugang |
| ---------- | --------------------- |
| Hetzner | Wireguard |
| Schule | Highport |
| LiveDesign | IPSEC VPN |
Die VPN basierten Zugänge sind tendenziell schwieriger zu finden und auszunutzen, während die Lösung in der Schule mittels Highport den SSH Service öffentlich erreichbar macht. Durch den `Highport` ist der SSH Service schwieriger zu finden. Zur Authentifizierung mit SSH verwenden wir SSH-Keys, da diese durch ihre komplexität sicherer sind, als Passwörter.
## Entwicklung mit ASP.NET (Was ist Blazor? / Was ist Razor? / Kestrel) ## Entwicklung mit ASP.NET (Was ist Blazor? / Was ist Razor? / Kestrel)
### Blazor [^7] ### Blazor [^7]
@@ -143,6 +151,14 @@ SignalR ist eine Library aus dem ASP.NET Framework, welche es möglich macht, Se
## Dependency Injection ## Dependency Injection
Dependency Injection ist ein Entwurfsmuster, bei dem die Abhängigkeiten eines Objekts nicht von diesem selbst erzeugt, sondern von außen „injiziert“ werden.
Wie der Software-Architekt Martin Fowler, der den Begriff im Jahr 2004 maßgeblich prägte, beschreibt, geht es im Kern darum, die Erzeugung von Objekten von deren Nutzung zu trennen [^9]. Anstatt dass eine Klasse ihre Hilfsobjekte mittels des new-Operators selbst instanziiert, werden ihr diese meist über den Konstruktor zur Verfügung gestellt.
In den folgenden beiden Kapiteln wird das Dependency Inversion Principle und das Microsoft Dependency Injection Framework genauer vorgestellt.
[^9]: https://martinfowler.com/articles/injection.html
### Dependency Inversion Principle [^1] ### 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 Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines von den fünf `SOLID` Prinzipien in der Softwareentwicklung.
@@ -156,10 +172,8 @@ Ausgangslage ist eine Softwarearchitektur im Direct-Dependency-Graph-Modell.
architecture-beta 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] service b(mdi:package-variant-closed)[Klasse B]
service c(mdi:package-variant-closed)[Klasse C]
a:R --> L:b a:R --> L:b
b:R --> L:c
``` ```
Bei diesem Beispiel ist die Klasse A ein high-level Modul, welches direkt auf die Klasse B referenziert, was das DI-Prinzip verbietet. 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. 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.
@@ -169,13 +183,9 @@ 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] service b(mdi:package-variant-closed)[Klasse B]
service ib(mdi:car-clutch)[Interface B] service ib(mdi:car-clutch)[Interface B]
service c(mdi:package-variant-closed)[Klasse C]
service ic(mdi:car-clutch)[Interface C]
a:B --> T:ib a:B --> T:ib
ib:R <-- L:b ib:R <-- L:b
b:B --> T:ic
ic:R <-- L:c
``` ```
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. 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.
@@ -307,7 +317,7 @@ Um das Projektziel dennoch zu erreichen, wurde der Zeitplan im Herbst 2025 massi
(Jon Bentley. 1985. Programmimg pearls. Commun. ACM 28, 9 (Sept. 1985), 896901. https://doi.org/10.1145/4284.315122) [^8] (Jon Bentley. 1985. Programmimg pearls. Commun. ACM 28, 9 (Sept. 1985), 896901. https://doi.org/10.1145/4284.315122) [^8]
Diese Diplomarbeit liefert weitere Evidenz, dass diese Faustregel stimmt. Diese Diplomarbeit liefert weitere Evidenz, dass diese Faustregel stimmt.
[^8](https://dl.acm.org/doi/10.1145/4284.315122) [^8]: https://dl.acm.org/doi/10.1145/4284.315122
## Sprints und Meetings (in Zukunft ja asynchron) ## Sprints und Meetings (in Zukunft ja asynchron)