分层架构 vs 功能文件夹
I’m happy to translate the article for you, but I’ll need the actual text of the post. Could you please paste the content you’d like translated (excluding the source line you’ve already provided)? Once I have the text, I’ll translate it into Simplified Chinese while preserving the original formatting, markdown, and any code snippets.
Introduction
在 .NET 中选择分层架构还是特性文件夹(Feature Folders)通常被描述为一个简单的文件夹结构决策。实际上,它是一项更深层次的架构选择,会影响代码库的增长、交付速度以及技术债务。
我使用这两种方法构建并维护了生产系统,体会到了经典分层的安全性以及在速度重要时可能带来的摩擦,也感受到了特性文件夹的流畅性以及缺乏纪律时可能出现的混乱。本文基于真实的观察,讨论了哪些地方出现了问题、哪些因素拖慢了团队,以及最终哪种方式更为有效。
分层(或洋葱)架构
大多数 .NET 开发者在职业生涯早期就会接触到一种分层结构:Core、Infrastructure、Application 和 Web/API。这种结构易于解释、绘图,并且被广泛认为是一种“安全”的架构选择。
在纸面上,分层架构符合 Clean Architecture 的原则:
- 依赖指向内部。
- 业务逻辑被隔离。
- 基础设施关注点被抽象掉。
常见痛点
- 多层修改:即使是小的功能添加,也常常需要触及多个层。
- 跨层泄漏:基础设施的关注点会渗入应用层代码。
- 上手难度:新开发者往往难以定位逻辑应该放在哪一层。
示例:添加 CreateOrder 接口
// Web layer
/Web/API/Controllers/OrderController.cs
// Application layer
/Application/Commands/CreateOrderCommand.cs
/Application/Handlers/CreateOrderHandler.cs
// Core/Domain
/Core/Domain/Order.cs
// Infrastructure
/Infrastructure/Repositories/OrderRepository.cs
/Infrastructure/Mapping/OrderProfile.cs
这种做法安全且明确,但显得冗长且缓慢,尤其对于小团队而言。
功能文件夹
Feature Folders 按业务能力而非技术层次组织代码。与同一功能相关的所有文件放在一起,便于在单一位置理解和修改行为。
观察到的收益
- 更快、更专注的功能开发。
- 对孤立功能的重构更简洁。
- 减少上下文切换,代码审查更容易。
示例文件夹结构
/Features
/Orders
OrderController.cs
CreateOrderHandler.cs
OrderValidator.cs
OrderRepository.cs
OrderDto.cs
这种结构减少了形式主义和文件放置的争论,让团队能够专注于业务问题。
权衡
| 方面 | 分层架构 | 功能文件夹 |
|---|---|---|
| 优点 | 边界明确,易于遵循 SOLID,适合大型团队 | 迭代更快,上手更容易,贴合业务概念 |
| 缺点 | 交付较慢,样板代码多,日常改动的认知负担更高 | 可能出现重复逻辑,需要明确的约定 |
实际出了什么问题?
在一个项目中,我们因为认为这是最佳实践而采用了分层方法。六个月后:
- 入职培训非常痛苦。
- 功能交付速度显著下降。
将代码重构为特性文件夹(Feature Folders)后恢复了进度,但前提是引入了共享逻辑的规则并避免了失控的蔓延。
选择正确的方法
- 小团队 / 快速迭代的产品 → Feature Folders 往往更胜一筹。
- 具有大量横切关注点的平台 → 分层架构可能更合适。
- 混合方案 → 通常将两种风格结合使用效果最佳:使用分层来管理共享基础设施,同时将特定功能的代码放在 Feature Folders 中。
实际建议
- 在下一个垂直切片中尝试 Feature Folders,即使是在分层项目中,也可以观察其对速度和清晰度的影响。
- 避免过早抽象:让重复自然出现后再提取共享组件。
- 绝不要在没有明确所有权和目的的情况下创建通用的 “Common” 文件夹。
架构应当赋能团队,而不是限制团队。