Structuration du projet

Lino a été développé pour simplifier la création de projets évolutifs et modulaires de manière efficace. Il offre une solution bien structurée, avec une séparation claire des responsabilités entre les couches, et est prêt à évoluer selon les besoins de votre projet.


Lors de la création d'un projet avec Lino, vous générez une solution .NET organisée selon les meilleures pratiques d'architecture et de modularisation, en mettant l'accent sur les performances, l'évolutivité et la facilité de maintenance.

Création d'un Nouveau Projet

La commande lino project facilite la création de nouveaux projets .NET de manière simple et efficace. Avec elle, vous pouvez configurer la structure de votre projet, sélectionner les dépendances nécessaires et définir les configurations de langue et d'infrastructure.

Pour créer un nouveau projet, utilisez la commande suivante :

lino project new

Lors de l'exécution, l'outil CLI vous demandera les informations suivantes :

  • Espace de noms du Projet : DĂ©finit l'espace de noms principal de la solution.
  • Nom d'Affichage : Nom convivial affichĂ© dans les interfaces.
  • Langage de Programmation : Actuellement, seul le C# (.NET) est pris en charge.
  • Stack de DĂ©veloppement : Actuellement .NET 9 avec Aspire.
  • Utiliser des Analyseurs de Code ? Choisissez entre Oui ou Non.
  • Utiliser un Cache DistribuĂ© ? Choisissez entre Oui ou Non.
  • Utiliser la Communication Asynchrone ? Choisissez entre Oui ou Non.
  • Langue des DonnĂ©es : DĂ©finit la langue utilisĂ©e pour les noms des entitĂ©s et autres donnĂ©es dans le système.
  • Langues SupportĂ©es par l'Application : Permet d'ajouter la prise en charge jusqu'Ă  10 langues pour l'internationalisation (i18n).
  • Langue par DĂ©faut : DĂ©finit la langue principale utilisĂ©e dans les API, les messages de retour, les validations et l'interface utilisateur.

Après avoir confirmé les informations, Lino créera automatiquement la structure du projet, comme indiqué ci-dessous :

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/
    

Analyseurs de Code

Les analyseurs de code statique sont des outils puissants qui aident à garantir la qualité et la cohérence du code pendant le développement. Ils le font en inspectant le code source sans exécution, détectant les erreurs, les problèmes de style et d'autres incohérences.

Lorsque vous choisissez d'activer les analyseurs de code lors de la création du projet, l'outil CLI configurera automatiquement les paquets suivants pour vous :

  • StyleCop.Analyzers : Effectue des vĂ©rifications de style de code, telles que la mise en forme des indentations, les espacements et les conventions de nommage.
  • SonarAnalyzer.CSharp : Un ensemble de règles de qualitĂ© du code et de sĂ©curitĂ©, qui aide Ă  dĂ©tecter les dĂ©fauts courants et les vulnĂ©rabilitĂ©s potentielles dans le code.
  • Roslynator.Analyzers : Offre une variĂ©tĂ© de règles de qualitĂ© et d'amĂ©liorations pour le code C#, aidant Ă  identifier des opportunitĂ©s de refactorisation et d'optimisation.

Avantages des Analyseurs de Code :

  • AmĂ©lioration de la QualitĂ© : Ils aident Ă  maintenir le code propre, lisible et exempt de problèmes courants.
  • PrĂ©vention des Erreurs : Ils dĂ©tectent les erreurs avant qu'elles ne soient exĂ©cutĂ©es, permettant au dĂ©veloppeur de corriger les problèmes tĂ´t dans le processus.
  • Standardisation : Ils garantissent que tous les dĂ©veloppeurs suivent les mĂŞmes conventions et règles de style, amĂ©liorant la cohĂ©rence du code.
  • Refactorisation AssistĂ©e : Ils facilitent la refactorisation du code en offrant des suggestions d'amĂ©lioration.

En activant les analyseurs de code, vous avez une méthode proactive pour améliorer la qualité de votre code et réduire le risque d'échecs en production.

Caché Distribué

