作为一名 C# 开发工程师,我们在项目中经常面临一个痛点:随着功能增加,原本整洁的项目逐渐演变成了“面条代码”(Spaghetti Code)。改一个字段要动全套界面,修一个 Bug 会引发三个新问题。
最近在优化我的项目时,我深入实践了 DDD(领域驱动设计) 和 整洁架构(Clean Architecture)。今天就来分享一下,如何通过“分层+接口”让你的 WPF 项目重获新生。
1. 为什么要分层?给你的软件加个“记忆模块”
很多初学者容易把 UI 逻辑、数据库操作和核心业务全都塞进 Code-behind。这种做法会让软件只有“短期记忆”。
持久化层(Persistence Layer) 的出现就是为了解决这个问题。它不是简单的数据库访问,而是软件与外部世界沟通的“桥梁”。通过引入分层架构,我们可以将数据的物理落地与业务逻辑彻底解耦。
2. 经典分层结构:让代码各司其职
在 WPF 中,我推荐采用以下四层架构,这也是现代工业级项目的标配:
UI 层 (WPF):只负责展示,Code-behind 保持干净,所有逻辑在 ViewModel 中处理。
应用层 (Application):指挥官。负责协调业务流程,比如“先读取、再计算、最后保存”。
领域层 (Domain):大脑。定义业务规则(例如“数据不能超限”),且不依赖任何数据库或 UI 技术。
基础设施层 (Infrastructure):执行者。负责写 SQL、操作底层 SDK、记录日志。
3. 核心精髓:依赖倒置 (DIP)
你可能听过“高层依赖底层”,但在优秀架构中,我们要把这个箭头反过来:
“高层模块不应该依赖低层模块,二者都应该依赖其抽象(接口)。”
当你需要调用一个服务时,不要关注它是怎么实现的,而是只关心接口契约。这样一来,无论你底层从 MySQL 换成 JSON,还是从串口通信换成网络通信,业务层代码一行都不用改!
4. DDD + IoC:黄金搭档
很多朋友担心 DDD 太复杂,或者不知道如何管理众多的接口。这里要用到 IoC 容器(控制反转)。
DDD 负责“蓝图设计”(定义接口),IoC 负责“施工装配”(自动注入实现)。没有 IoC,DDD 就像一堆碎片,组装起来非常痛苦;有了 IoC,你的项目就像组装乐高一样简单。
我的最佳实践建议:
基础服务独立化:日志、用户管理等支撑服务,建议封装成模块,对外暴露 AddModuleServices 扩展方法,保持全局容器整洁。
模块化局部 IoC:复杂的模块内部可以有自己的容器,不必一股脑堆进全局。
5. 写给开发者的 .cursorrules 建议
为了保证架构不“变质”,你可以给你的开发助手(如 Cursor/Windsurf)配置一套规则,强行固化这些原则。
关键约束(摘录自我的 .cursorrules):
Layer Segregation:Domain 层禁止任何依赖,Application 层只依赖 Domain。
IoC Enforcement:禁止使用 new 关键字实例化 Service,必须使用构造函数注入。
Async/Await:所有 I/O 操作必须异步,确保 UI 响应丝滑。
结语
软件架构的本质,就是管理复杂性。
当你开始把关注点从“怎么把这个功能写出来”转移到“如何定义这个功能的接口边界”时,你就已经迈入了高级开发者的行列。保持这种职责分明的清晰感,你的代码库才会有生命力。