Strukturierung des Projekts
Lino wurde entwickelt, um die Erstellung skalierbarer und modularer Projekte effizient zu vereinfachen. Es bietet eine gut strukturierte Lösung mit einer klaren Trennung der Verantwortlichkeiten zwischen den Schichten und ist bereit, mit den Anforderungen Ihres Projekts zu wachsen.
Beim Erstellen eines Projekts mit Lino erstellen Sie eine .NET-Lösung, die nach den besten Praktiken der Architektur und Modularisierung organisiert ist, mit Fokus auf Leistung, Skalierbarkeit und Wartungsfreundlichkeit.
Erstellen eines neuen Projekts
Der Befehl lino project erleichtert das Erstellen neuer .NET-Projekte auf einfache und effiziente Weise. Damit können Sie die Struktur Ihres Projekts einrichten, die erforderlichen AbhÀngigkeiten auswÀhlen und Spracheinstellungen sowie Infrastruktur konfigurieren.
Um ein neues Projekt zu erstellen, verwenden Sie den folgenden Befehl:
lino project new
WĂ€hrend der AusfĂŒhrung fordert die CLI die folgenden Informationen an:
- Projekt-Namespace: Definiert den Haupt-Namespace der Lösung.
- Anzeige-Name: Benutzerfreundlicher Name, der in den Schnittstellen angezeigt wird.
- Programmiersprache: Derzeit wird nur C# (.NET) unterstĂŒtzt.
- Entwicklungsstack: Derzeit .NET 10 mit Aspire.
- Code-Analyzer verwenden? WĂ€hlen Sie Ja oder Nein.
- Verwenden von verteiltem Cache? WĂ€hlen Sie Ja oder Nein.
- Verwenden von asynchroner Kommunikation? WĂ€hlen Sie Ja oder Nein.
- Datensprache: Definiert die Sprache, die fĂŒr die Namen der EntitĂ€ten und andere im System angegebenen Daten verwendet wird.
- UnterstĂŒtzte Sprachen der Anwendung: Ermöglicht das HinzufĂŒgen von UnterstĂŒtzung fĂŒr bis zu 10 Sprachen zur Internationalisierung (i18n).
- Standardsprache: Definiert die Hauptsprache, die in APIs, RĂŒckmeldungen, Validierungen und in der BenutzeroberflĂ€che verwendet wird.
Nachdem Sie die Informationen bestÀtigt haben, erstellt Lino automatisch die Projektstruktur, wie unten gezeigt:
MyApp/
âââ MyApp.sln
âââ src/
â âââ Aspire/
â â âââ AppHost/
â â â âââ MyApp.AppHost.csproj
â â âââ ServiceDefaults/
â â âââ MyApp.ServiceDefaults.csproj
â âââ Services/
â âââ Shared/
â âââ Api/
â â âââ MyApp.Shared.Api.csproj
â âââ Application/
â â âââ MyApp.Shared.Application.csproj
â âââ Domain/
â â âââ MyApp.Shared.Domain.csproj
â âââ Infrastructure/
â â âââ MyApp.Shared.Infrastructure.csproj
â âââ Infrastructure.Persistence/
â âââ MyApp.Shared.Infrastructure.Persistence.csproj
âââ tests/
Code-Analyzer
Statische Code-Analyzer sind leistungsstarke Tools, die dazu beitragen, die QualitĂ€t und Konsistenz des Codes wĂ€hrend der Entwicklung zu gewĂ€hrleisten. Sie tun dies, indem sie den Quellcode inspizieren, ohne dass eine AusfĂŒhrung erforderlich ist, und Fehler, Stilprobleme und andere Inkonsistenzen erkennen.
Wenn Sie sich entscheiden, wĂ€hrend der Erstellung des Projekts die Code-Analyzer zu aktivieren, wird die CLI automatisch die folgenden Pakete fĂŒr Sie konfigurieren:
- StyleCop.Analyzers: FĂŒhrt Code-StilprĂŒfungen durch, wie z.B. EinrĂŒckung, AbstĂ€nde und Namenskonventionen.
- SonarAnalyzer.CSharp: Ein Regelwerk zur CodequalitĂ€t und Sicherheit, das hilft, hĂ€ufige Fehler und potenzielle SicherheitslĂŒcken im Code zu erkennen.
- Roslynator.Analyzers: Bietet eine Vielzahl von QualitĂ€tsregeln und Verbesserungen fĂŒr C#-Code, um Refaktorisierungs- und Optimierungsmöglichkeiten zu identifizieren.
Vorteile der Code-Analyzer:
- Verbesserung der QualitÀt: Sie helfen, den Code sauber, lesbar und frei von hÀufigen Problemen zu halten.
- FehlerprĂ€vention: Sie erkennen Fehler, bevor sie ausgefĂŒhrt werden, sodass der Entwickler Probleme frĂŒhzeitig im Prozess beheben kann.
- Standardisierung: Sie stellen sicher, dass alle Entwickler die gleichen Konventionen und Stilregeln einhalten, was die Konsistenz des Codes verbessert.
- UnterstĂŒtzte Refaktorisierung: Sie erleichtern die Refaktorisierung des Codes und bieten VerbesserungsvorschlĂ€ge.
Mit der Aktivierung der Code-Analyzer haben Sie eine proaktive Möglichkeit, die QualitÀt Ihres Codes zu verbessern und das Risiko von Fehlern in der Produktionsumgebung zu verringern.
Verteiltes Cache
Verteiltes Caching ist eine Technik, die verwendet wird, um die Leistung und Skalierbarkeit von Anwendungen zu verbessern, indem hĂ€ufig abgerufene Daten in einer externen Cache-Schicht zum Datenbank gespeichert werden. Es ermöglicht den Instanzen der Anwendung, Daten effizient zu teilen, was hohe VerfĂŒgbarkeit und kĂŒrzere Antwortzeiten gewĂ€hrleistet.
Wenn Sie sich entscheiden, das verteilte Caching wĂ€hrend der Erstellung Ihres Projekts zu aktivieren, wird Redis in Ihren Aspire-Container integriert, um ein hochverfĂŒgbares Caching-System bereitzustellen.
Vorteile des verteilten Cache:
- Leistungsverbesserung: Reduziert die Antwortzeit von Anfragen, indem der Zugriff auf die Datenbank minimiert wird.
- Skalierbarkeit: Ermöglicht es der Anwendung, horizontal zu skalieren, da der Cache von verschiedenen Instanzen transparent abgerufen werden kann.
- Hohe VerfĂŒgbarkeit: Mit Redis bleibt der Cache selbst bei AusfĂ€llen verfĂŒgbar und bietet eine robuste Lösung fĂŒr verteilte Systeme.
- Kostensenkung: Verringert die Last auf der Datenbank und im System, wodurch die Notwendigkeit fĂŒr aufwendige Verarbeitung bei wiederholten Anfragen reduziert wird.
Mit der Aktivierung des verteilten Caches verbessern Sie die Leistung Ihrer Anwendung erheblich und garantieren eine schnellere Antwortzeit fĂŒr Benutzer, wĂ€hrend Sie die Last auf Backend-Systemen verringern.
Asynchrone Kommunikation
Asynchrone Kommunikation ist ein Ansatz, der es Systemen und Komponenten ermöglicht, auf nicht blockierende Weise zu kommunizieren, d.h., ohne dass das Senden oder Empfangen von Daten die Verarbeitung anderer Aufgaben unterbricht. Dies ist besonders nĂŒtzlich in verteilten Systemen und in Situationen mit hoher Last, in denen Effizienz und Resilienz entscheidend sind.
Wenn Sie sich entscheiden, asynchrone Kommunikation zu aktivieren, wird RabbitMQ in Ihr Projekt integriert und MassTransit wird konfiguriert, um die Verwendung dieser asynchronen Kommunikation in Ihrer Anwendung zu erleichtern.
Vorteile der asynchronen Kommunikation:
- Verbessertes Leistung: Ermöglicht parallele Operationen, ohne den Ablauf des Systems zu blockieren.
- Skalierbarkeit: Erleichtert die Skalierung des Systems, sodass es groĂe Datenmengen und gleichzeitige Benutzer ohne Leistungsverlust verarbeiten kann.
- Resilienz: Bei temporĂ€ren AusfĂ€llen können Nachrichten neu verarbeitet oder fĂŒr eine spĂ€tere Verarbeitung gespeichert werden.
- Entkopplung: Systeme können so entworfen werden, dass sie ohne direkte AbhÀngigkeit von sofortigen Antworten kommunizieren, was mehr FlexibilitÀt und Organisation fördert.
Die Integration mit RabbitMQ und die Verwendung von MassTransit machen die Kommunikation zwischen den Komponenten effizienter und robuster und tragen so zur Skalierbarkeit und FlexibilitÀt Ihrer Anwendung bei.
NĂ€chste Schritte
Jetzt, da Sie Ihr .NET-Projekt mit Lino erstellt haben, öffnen Sie es in Ihrem bevorzugten Code-Editor. Sie können Visual Studio, Visual Studio Code oder jede andere IDE Ihrer Wahl verwenden.
Sobald das Projekt geöffnet ist, können Sie beginnen, die Dienste hinzuzufĂŒgen und zu konfigurieren, die Ihre Anwendung ausmachen. Dies ist der nĂ€chste Schritt im Entwicklungsprozess.
In der nĂ€chsten Sektion zeigen wir Ihnen, wie Sie diese Dienste in Ihrem neuen Projekt erstellen und konfigurieren, um es fĂŒr eine organisierte und skalierbare Weiterentwicklung gemÀà den Anforderungen Ihrer Anwendung vorzubereiten.
Erstellen und Verwalten von Diensten
Nachdem das Projekt erstellt wurde, ist der nĂ€chste Schritt, Dienste hinzuzufĂŒgen. Lino bietet eine einfache und intuitive Möglichkeit, Dienste zu erstellen, die in monolithischen Systemen oder Mikroservice-Architekturen verwendet werden können.
Um einen neuen Dienst zu erstellen, verwenden Sie den folgenden Befehl:
lino service new
WĂ€hrend der AusfĂŒhrung fordert die CLI die folgenden Informationen an:
- Namespace des Dienstes: Definiert den Namen und den Namespace des Dienstes.
- Anzeige Name: Der benutzerfreundliche Name, der in den Schnittstellen angezeigt wird.
- Diensttyp: WĂ€hlen Sie zwischen Einfach oder Modular.
- Datenbank: WĂ€hlen Sie zwischen PostgreSQL oder SQL Server.
Wenn der gewÀhlte Diensttyp Einfach ist, werden auch die folgenden Informationen abgefragt:
- Architekturstil: Derzeit nur Clean Architecture.
- Strongly Typed ID verwenden? WĂ€hlen Sie zwischen Ja oder Nein.
Arten von Diensten
Einfacher Dienst: Ein einfacher Dienst hat eine schlankere Struktur und ist fĂŒr monolithische Systeme oder Mikroservice-Projekte geeignet, bei denen jeder Dienst eine unabhĂ€ngige Verantwortung hat.
Modularer Dienst: FĂŒr gröĂere Systeme, die eine bessere Organisation und Skalierbarkeit erfordern, können Sie sich fĂŒr einen modularen Dienst entscheiden. Dieser Typ ermöglicht es, den Dienst in kleinere, spezifischere Module zu unterteilen, was die Wartung und das Wachstum des Systems erleichtert.
Ob einfacher oder modularer Dienst, die Datenbank wird fĂŒr jeden Dienst einzigartig sein. Die Architektur und die Verwendung von Strongly Typed IDs gelten fĂŒr einfache Dienste. Im Fall von modularen Diensten wird diese Entscheidung auf Ebene jedes Moduls getroffen, das innerhalb des Dienstes erstellt wird.
Die Struktur von Lino ist flexibel und ermöglicht die Erstellung von einfachen und modularen Diensten innerhalb desselben Projekts.
Architekturstil
Lino verwendet bereits Clean Architecture fĂŒr alle Dienste. Dies stellt sicher, dass Ihre Anwendung einer gut strukturierten Architektur folgt, die die Trennung von Verantwortlichkeiten fördert und Wartbarkeit sowie Skalierbarkeit erleichtert.
Vorteile von Clean Architecture:
- Entkopplung: Die GeschÀftslogik ist von technischen Details unabhÀngig, was mehr FlexibilitÀt und Testbarkeit ermöglicht.
- Wartbarkeit: Da die Schichten gut voneinander getrennt sind, können Ănderungen vorgenommen werden, ohne andere Teile des Systems zu beeintrĂ€chtigen.
- Testbarkeit: Die Trennung von Anliegen erleichtert das Erstellen von Unit- und Integrationstests fĂŒr jede Schicht unabhĂ€ngig.
- Skalierbarkeit: Das Projekt ist leichter skalierbar, da Komponenten geÀndert oder ausgetauscht werden können, ohne die GeschÀftslogik zu beeintrÀchtigen.
Wenn Sie sich entscheiden, einen einfachen Dienst mit der Implementierung von Clean Architecture zu erstellen, wird das Projekt mit der folgenden Struktur generiert:
MyApp/
âââ MyApp.sln
âââ src/
â âââ Aspire/
â â âââ AppHost/
â â â âââ MyApp.AppHost.csproj
â â âââ ServiceDefaults/
â â âââ MyApp.ServiceDefaults.csproj
â âââ Services/
â âââ Shared/
â â âââ Api/
â â â âââ MyApp.Shared.Api.csproj
â â âââ Application/
â â â âââ MyApp.Shared.Application.csproj
â â âââ Domain/
â â â âââ MyApp.Shared.Domain.csproj
â â âââ Infrastructure/
â â â âââ MyApp.Shared.Infrastructure.csproj
â â âââ Infrastructure.Persistence/
â â âââ MyApp.Shared.Infrastructure.Persistence.csproj
â âââ MySimpleService/
â âââ Api/
â â âââ MyApp.MySimpleService.Api.csproj
â âââ Application/
â â âââ MyApp.MySimpleService.Application.csproj
â âââ Domain/
â â âââ MyApp.MySimpleService.Domain.csproj
â âââ Infrastructure/
â â âââ MyApp.MySimpleService.Infrastructure.csproj
â âââ Infrastructure.Persistence/
â â âââ MyApp.MySimpleService.Infrastructure.Persistence.csproj
â âââ Integration.Events/
â âââ MyApp.MySimpleService.Integration.Events.csproj
âââ tests/
Wenn Sie einen modularen Dienst wĂ€hlen, wird das Projekt die folgende Struktur ĂŒbernehmen, die das HinzufĂŒgen neuer Module im Verlauf der Dienstentwicklung flexibel und organisiert ermöglicht:
MyApp/
âââ MyApp.sln
âââ src/
â âââ Aspire/
â â âââ AppHost/
â â â âââ MyApp.AppHost.csproj
â â âââ ServiceDefaults/
â â âââ MyApp.ServiceDefaults.csproj
â âââ Services/
â âââ Shared/
â â âââ Api/
â â â âââ MyApp.Shared.Api.csproj
â â âââ Application/
â â â âââ MyApp.Shared.Application.csproj
â â âââ Domain/
â â â âââ MyApp.Shared.Domain.csproj
â â âââ Infrastructure/
â â â âââ MyApp.Shared.Infrastructure.csproj
â â âââ Infrastructure.Persistence/
â â âââ MyApp.Shared.Infrastructure.Persistence.csproj
â âââ MyModularService/
â âââ Host/
â â âââ MyApp.MyModularService.Host.csproj
â âââ Infrastructure/
â â âââ MyApp.MyModularService.Infrastructure.csproj
â âââ Modules/
âââ tests/
Strongly Typed ID
Strongly Typed ID ist ein Ansatz, der darauf abzielt, die Sicherheit und Klarheit des Codes zu verbessern, indem er sicherstellt, dass Identifizierer (IDs) spezifischer und stark typisiert sind, um die Verwendung von generischen Typen wie int oder guid zur Darstellung eindeutiger EntitÀten zu vermeiden.
Mit Strongly Typed ID wĂŒrden Sie anstelle von generischen Typen, wie einer Ganzzahl zur Darstellung einer Benutzer-ID, einen spezifischen Typ fĂŒr die Benutzer-ID erstellen. Dies hilft, hĂ€ufige Fehler zu vermeiden, wie die falsche Verwendung von IDs unterschiedlicher Typen in falschen Kontexten.
Vorteile der Verwendung von Strongly Typed IDs:
- Typensicherheit: Stellt sicher, dass IDs korrekt verwendet werden, und vermeidet die Mischung verschiedener Identifizierer, wie Benutzer-IDs und Produkt-IDs.
- Klarheit: Der Code wird klarer, da jeder ID-Typ explizit durch eine spezifische Klasse dargestellt wird.
- Leichtere Refaktorisierung: Wenn der ID-Typ geÀndert werden muss, Àndern Sie nur den spezifischen ID-Typ, und der restliche Code bleibt sicher.
- Vermeidung von Fehlern: Reduziert die Wahrscheinlichkeit von Fehlern durch unsachgemĂ€Ăe Verwendung generischer Identifizierer in falschen Kontexten.
Erstellen und Verwalten von Modulen
Nachdem ein modularer Dienst erstellt wurde, besteht der nĂ€chste Schritt darin, Module hinzuzufĂŒgen. Module ermöglichen es, die GeschĂ€ftslogik unabhĂ€ngig zu organisieren und bringen noch mehr Skalierbarkeit und Struktur in das System.
Um ein neues Modul zu erstellen, verwenden Sie den folgenden Befehl:
lino module new
WĂ€hrend der AusfĂŒhrung fordert die CLI die folgenden Informationen an:
- Dienst: Definiert, zu welchem Dienst das neue Modul gehört.
- Modul-Namespace: Definiert den Namen und Namespace des Moduls.
- Anzeigename: Benutzerfreundlicher Name, der in den BenutzeroberflÀchen angezeigt wird.
- Architekturstil: Derzeit nur Clean Architecture verfĂŒgbar.
- Stark typisierte ID verwenden? WĂ€hlen Sie zwischen Ja oder Nein.
Am Ende generiert Lino das neue Modul und behÀlt die Struktur Ihres modularen Dienstes bei:
MyApp/ âââ MyApp.sln âââ src/ â âââ Aspire/ â â âââ AppHost/ â â â âââ MyApp.AppHost.csproj â â âââ ServiceDefaults/ â â âââ MyApp.ServiceDefaults.csproj â âââ Services/ â âââ Shared/ â â âââ Api/ â â â âââ MyApp.Shared.Api.csproj â â âââ Application/ â â â âââ MyApp.Shared.Application.csproj â â âââ Domain/ â â â âââ MyApp.Shared.Domain.csproj â â âââ Infrastructure/ â â â âââ MyApp.Shared.Infrastructure.csproj â â âââ Infrastructure.Persistence/ â â âââ MyApp.Shared.Infrastructure.Persistence.csproj â âââ MyModularService/ â âââ Host/ â â âââ MyApp.MyModularService.Host.csproj â âââ Infrastructure/ â â âââ MyApp.MyModularService.Infrastructure.csproj â âââ Modules/ â âââ MyModule/ â âââ Api/ â â âââ MyApp.MyModularService.MyModule.Api.csproj â âââ Application/ â â âââ MyApp.MyModularService.MyModule.Application.csproj â âââ Domain/ â â âââ MyApp.MyModularService.MyModule.Domain.csproj â âââ Infrastructure/ â â âââ MyApp.MyModularService.MyModule.Infrastructure.csproj â âââ Infrastructure.Persistence/ â â âââ MyApp.MyModularService.MyModule.Infrastructure.Persistence.csproj â âââ Integration.Events/ â âââ MyApp.MyModularService.MyModule.Integration.Events.csproj âââ tests/
Datenbankstruktur
Es ist wichtig zu beachten, dass die Datenbank mit dem Dienst verbunden ist. Innerhalb eines modularen Dienstes wird jedes Modul durch sein eigenes Schema in der zugehörigen Datenbank reprÀsentiert. Dieser Ansatz bietet Isolation und Organisation, ohne dass mehrere verschiedene Datenbanken erforderlich sind.
Ăber die UnabhĂ€ngigkeit zwischen Modulen
Ebenso wie Dienste keine direkten AbhÀngigkeiten untereinander haben, werden auch Module als unabhÀngige Projekte innerhalb des Dienstes erstellt.
Vorteile dieser Entkopplung:
- Isolation: Jedes Modul kann unabhÀngig weiterentwickelt werden, was Wartung und kontinuierliche Verbesserung erleichtert.
- Organisation: Die Anwendung wird wirklich modular, respektiert die Grenzen des Kontexts (Bounded Contexts) und fördert gute Architekturpraktiken.
- FlexibilitĂ€t: Ermöglicht das HinzufĂŒgen, Entfernen oder Refaktorieren von Modulen, ohne andere Module direkt zu beeinflussen.
- Testbarkeit: Jedes Modul kann isoliert getestet werden, was die ZuverlÀssigkeit und QualitÀt des Systems erhöht.
Damit schlieĂen wir den Prozess der Modulerstellung ab. In den nĂ€chsten Themen werden wir sehen, wie interne Elemente eines Moduls wie EntitĂ€ten, Wertobjekte, AufzĂ€hlungen, Befehle, Abfragen, APIs, Integrationen und vieles mehr strukturiert werden.
