Estruturando o Projeto

O Lino foi desenvolvido para simplificar a criação de projetos escaláveis e modulares de maneira eficiente. Ele oferece uma solução bem estruturada, com uma separação clara de responsabilidades entre as camadas, e está preparado para crescer conforme as necessidades do seu projeto evoluem.


Ao criar um projeto com o Lino, você gera uma solução .NET organizada segundo as melhores práticas de arquitetura e modularização, com foco em performance, escalabilidade e facilidade de manutenção.

Criando um Novo Projeto

O comando lino project facilita a criação de novos projetos .NET de forma simples e eficiente. Com ele, você pode configurar a estrutura do seu projeto, selecionar as dependências necessárias e definir configurações de idiomas e infraestrutura.

Para criar um novo projeto, utilize o seguinte comando:

lino project new

Durante a execução, o CLI solicitará as seguintes informações:

  • Namespace do Projeto: Define o namespace principal da solução.
  • Nome de Exibição: Nome amigável exibido nas interfaces.
  • Linguagem de Programação: Atualmente, Ă© suportado apenas C# (.NET).
  • Stack de Desenvolvimento: Atualmente, .NET 9 com Aspire.
  • Utilizar Analisadores de CĂłdigo? Escolha entre Sim ou NĂŁo.
  • Utilizar Cache DistribuĂ­do? Escolha entre Sim ou NĂŁo.
  • Utilizar Comunicação AssĂ­ncrona? Escolha entre Sim ou NĂŁo.
  • Idioma dos Dados: Define o idioma utilizado para os nomes das entidades e outros dados informados no sistema.
  • Idiomas Suportados pela Aplicação: Permite adicionar suporte a atĂ© 10 idiomas para internacionalização (i18n).
  • Idioma PadrĂŁo: Define o idioma principal utilizado em APIs, mensagens de retorno, validações e na interface do usuário.

Após confirmar as informações, o Lino criará automaticamente a estrutura do projeto, conforme ilustrado abaixo:

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/
    

Analisadores de CĂłdigo

Os analisadores de código estático são ferramentas poderosas que ajudam a garantir a qualidade e a consistência do código durante o desenvolvimento. Eles fazem isso inspecionando o código-fonte sem a necessidade de execução, detectando erros, problemas de estilo e outras inconsistências.

Quando você escolhe habilitar os analisadores de código durante a criação do projeto, o CLI configurará automaticamente os seguintes pacotes para você:

  • StyleCop.Analyzers: Realiza verificações de estilo de cĂłdigo, como formatação de indentação, espaçamento e convenções de nomenclatura.
  • SonarAnalyzer.CSharp: Um conjunto de regras de qualidade de cĂłdigo e segurança, que ajuda a detectar falhas comuns e potenciais vulnerabilidades no cĂłdigo.
  • Roslynator.Analyzers: Oferece uma variedade de regras de qualidade e melhorias para o cĂłdigo C#, ajudando a identificar oportunidades de refatoração e otimização.

Vantagens dos Analisadores de CĂłdigo:

  • Melhoria da Qualidade: Eles ajudam a manter o cĂłdigo limpo, legĂ­vel e livre de problemas comuns.
  • Prevenção de Erros: Detectam erros antes de serem executados, permitindo que o desenvolvedor corrija problemas cedo no processo.
  • Padronização: Garantem que todos os desenvolvedores sigam as mesmas convenções e regras de estilo, melhorando a consistĂŞncia do cĂłdigo.
  • Refatoração Assistida: Facilitam a refatoração do cĂłdigo, oferecendo sugestões para melhorias.

Ao ativar os analisadores de código, você tem uma forma proativa de melhorar a qualidade do seu código e reduzir o risco de falhas no ambiente de produção.

Cache DistribuĂ­do

O cache distribuído é uma técnica usada para melhorar a performance e escalabilidade de aplicações, armazenando dados frequentemente acessados em uma camada de cache externa ao banco de dados. Ele permite que as instâncias do aplicativo compartilhem dados em cache de forma eficiente, garantindo alta disponibilidade e redução do tempo de resposta.

Se você optar por habilitar o cache distribuído durante a criação do seu projeto, o Redis será integrado ao seu container Aspire, oferecendo um sistema de caching de alta disponibilidade.

