项目结构化
Lino 旨在高效简化可扩展和模块化项目的创建。它提供了结构清晰的解决方案,在各层之间有明确的职责划分,并能够随着项目需求的发展而扩展。
使用Lino创建项目时,您将生成一个遵循最佳架构和模块化实践的.NET解决方案,重点关注性能、可扩展性和易维护性。
创建新项目
命令 lino project 简化了创建 .NET 新项目的过程,既简单又高效。使用此命令,您可以配置项目结构、选择所需的依赖项,并定义语言和基础设施设置。
要创建一个新项目,请使用以下命令:
lino project new
在执行过程中,命令行界面将请求以下信息:
- 项目命名空间:定义解决方案的主命名空间。
- 显示名称:在界面中显示的友好名称。
- 编程语言:目前只支持 C# (.NET)。
- 开发堆栈:目前是 .NET 9 与 Aspire。
- 是否使用代码分析器?选择是或否。
- 是否使用分布式缓存?选择是或否。
- 是否使用异步通信?选择是或否。
- 数据语言:定义系统中实体名称和其他数据的语言。
- 应用程序支持的语言:允许添加最多 10 种语言以支持国际化(i18n)。
- 默认语言:定义在 API、响应消息、验证和用户界面中使用的主要语言。
确认信息后,Lino 将自动创建项目结构,如下所示:
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/
代码分析器
静态代码分析器是强大的工具,有助于确保代码在开发过程中的质量和一致性。它们通过在不执行代码的情况下检查源代码,发现错误、样式问题和其他不一致之处。
当您选择在创建项目时启用代码分析器时,命令行界面将自动为您配置以下包:
- StyleCop.Analyzers:执行代码样式检查,例如缩进、空格和命名约定。
- SonarAnalyzer.CSharp:一组用于代码质量和安全性的规则,帮助发现常见错误和潜在的漏洞。
- Roslynator.Analyzers:提供多种 C# 代码质量和优化规则,帮助发现重构和优化的机会。
代码分析器的好处:
- 提高质量:帮助保持代码整洁、可读并避免常见问题。
- 预防错误:在执行前检测到错误,帮助开发者尽早修复问题。
- 规范化:确保所有开发人员遵循相同的样式和规则,从而提高代码一致性。
- 重构支持:帮助进行代码重构,提供改进建议。
启用代码分析器后,您可以积极地提升代码质量,减少生产环境中失败的风险。
分布式缓存
分布式缓存是一种提高应用程序性能和可扩展性的方法,通过将频繁访问的数据存储在一个独立于数据库的外部缓存中,从而减少对数据库的访问。它使应用程序的各个实例能够有效地共享缓存数据,确保高可用性并减少响应时间。
如果在创建项目时选择启用分布式缓存,Redis 将被集成到您的 Aspire 容器中,提供一个高可用的缓存系统。
分布式缓存的好处:
- 提高性能:减少查询响应时间,最小化数据库访问。
- 可扩展性:允许应用程序横向扩展,因为缓存可以从多个实例中透明访问。
- 高可用性:使用 Redis 时,即使发生故障,缓存仍然可用,确保分布式系统的可靠性。
- 降低成本:减少对数据库和系统的负担,避免重复计算相同请求的结果。
启用分布式缓存后,您将显著提高应用程序的性能,确保用户响应速度更快,同时减轻后端服务器的负担。
异步通信
异步通信是一种允许系统和组件非阻塞地交换数据的方法,即不需要等待数据的发送或接收完成即可执行其他任务。在分布式系统和高负载情况下,这种方式尤其有用,能够提高效率和系统的韧性。
如果您选择启用异步通信,RabbitMQ 将被集成到您的项目中,MassTransit 将被配置以简化在应用程序中的异步通信。
异步通信的好处:
- 提高性能:允许并行执行操作,而不会阻塞系统的其他任务。
- 可扩展性:帮助系统扩展,处理大量数据和并发用户,而不降低性能。
- 鲁棒性:在临时故障发生时,异步通信可以重试或存储消息以便稍后处理。
- 解耦:系统可以在不依赖即时响应的情况下进行通信,从而提高灵活性和组织性。
通过集成 RabbitMQ 和使用 MassTransit,组件之间的通信将更加高效且可靠,确保您的应用程序具有良好的可扩展性和灵活性。
下一步
现在,您已使用 Lino 创建了您的 .NET 项目,请在您最喜欢的代码编辑器中打开它。您可以使用 Visual Studio、Visual Studio Code 或任何您选择的 IDE。
打开项目后,您可以开始添加和配置构成应用程序的服务。这是开发过程中的下一步。
在下一部分中,我们将展示如何在您的新项目中创建和配置这些服务,以便根据您的应用需求,以有组织且可扩展的方式进行开发。
创建和管理服务
在创建项目之后,下一步是添加服务。Lino 提供了一种简单直观的方式来创建服务,可用于单体系统或微服务架构。
要创建一个新服务,请使用以下命令:
lino service new
执行过程中,CLI 将要求提供以下信息:
- 服务命名空间:定义服务的名称和命名空间。
- 显示名称:在界面中显示的友好名称。
- 服务类型:选择简单或模块化。
- 数据库:选择 PostgreSQL 或 SQL Server。
如果选择了简单类型服务,还需提供以下信息:
- 架构风格:目前仅支持 Clean Architecture。
- 使用强类型 ID?选择是或否。
服务类型
简单服务:简单服务结构更精简,适合单体系统或微服务项目,每个服务具有独立的责任。
模块化服务:适用于需要更高组织性和可扩展性的大型系统,允许将服务划分为更小且专注的模块,便于维护和扩展。
无论是简单服务还是模块化服务,每个服务都将拥有独立的数据库。强类型 ID 的架构适用于简单服务,对于模块化服务,则由各模块独立决定。
Lino 的结构非常灵活,允许在同一项目中同时创建简单服务和模块化服务。
架构风格
Lino 为所有服务应用了 Clean Architecture,确保应用遵循良好的架构规范,促进职责分离,便于维护和扩展。
Clean Architecture 的优势:
- 解耦:业务逻辑独立于技术细节,提高灵活性和可测试性。
- 可维护性:各层之间分离,便于修改而不会影响系统的其他部分。
- 可测试性:关注点分离,便于为各层编写单元测试和集成测试。
- 可扩展性:组件可以轻松更换或修改而不会影响业务逻辑。
如果您选择创建一个简单服务,使用 Clean Architecture,项目将具有以下结构:
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
如果您选择创建一个模块化服务,项目将采用以下结构,支持在开发过程中灵活、有序地添加新模块:
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/
强类型 ID
强类型 ID 是一种提升代码安全性和清晰性的做法,通过为标识符(ID)定义具体类型,而不是使用通用类型(如 int
或 guid
)。
使用强类型 ID,可以避免将不同类型的 ID 混淆使用,从而减少常见错误。例如,为用户 ID 定义专用类型,而不是仅使用整数。
使用强类型 ID 的好处:
- 类型安全:确保正确使用 ID,避免不同类型 ID 混用。
- 代码清晰:每种 ID 类型由专门的类表示,代码更具可读性。
- 易于重构:如果 ID 类型需要更改,只需修改专用类型即可,其他代码保持安全。
- 减少错误:避免在错误的上下文中错误使用 ID。
模块化服务的下一步
创建模块化服务后,下一步是向其中添加模块。模块可以独立组织业务逻辑和基础设施,使系统更具可扩展性和组织性。
在下一主题中,我们将学习如何在模块化服务中创建和管理模块,从而充分利用模块化服务的灵活性和可扩展性。
创建和管理模块
创建模块化服务后,下一步是向其中添加模块。模块允许独立地组织业务逻辑,为系统带来更多的可扩展性和组织性。
要创建一个新模块,请使用以下命令:
lino module new
在执行过程中,CLI 将提示输入以下信息:
- 服务:定义新模块将创建在哪个服务中。
- 模块命名空间:定义模块的名称和命名空间。
- 显示名称:界面上显示的用户友好名称。
- 架构样式:目前仅支持 Clean Architecture。
- 使用强类型 ID?选择是或否。
最后,Lino 将在保持模块化服务结构不变的情况下生成新模块:
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
数据库结构
需要特别注意的是,数据库与服务绑定。在一个模块化服务中,每个模块由其在关联数据库中的独立 schema 进行表示。这种方法提供了隔离和组织,无需创建多个独立的数据库。
关于模块的独立性
就像服务之间没有直接依赖关系一样,模块也作为服务内部的独立项目进行创建。
这种解耦的好处:
- 隔离:每个模块可以独立演化,简化了维护和持续改进。
- 组织性:应用程序变得真正模块化,尊重上下文边界(Bounded Contexts),促进了良好的软件架构实践。
- 灵活性:可以添加、移除或重构模块,而不会直接影响服务中的其他模块。
- 测试便捷性:每个模块都可以单独进行测试,从而提高了系统的可靠性和质量。
通过以上内容,我们完成了模块创建过程。在接下来的章节中,我们将深入了解如何构建模块内部的元素,如实体、值对象、枚举、命令、查询、API、集成等。