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.