Vantagens do Cache DistribuĂ­do:

  • Melhoria de Performance: Reduz o tempo de resposta das requisições, minimizando o acesso ao banco de dados.
  • Escalabilidade: Permite que a aplicação seja escalada horizontalmente, já que o cache pode ser acessado de diferentes instâncias de forma transparente.
  • Alta Disponibilidade: Com o Redis, o cache Ă© mantido disponĂ­vel mesmo em caso de falhas, oferecendo uma solução robusta para sistemas distribuĂ­dos.
  • Redução de Custo: Diminui a carga no banco de dados e no sistema, reduzindo a necessidade de processamento em requisições repetitivas.

Ao habilitar o cache distribuído, você estará melhorando significativamente a performance da sua aplicação, garantindo uma resposta mais rápida aos usuários e diminuindo a carga nos sistemas backend.

Comunicação Assíncrona

A comunicação assíncrona é uma abordagem que permite que sistemas e componentes se comuniquem de forma não bloqueante, ou seja, sem que o envio ou recebimento de dados interrompa o processamento de outras tarefas. Isso é especialmente útil em sistemas distribuídos e em situações de alta carga, onde a eficiência e a resiliência são cruciais.

Se você escolher habilitar a comunicação assíncrona, o RabbitMQ será integrado ao seu projeto, e o MassTransit será configurado para facilitar o uso dessa comunicação assíncrona em sua aplicação.

Vantagens da Comunicação Assíncrona:

  • Desempenho Aprimorado: Permite que as operações sejam realizadas em paralelo, sem bloquear o fluxo de execução do sistema.
  • Escalabilidade: Facilita a escalabilidade do sistema, permitindo que ele trate grandes volumes de dados e usuários simultâneos sem perder performance.
  • ResiliĂŞncia: Em caso de falhas temporárias, a comunicação assĂ­ncrona permite que as mensagens sejam reprocessadas ou armazenadas para posterior processamento.
  • Desacoplamento: Os sistemas podem ser projetados para se comunicar sem depender diretamente de respostas imediatas, promovendo maior flexibilidade e organização.

A integração com o RabbitMQ e o uso do MassTransit tornam a comunicação entre os componentes mais eficiente e resiliente, ajudando a garantir a escalabilidade e a flexibilidade de sua aplicação.

PrĂłximos Passos

Agora que vocĂŞ criou seu projeto .NET com o Lino, abra-o no seu editor de cĂłdigo favorito. VocĂŞ pode usar o Visual Studio, Visual Studio Code ou qualquer outra IDE de sua preferĂŞncia.

Com o projeto aberto, você pode começar a adicionar e configurar os serviços que compõem sua aplicação. Essa é a próxima etapa no fluxo de desenvolvimento.

Na próxima seção, vamos mostrar como criar e configurar esses serviços no seu novo projeto, preparando-o para crescer de forma organizada e escalável conforme as necessidades da sua aplicação.

Criar e gerenciar serviços

Após criar um projeto, o próximo passo é adicionar serviços. O Lino oferece uma maneira simples e intuitiva de criar serviços para sistemas monolíticos ou arquiteturas de microsserviços.

Para criar um novo serviço, use o seguinte comando:

lino service new

Durante o processo, o CLI solicitará as seguintes informações:

  • Namespace do Serviço: Define o nome e o namespace do serviço.
  • Nome de Exibição: Nome amigável que será exibido na interface.
  • Tipo de Serviço: Escolha entre simples ou modularizado.
  • Banco de Dados: Escolha entre PostgreSQL ou SQL Server.

Se o tipo escolhido for simples, também serão solicitadas as informações:

  • Estilo de Arquitetura: Atualmente apenas Clean Architecture Ă© suportada.
  • Utilizar IDs fortemente tipados? Escolha sim ou nĂŁo.

Tipos de Serviço

Serviço Simples: Estrutura mais enxuta, ideal para projetos monolíticos ou microsserviços com responsabilidades claras e isoladas.

Serviço Modularizado: Ideal para sistemas maiores que exigem maior organização e escalabilidade, permitindo dividir o serviço em módulos menores e focados, facilitando a manutenção e a evolução.

Independentemente do tipo, cada serviço terá seu próprio banco de dados. O suporte a IDs fortemente tipados é padrão para serviços simples; em serviços modularizados, essa decisão é feita por módulo.

A estrutura do Lino é flexível, permitindo a criação de serviços simples e modularizados dentro do mesmo projeto.

Estilo de Arquitetura

Todos os serviços no Lino utilizam a Clean Architecture, garantindo boas práticas de separação de responsabilidades, facilidade de manutenção e evolução do sistema.