Le cache distribué est une technique utilisée pour améliorer les performances et l'évolutivité des applications, en stockant les données fréquemment accédées dans une couche de cache externe à la base de données. Il permet aux instances de l'application de partager efficacement les données mises en cache, garantissant une haute disponibilité et une réduction du temps de réponse.

Si vous choisissez d'activer le cache distribué lors de la création de votre projet, Redis sera intégré à votre conteneur Aspire, offrant un système de cache à haute disponibilité.

Avantages du Cache Distribué :

  • AmĂ©lioration des Performances : RĂ©duit le temps de rĂ©ponse des demandes en minimisant l'accès Ă  la base de donnĂ©es.
  • ScalabilitĂ© : Permet de faire Ă©voluer l'application horizontalement, car le cache peut ĂŞtre accĂ©dĂ© par diffĂ©rentes instances de manière transparente.
  • Haute DisponibilitĂ© : Avec Redis, le cache reste disponible mĂŞme en cas de dĂ©faillance, offrant une solution robuste pour les systèmes distribuĂ©s.
  • RĂ©duction des CoĂ»ts : RĂ©duit la charge sur la base de donnĂ©es et sur le système, diminuant ainsi le besoin de traitement pour les demandes rĂ©pĂ©titives.

En activant le cache distribué, vous améliorez considérablement les performances de votre application, garantissant une réponse plus rapide aux utilisateurs et réduisant la charge sur les systèmes backend.

Communication Asynchrone

La communication asynchrone est une approche qui permet aux systèmes et aux composants de communiquer de manière non bloquante, c'est-à-dire sans que l'envoi ou la réception de données n'interrompe le traitement des autres tâches. Cela est particulièrement utile dans les systèmes distribués et en cas de forte charge, où l'efficacité et la résilience sont essentielles.

Si vous choisissez d'activer la communication asynchrone, RabbitMQ sera intégré à votre projet, et MassTransit sera configuré pour faciliter l'utilisation de cette communication asynchrone dans votre application.

Avantages de la Communication Asynchrone :

  • AmĂ©lioration des Performances : Permet d'exĂ©cuter les opĂ©rations en parallèle sans bloquer le flux d'exĂ©cution du système.
  • ScalabilitĂ© : Facilite l'Ă©volutivitĂ© du système, lui permettant de traiter de grands volumes de donnĂ©es et des utilisateurs simultanĂ©s sans perdre de performance.
  • RĂ©silience : En cas de dĂ©faillance temporaire, la communication asynchrone permet de retraiter ou de stocker les messages pour un traitement ultĂ©rieur.
  • DĂ©couplage : Les systèmes peuvent ĂŞtre conçus pour communiquer sans dĂ©pendre directement de rĂ©ponses immĂ©diates, offrant ainsi plus de flexibilitĂ© et d'organisation.

L'intégration avec RabbitMQ et l'utilisation de MassTransit rendent la communication entre les composants plus efficace et résiliente, contribuant ainsi à garantir l'évolutivité et la flexibilité de votre application.

Étapes Suivantes

Maintenant que vous avez créé votre projet .NET avec Lino, ouvrez-le dans votre éditeur de code préféré. Vous pouvez utiliser Visual Studio, Visual Studio Code ou tout autre IDE de votre choix.

Une fois le projet ouvert, vous pouvez commencer à ajouter et configurer les services qui composent votre application. C'est la prochaine étape du flux de développement.

Dans la prochaine section, nous vous montrerons comment créer et configurer ces services dans votre nouveau projet, le préparant à se développer de manière organisée et évolutive en fonction des besoins de votre application.

Création et gestion des services

Après la création du projet, l'étape suivante consiste à ajouter des services. Lino offre un moyen simple et intuitif de créer des services, qui peuvent être utilisés dans des systèmes monolithiques ou des architectures de microservices.

Pour créer un nouveau service, utilisez la commande suivante :

lino service new

Lors de l'exécution, le CLI demandera les informations suivantes :

  • Namespace du service : DĂ©finit le nom et le namespace du service.
  • Nom d'affichage : Nom convivial affichĂ© dans les interfaces.
  • Type de service : Choisissez entre Simple ou Modulaire.
  • Base de donnĂ©es : Choisissez entre PostgreSQL ou SQL Server.

