在现代软件开发中,高效地构建应用程序对于可维护性、可伸缩性和适应性至关重要。在 .NET 社区中越来越受欢迎的一种体系结构模式是
垂直切片体系结构
。
与传统的分层架构不同,垂直切片强调将应用程序划分为功能,而不是 UI、业务逻辑和数据访问等技术问题。
这种方法增强了凝聚力,减少了依赖性,并使其更容易独立地处理特定功能。
什么是垂直切片?
垂直切片是指围绕应用程序的功能构建应用程序,每个切片代表一个完整的、独立的功能,包含从用户界面到数据库的所有必要组件。每个切片包括:
表示层 :负责用户交互,通常是 Web UI 或 API。
业务逻辑层 :包含域逻辑和业务规则。
数据访问层 :管理数据持久性和检索。
垂直切片的好处
功能独立 性:每个功能都是独立的,因此可以更轻松地独立开发、测试和部署。
提高凝聚力 :功能的所有部分都位于一起,增强了理解并减轻了开发人员的认知负担。
更易于维护 :隔离功能可最大程度地减少更改的影响,并使调试更简单。
增强的可扩展性 :功能可以独立扩展,优化资源使用。
在 .NET 中实现垂直切片
让我们演练一个在 .NET Web API 应用程序中实现垂直切片的示例。
第 1 步:设置项目
创建新的 ASP.NET Core Web API 项目:
dotnet new webapi -n VerticalSlicingExample
cd VerticalSlicingExample
第 2 步:定义特征结构
按要素而不是图层组织工程。例如,如果您的应用程序具有 和 功能,请按如下方式构建它:
VerticalSlicingExample
│
├── Features
│ ├── Orders
│ │ ├── CreateOrder
│ │ │ ├── CreateOrderCommand.cs
│ │ │ ├── CreateOrderHandler.cs
│ │ │ └── CreateOrderController.cs
│ │ └── GetOrder
│ │ ├── GetOrderQuery.cs
│ │ ├── GetOrderHandler.cs
│ │ └── GetOrderController.cs
│ └── Customers
│ ├── CreateCustomer
│ │ ├── CreateCustomerCommand.cs
│ │ ├── CreateCustomerHandler.cs
│ │ └── CreateCustomerController.cs
│ └── GetCustomer
│ ├── GetCustomerQuery.cs
│ ├── GetCustomerHandler.cs
│ └── GetCustomerController.cs
├── Program.cs
└── Startup.cs
步骤 3:实现特征切片
让我们实现特征切片。
CreateOrderCommand.cs
public classCreateOrderCommand
{
publicstring ProductName { get; set; }
publicint Quantity { get; set; }
publicdecimal Price { get; set; }
}
CreateOrderHandler.cs
public classCreateOrderHandler
{
privatereadonlyApplicationDbContext _context;
publicCreateOrderHandler(ApplicationDbContext context)
{
_context = context;
}
publicasyncTaskHandle(CreateOrderCommand command)
{
var order = newOrder
{
ProductName = command.ProductName,
Quantity = command.Quantity,
Price = command.Price,
OrderDate = DateTime.UtcNow
};
_context.Orders.Add(order);
await _context.SaveChangesAsync();
}
}
CreateOrderController.cs
[ApiController]
[Route("api/[controller]")]
public classCreateOrderController : ControllerBase
{
privatereadonlyCreateOrderHandler _handler;
publicCreateOrderController(CreateOrderHandler handler)
{
_handler = handler;
}
[HttpPost]
publicasyncTask<IActionResult>Post(CreateOrderCommand command)
{
await _handler.Handle(command);
returnOk();
}
}
步骤 4:注册依赖项
在 中,注册依赖项:Startup.cs
publicvoidConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<CreateOrderHandler>();
services.AddControllers();
}
步骤 5:配置数据库上下文
ApplicationDbContext.cs
public classApplicationDbContext : DbContext
{
publicApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
publicDbSet<Order> Orders { get; set; }
}
public classOrder
{
publicint Id { get; set; }
publicstring ProductName { get; set; }
publicint Quantity { get; set; }
publicdecimal Price { get; set; }
publicDateTime OrderDate { get; set; }
}
使用连接字符串进行更新:appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=VerticalSlicingDb;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
步骤 6:运行应用程序
运行应用程序并使用 Postman 等工具测试终结点。使用表示 的 JSON 正文向 发送 POST 请求。
将垂直切片与 SOA 集成
在面向服务的体系结构 (SOA) 中,每个服务都是一个独立的单元,具有其业务逻辑和数据存储。垂直切片通过确保每个服务(或微服务)都以功能为中心来补充 SOA。每个服务都可以公开其 API 端点,同时封装其数据访问和业务逻辑,遵循单一责任原则。
示例:Orders Microservice
表示层 :ASP.NET 核心 Web API
业务逻辑层 :包含在每个处理程序类中。
数据访问层 :用于数据库操作的实体框架核心或 Dapper。
示例:客户微服务
表示层 :ASP.NET 核心 Web API
业务逻辑层 :包含在每个处理程序类中。
数据访问层 :用于数据库操作的实体框架核心或 Dapper。
将垂直切片扩展到其他技术
垂直切片也可以应用于 Angular、React 或 Vue.js 等前端技术,其中每个功能切片都包括组件、服务和状态管理。
此外,它可以与 Azure 或 AWS 等云服务集成,其中每个切片都可以具有其无服务器函数、存储帐户和其他资源。
示例:Angular 功能模块
使用功能模块构建 Angular 项目:
src
│
├── app
│ ├── orders
│ │ ├── create-order
│ │ │ ├── create-order.component.ts
│ │ │ ├── create-order.service.ts
│ │ │ ├── create-order.component.html
│ │ │ └── create-order.component.css
│ │ └── get-order
│ │ ├── get-order.component.ts
│ │ ├── get-order.service.ts
│ │ ├── get-order.component.html
│ │ └── get-order.component.css
│ └── customers
│ ├── create-customer
│ │ ├── create-customer.component.ts
│ │ ├── create-customer.service.ts
│ │ ├── create-customer.component.html
│ │ └── create-customer.component.css
│ └── get-customer
│ ├── get-customer.component.ts
│ ├── get-customer.service.ts
│ ├── get-customer.component.html
│ └── get-customer.component.css
示例:Azure 函数应用
按功能构建 Azure 函数应用:
FunctionApp
│
├── Orders
│ ├── CreateOrder
│ │ ├── index.js
│ │ └── function.json
│ └── GetOrder
│ ├── index.js
│ └── function.json
└── Customers
├── CreateCustomer
│ ├── index.js
│ └── function.json
└── GetCustomer
├── index.js
└── function.json
传统分层架构与垂直切片架构
传统分层架构
结构 :
根据技术问题将应用程序划分为水平层。
典型的层包括表示、业务逻辑和数据访问。
凝聚力 :
由于相关代码分散在多个层中,因此功能内的内聚力较低。
层内凝聚力高,但不一定跨要素。
依赖关系 :
层以分层方式相互依赖。
较低层(例如,数据访问)的变化可能会对较高层(例如,演示)产生连锁反应。
功能开发 :
需要接触多个图层才能实现单个功能。
由于跨层变化,开发速度较慢。
可扩展性 :
水平缩放需要复制整个图层。
更难独立扩展特定功能。
保养:
维护起来更具挑战性,因为更改通常需要跨多个层进行更新。
由于特征逻辑的分散,调试可能很复杂。
测试 :
单元测试侧重于单个层,因此集成测试对于整体验证至关重要。
更复杂的测试设置,以确保所有层都能正常工作。
垂直切片架构
结构 :
根据功能将应用程序划分为垂直切片。
每个切片都包含自己的 Presentation、Business Logic 和 Data Access 组件。
凝聚力 :
由于所有相关代码都位于一起,因此每个功能切片内具有很高的内聚力。
每个切片独立运行。
依赖关系 :
功能彼此独立。
一个要素切片中的更改对其他要素切片的影响最小。
功能开发 :
开发速度更快,因为每个功能都可以独立实现。
开发人员可以一次专注于一个切片,而不必担心应用程序的其他部分。
可扩展性 :
更轻松地独立扩展特定功能。
每个功能都可以根据需要进行部署和扩展,而不会影响其他功能。
保养:
由于更改在要素切片中本地化,因此更易于维护。
由于所有相关代码都包含在切片中,因此简化了调试。
测试 :
单元测试侧重于单个功能切片,从而可以更轻松地隔离和测试功能。
集成测试更直接,因为每个切片都是一个完整的功能。
总结
传统的分层架构 适用于较小的应用程序,或者当保持严格的关注点分离至关重要时,但随着应用程序的增长,它可能会导致开发和维护挑战变慢。
垂直切片架构 非常适合功能独立性、开发速度更快、更易于维护的大型复杂应用程序。它与微服务和领域驱动设计等现代开发实践非常吻合。
如果你喜欢我的文章,请给我一个赞!谢谢