Principais benefĂ­cios da Clean Architecture:

  • Desacoplamento: A lĂłgica de negĂłcios Ă© isolada dos detalhes tĂ©cnicos, aumentando a flexibilidade e a testabilidade.
  • Manutenibilidade: Separação clara entre camadas, facilitando mudanças sem impactar o sistema inteiro.
  • Testabilidade: A separação de responsabilidades facilita a criação de testes unitários e de integração.
  • Escalabilidade: Componentes podem ser modificados ou substituĂ­dos sem impactar a lĂłgica de negĂłcios.

Se optar por criar um serviço simples com Clean Architecture, a estrutura do projeto será semelhante a:

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
    

Se optar por criar um serviço modularizado, o projeto será estruturado para permitir a adição de novos módulos de maneira organizada:

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/
    

IDs Fortemente Tipados

IDs fortemente tipados são uma prática para aumentar a segurança e a clareza do código, usando tipos específicos para identificadores (ID) em vez de tipos genéricos (como int ou guid).

Com IDs fortemente tipados, evita-se o uso incorreto de identificadores, reduzindo erros comuns. Por exemplo, um ID de usuário é representado por um tipo próprio em vez de um simples inteiro.

Vantagens dos IDs fortemente tipados:

  • Segurança de Tipo: Garante o uso correto dos IDs, impedindo misturas de tipos diferentes.
  • Clareza no CĂłdigo: Cada tipo de ID Ă© representado por uma classe especĂ­fica, melhorando a legibilidade.
  • Facilidade de Refatoração: Mudanças no formato de um ID sĂŁo aplicadas apenas no tipo correspondente, mantendo o restante seguro.
  • Redução de Erros: Evita a utilização de IDs em contextos incorretos.

Próximos passos para Serviços Modularizados

Após criar um serviço modularizado, o próximo passo é adicionar módulos. Módulos organizam a lógica de negócios e a infraestrutura de forma independente, tornando o sistema mais escalável e organizado.

Na próxima seção, aprenderemos como criar e gerenciar módulos dentro de serviços modularizados, aproveitando ao máximo a flexibilidade e escalabilidade dessa abordagem.

Criando e Gerenciando MĂłdulos

Após criar um serviço modular, o próximo passo é adicionar módulos a ele. Módulos permitem organizar a lógica de negócios de forma independente, trazendo ainda mais escalabilidade e organização ao sistema.

Para criar um novo mĂłdulo, utilize o seguinte comando:

lino module new

Durante a execução, o CLI solicitará as seguintes informações:

  • Serviço: Define qual serviço o novo mĂłdulo será criado.
  • Namespace do MĂłdulo: Define o nome e o namespace do mĂłdulo.
  • Nome de Exibição: Nome amigável exibido nas interfaces.
  • Estilo Arquitetural: Atualmente, apenas Clean Architecture.
  • Utilizar Strongly Typed ID? Escolha entre Sim ou NĂŁo.

Ao final, o Lino gerará o novo módulo mantendo a estrutura do seu serviço modular:

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

Estrutura de Banco de Dados

É importante destacar que o banco de dados está vinculado ao serviço. Dentro de um serviço modular, cada módulo é representado por seu próprio schema no banco de dados associado. Essa abordagem proporciona isolamento e organização, sem a necessidade de criar múltiplos bancos de dados distintos.

Sobre a IndependĂŞncia entre MĂłdulos

Assim como os serviços não possuem dependências diretas entre si, os módulos também são criados como projetos independentes dentro do serviço.

Vantagens desse desacoplamento:

  • Isolamento: Cada mĂłdulo pode evoluir de forma independente, facilitando a manutenção e a evolução contĂ­nua.
  • Organização: A aplicação torna-se verdadeiramente modular, respeitando os limites de contexto (Bounded Contexts) e promovendo boas práticas de arquitetura de software.
  • Flexibilidade: Permite adicionar, remover ou refatorar mĂłdulos sem impactar diretamente outros mĂłdulos do serviço.
  • Facilidade de testes: Cada mĂłdulo pode ser testado de forma isolada, aumentando a confiabilidade e a qualidade do sistema.

Com isso, concluímos o processo de criação de módulos. Nos próximos tópicos, veremos como estruturar os elementos internos de um módulo, como entidades, objetos de valor, enumerações, comandos, consultas, APIs, integrações e muito mais.

Ocorreu um erro não tratado. Recarregar đź—™