Si le type de service choisi est Simple, les informations suivantes seront également demandées :

  • Style architectural : Actuellement, seule la Clean Architecture est disponible.
  • Utiliser des Strongly Typed ID ? Choisissez entre Oui ou Non.

Types de service

Service simple : Un service simple a une structure plus légère, adaptée aux systèmes monolithiques ou aux projets de microservices où chaque service a une responsabilité indépendante.

Service modulaire : Pour les systèmes plus grands, nécessitant une plus grande organisation et évolutivité, vous pouvez opter pour un service modulaire. Ce type permet de diviser le service en modules plus petits et plus spécifiques, facilitant la maintenance et l'expansion du système.

Que le service soit simple ou modulaire, la base de données sera unique pour chaque service. L'architecture et l'utilisation des Strongly Typed IDs s'appliquent aux services simples. Pour les services modulaires, cette décision sera prise au niveau de chaque module créé au sein du service.

La structure de Lino est flexible, permettant de créer des services simples et modulaires au sein du même projet.

Style architectural

Lino applique déjà la Clean Architecture à tous les services. Cela garantit que votre application suit une architecture bien structurée, favorisant la séparation des responsabilités et facilitant la maintenance et l'évolutivité.

Avantages de la Clean Architecture :

  • DĂ©couplage : La logique mĂ©tier est indĂ©pendante des dĂ©tails techniques, offrant ainsi une plus grande flexibilitĂ© et testabilitĂ©.
  • MaintenabilitĂ© : Étant donnĂ© que les couches sont bien sĂ©parĂ©es, il est plus facile d'apporter des modifications sans affecter d'autres parties du système.
  • TestabilitĂ© : La sĂ©paration des prĂ©occupations facilite la crĂ©ation de tests unitaires et d'intĂ©gration pour chaque couche de manière indĂ©pendante.
  • ScalabilitĂ© : Le projet est plus facile Ă  faire Ă©voluer, car les composants peuvent ĂŞtre modifiĂ©s ou remplacĂ©s sans affecter la logique mĂ©tier.

Si vous choisissez de créer un service simple, en utilisant l'implémentation de Clean Architecture, le projet sera généré avec la structure suivante :

MyApp/
├── MyApp.sln
├── src/
│   ├── Aspire/
│   │   ├── AppHost/
│   │   │   └── MyApp.AppHost.csproj
│   │   └── ServiceDefaults/
│   │       └── MyApp.ServiceDefaults.csproj
│   ├── Integrations/
│   │   └── Internal/
│   │       └── MySimpleService/
│   │           └── Http/
│   │               ├── Clients/
│   │               │   └── MyApp.Integrations.MySimpleService.Http.Clients.csproj
│   │               └── Contracts/
│   │                   └── MyApp.Integrations.MySimpleService.Http.Contracts.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
│           └── IntegrationEvents/
│               └── MyApp.MySimpleService.IntegrationEvents.csproj
└── tests/
    └── Services/
        └── MySimpleService/
            ├── IntegrationTests/
            │   └── MyApp.MySimpleService.IntegrationTests.csproj
            └── UnitTests/
                └── MyApp.MySimpleService.UnitTests.csproj
    

Si vous choisissez un service modulaire, le projet adoptera la structure suivante, permettant l'ajout de nouveaux modules de manière flexible et organisée tout au long du développement du service :

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

Le Strongly Typed ID est une approche visant à améliorer la sécurité et la clarté du code en garantissant que les types d'identifiants (ID) sont plus spécifiques et fortement typés, évitant l'utilisation de types génériques tels que int ou guid pour représenter des entités uniques.

Avec le Strongly Typed ID, au lieu d'utiliser des types génériques tels qu'un entier pour représenter un identifiant d'utilisateur, vous créeriez un type spécifique pour l'ID de l'utilisateur. Cela permet d'éviter des erreurs courantes, comme l'utilisation incorrecte d'ID de types différents dans des contextes inappropriés.

