我们构建软件的方式不断发展。虽然 Clean Architecture 一直是 .NET 开发人员的最爱,但 Vertical Slice Architecture 以其以功能为中心的方法而受到关注。那么,让我们快速深入了解 Vertical Slice,将其与 Clean Architecture 进行比较,看看它是否适合您的下一个项目!
But,Vertical Slice 会是答案吗?或。传统架构可能很僵化且难以扩展,有时很难使代码与业务逻辑保持一致。Vertical Slice 按功能组织所有内容,为您提供更大的灵活性。但让我们说实话——我们不知道它是否适合所有情况。这一切都是为了尝试一下,看看它如何满足您的需求。准备好探索了吗?让我们开始吧!
垂直切片架构,其中每个功能(例如,“创建书籍”和“创建用户”)都通过不同的层移动:UI、域、存储库和数据库。每个切片都是自包含的,处理跨所有层的特定流,确保模块化和功能隔离。
理解 Vertical Slice 的理想方法之一是将其与 Clean Architecture 等传统的分层架构进行比较。让我们看看他们是如何叠加的!
Clean Architecture (Left Side):
像蛋糕一样分层:Clean Architecture 将应用程序分成多个层,就像蛋糕一样。你有自己的控制器 (UI) 和业务逻辑。一切都被整齐地分成自己的层。Api.csprojApplication.csproj
命令和功能:在 Clean Architecture 中,您的命令 like 和 隐藏在 Application 下它们自己的文件夹中。但这里有一个问题 — 它们被分成多个图层,所以当您想创建一个功能时,您必须在每个图层中烘焙一点!CreateBookHandler.csCreateUserHandler.cs
Vertical Slice Architecture (Right Side):
一个功能,一个切片:现在想象一下,您不是像千层蛋糕一样把东西分开,而是抓住整个功能并将其包装成一个整齐的包装!这就是 Vertical Slice。每个功能(如 “Books” 或 “Users”) 都有自己的小捆绑包,其中包含所需的一切。
All-In-One:您的 “Books” 功能包含其控制器、数据模型、命令,甚至逻辑 (, , )。无需在图层之间跳转 - 一切都在一个切片中。这就像把你最喜欢的菜的所有配料都放在一个碗里一样!Book.csCreateBookCommand.csBooksController.cs
So, What’s the Big Difference?
当您需要整齐、分层的职责分离时,Clean Architecture 非常棒。但是,当您需要跨层跳转以完成单个功能时,可能会感觉有点慢。
另一方面,Vertical Slice 就像快速通道!它是功能优先的,这意味着功能所需的一切都捆绑在一个地方。易于查找,易于更改。
隔离😡的挑战:功能隔离出错
好了,我们被 Vertical Slice 的想法所吸引 — 它速度快,是模块化的,并且它把所有东西都放在漂亮的小捆绑包中。但这里有一个问题:当你如此完全地隔离特征时,它可能是一把双刃剑。
想象一下,你有自己的整洁切片:一个用于 Books,另一个用于 Users,还有更多用于其他功能。一切都运行正常,直到有一天您需要访问 Books 切片中的 User 数据 — 也许是为了检查用户是否可以借书。呃哦!由于这些切片是独立的,因此您无法直接从 Books 切片访问 。这就是事情变得棘手的地方。UserRepository
该图像描述了一个垂直切片架构,其中 “Books” 功能直接从 “Users” 功能访问。这打破了特征隔离的原则,因为垂直切片架构中的每个特征都应该是自包含且独立的。跨功能直接共享存储库会形成紧密耦合,使系统更难维护。相反,应该通过共享服务或共享内核来处理共享逻辑(如获取用户),以保持功能隔离和模块化。ReserveBookQuery.csUserRepository.GetUsers()
解决方案:保持切片的整洁但相互连接
我们希望保持 slice 的独立性,但有时 slice 需要相互通信。以下是在不使代码库变得一团糟的情况下处理此问题的方法:
Shared Kernel 来救援 🛟
Shared Kernel 是一个很酷的中间人,它允许 slice 共享逻辑、数据和事件,而不会互相踩踏。方法如下:
1. Shared Services
切片可以调用共享服务(如 a )来获取公共数据或逻辑,而无需在功能之间创建依赖关系。UserService
切片(“Books”和“Users”)都通过 UserService 或类似服务访问共享逻辑或数据,这些服务位于提供通用功能的共享内核中。
示例:
“Books” 切片用于在有人借书时获取用户信息。UserService
2. 事件驱动的通信
切片发布和订阅事件类似于在整个应用程序中触发操作,同时保持松散耦合。BookBorrowedEvent
该图显示了在运行 后在共享内核中触发 的 书籍功能。Users 功能侦听此事件并更新 中的用户历史记录。该活动就像一个信使,让两个功能在不直接连接的情况下进行对话,保持一切模块化和简洁!BookBorrowedEvent.csBorrowBookCommand.csUpdateUserHistory.cs
3. 暴露的内部 API 端点
切片公开其他切片调用以交换数据的内部 API 端点,例如应用程序内的微型微服务。
示例:
“Books” 切片向**“Users”**切片发送 HTTP 请求,以通过 获取用户详细信息。/api/users/{id}
现在我们已经探讨了切片如何通信,重要的是要记住并非所有模式都适合每个场景。每个项目、功能和用例都是独一无二的,因此在确定切片应如何通信时,请注意并仔细评估。
对于紧密耦合、可重用的逻辑:共享内核中的共享服务可能非常适合。
对于松散耦合和对变化做出反应:事件驱动的通信使事情保持灵活。
对于结构化的切片间数据交换:内部 API 端点是您的迷你微服务解决方案。
选择错误的通信方式可能会造成混乱,所以问问自己:我的切片需要有多独立?我的使用案例是否需要立即响应,还是可以异步响应事件?让系统的需求指导您的决定。
🚀 开发人员的过渡:从干净的架构到垂直切片
从 Clean Architecture 转向 Vertical Slice 不仅仅是代码结构的转变,而是您对功能开发和团队协作的看法的转变。以下是预期内容:
1. 更快的功能开发
减少跳转:将您需要的所有内容(命令、查询、处理程序)都放在一个切片中,从而简化了添加新功能的过程。不再需要跨图层或多个项目导航。
即时聚焦:开发人员只关注该功能,减少上下文切换并允许更快的迭代。
2. 减少合并冲突
隔离的功能切片:由于切片是自包含的,因此接触相同文件的开发人员较少,从而减少了大型团队中发生合并冲突的机会。
独立的工作流程:团队可以在单独的切片上工作,而不会互相踩踏,从而提高整体生产力。
3. 提高团队生产力
功能优先的思维方式:开发人员可以端到端地交付功能,而不会因依赖关系而减慢其速度。无需等待其他团队更新服务或存储库。
并行开发:由于切片独立性,团队可以同时处理多个功能,从而加快交付周期。
4. 更清晰的所有权
自包含切片:团队完全拥有自己的功能,从表示到数据库逻辑。这使得责任更加明确,并避免在出现 bug 时推卸责任。
更轻松的入职培训:新团队成员可以专注于单个功能切片来了解系统,而不是浏览多个层次。
5. Risk of Ball of Mud
过度填充 slice 的诱惑:注意在一个 slice 中添加太多 logic 或直接从另一个 slice 调用方法。这可能会导致紧密耦合的混乱,从而抵消模块化的好处。
解决方案:使用共享内核、事件驱动型通信或 API 端点负责任地处理跨切片逻辑。
6. 代码复制与重用
受控重复:您可能会遇到需要在多个切片中出现相同逻辑的情况。虽然一些重复是可以接受的,但请避免过度依赖共享服务以保持切片独立性。
解决方案:在绝对必要时通过 Shared Services 重用通用逻辑,但要遵守功能之间的界限。
7. 沟通复杂性
没有自由的方法调用:与可以跨层共享服务和存储库的 Clean Architecture 不同,Vertical Slice 需要一种更周到的方法来处理切片之间的通信。
解决方案:仔细评估何时使用 Events、Shared Services 或 API 进行切片间通信,以避免功能紧密耦合。
最后的思考
Vertical Slice 和 Clean Architecture 都有其独特的优势和权衡。Vertical Slice 在功能开发速度方面确实大放异彩。由于每个功能都是独立的,因此无需浏览多个图层 — 您需要的一切都在一个地方。这种简单性使开发人员能够快速进入和退出,从而减少摩擦并实现快速迭代。但是,当 slice 需要相互通信时,这种模块化需要仔细管理以避免引入复杂性。优点是它通过保持功能隔离和可管理来帮助防止大泥球。
相比之下,Clean Architecture 在模块重用和关注点分离方面提供了灵活性。虽然跨层轻松调用方法很诱人,但如果没有规则这样做可能会导致技术债务或紧密耦合的系统,从长远来看,这会使维护变得更加困难。但是,当与域驱动设计 (DDD) 原则结合使用时,Clean Architecture 可以有效地在层之间实施明确的边界,使核心域与外部关注点解耦,并确保可扩展、可维护的结构。
Clean Architecture 的一个关键点是其层重用的潜力。例如,持久性层和域层通常可以通过利用类库跨平台重用,例如 Web 和移动应用程序。这在 Vertical Slice 中更难实现,因为每个 Slice 都与特定特征紧密绑定。
没有一个完美的条件可以证明 Vertical Slice 或 Clean Architecture 绝对是最好的。这完全取决于您的项目需求、团队的工作流程和您的长期目标。但是,通过正确的用例、团队结构和开发优先级,Vertical Slice 可以提供一种非常有效的方法来构建快速、隔离和模块化的系统。同样,当可重用性和关注点分离是项目优先事项的最前沿时,Clean Architecture 也会表现出色。
如果你喜欢我的文章,请给我一个赞!谢谢