Avantages de l'utilisation des Strongly Typed IDs :

  • SĂ©curitĂ© des types : Garantit que les ID sont utilisĂ©s correctement, en Ă©vitant la confusion entre diffĂ©rents types d'identifiants, tels que les ID d'utilisateurs et les ID de produits.
  • ClartĂ© : Le code devient plus clair, car chaque type d'ID est explicitement reprĂ©sentĂ© par une classe spĂ©cifique.
  • FacilitĂ© de refactorisation : Si le type d'identifiant doit changer, vous modifiez uniquement le type d'ID spĂ©cifique et le reste du code reste sĂ©curisĂ©.
  • Évite les erreurs : RĂ©duit le risque de bugs liĂ©s Ă  une mauvaise utilisation des identifiants gĂ©nĂ©riques dans des contextes incorrects.

Création et gestion des modules

Après avoir créé un service modulaire, l'étape suivante consiste à y ajouter des modules. Les modules permettent d'organiser la logique métier de manière indépendante, apportant ainsi plus de scalabilité et d'organisation au système.

Pour créer un nouveau module, utilisez la commande suivante :

lino module new

Lors de l'exécution, l'outil CLI demandera les informations suivantes :

  • Service : DĂ©finit Ă  quel service le nouveau module sera ajoutĂ©.
  • Namespace du module : DĂ©finit le nom et le namespace du module.
  • Nom d'affichage : Nom convivial affichĂ© dans les interfaces.
  • Style architectural : Actuellement, seul Clean Architecture est disponible.
  • Utiliser une ID fortement typĂ©e ? Choisissez entre Oui ou Non.

À la fin, Lino générera le nouveau module en préservant la structure de votre service modulaire :

MyApp/
├── MyApp.sln
├── src/
│   ├── Aspire/
│   │   ├── AppHost/
│   │   │   └── MyApp.AppHost.csproj
│   │   └── ServiceDefaults/
│   │       └── MyApp.ServiceDefaults.csproj
│   ├── Integrations/
│   │   └── Internal/
│   │       └── MyModularService/
│   │           └── MyModule/
│   │               └── Http/
│   │                   ├── Clients/
│   │                   │   └── MyApp.Integrations.MyModularService.MyModule.Http.Clients.csproj
│   │                   └── Contracts/
│   │                       └── MyApp.Integrations.MyModularService.MyModule.Http.Contracts.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
│                   └── IntegrationEvents/
│                       └── MyApp.MyModularService.MyModule.IntegrationEvents.csproj
└── tests/
    └── Services/
        └── MyModularService/
            └── Modules/
                └── MyModule/
                    ├── IntegrationTests/
                    │   └── MyApp.MyModularService.MyModule.IntegrationTests.csproj
                    └── UnitTests/
                        └── MyApp.MyModularService.MyModule.UnitTests.csproj

Structure de la base de données

Il est important de souligner que la base de données est liée au service. Dans un service modulaire, chaque module est représenté par son propre schéma dans la base de données associée. Cette approche permet l'isolation et l'organisation, sans avoir besoin de créer plusieurs bases de données distinctes.

À propos de l'indépendance entre les modules

Tout comme les services n'ont pas de dépendances directes entre eux, les modules sont également créés comme des projets indépendants au sein du service.

Avantages de cette découplage :

  • Isolation : Chaque module peut Ă©voluer de manière indĂ©pendante, facilitant ainsi la maintenance et l'Ă©volution continue.
  • Organisation : L'application devient vĂ©ritablement modulaire, respectant les limites du contexte (Bounded Contexts) et favorisant de bonnes pratiques d'architecture logicielle.
  • FlexibilitĂ© : Permet d'ajouter, de supprimer ou de refactoriser des modules sans affecter directement les autres modules du service.
  • FacilitĂ© de tests : Chaque module peut ĂŞtre testĂ© de manière isolĂ©e, augmentant ainsi la fiabilitĂ© et la qualitĂ© du système.

Ainsi, nous avons terminé le processus de création des modules. Dans les prochains sujets, nous verrons comment structurer les éléments internes d'un module, tels que les entités, les objets de valeur, les énumérations, les commandes, les requêtes, les API, les intégrations et bien plus encore.

Une erreur non gérée est survenue. Rafraîchir đź—™