我们正在用 C# 编写 REST Web API。我们有某种形式的干净/洋葱架构,具有应用程序、域和基础设施层。我想在项目中注入一些 DDD 思想,让领域模型真正代表领域结构。
但是,正如许多示例所示,我们的持久性/基础设施并不使用实体框架直接访问数据库。相反,我们查询其他 API,并且我们拥有我不会考虑聚合根的类型的存储库。
问题1
假设我们有一个可识别的聚合根模型
System
。 SystemRepository
通过 HTTP 查询 API 1,并可以返回 System
。我遇到的问题是我想要一个 GenerateReport()
上的方法 System
来生成 Report
System
。
A
Report
不是一个实体,可以通过查询 API 2 来构造。我想在基础设施层中保留对 API 2 的 HTTP 调用,其他层不应该关心数据存储是 HTTP 还是数据库。
我可以创建一个接口
IReportService
并在基础设施中实现它,将其注入控制器并将其传递给System.GenerateReport()
,但它很容易被误解为BLL服务。理想情况下,我不希望看到在应用程序或域层中使用 IReportService
。
解决这个问题有什么好主意吗?
问题2
我遇到的另一个问题是,我想从我的控制器端点返回
Report
。为了采用 DDD 方式,我需要首先获取 System
,这意味着调用 API 1。但是客户端在请求 System
时已经知道 Report
的身份,所以我想绕过对 API 的调用1 然后转到 API 2 并获取 Report
。在这里,我想我需要一个缓存实现,我想对吗?
如果我是你,我会尝试将任务分成几个部分,因为此刻你正在同时解决所有问题。
比如这样。
第 1 步。 定义 API,此阶段不要考虑其他方面。
因为您指定了
REST
标签,例如这样:
/systems/{systemId}
/systems/{systemId}/report
第2步。确定实体的级别。从描述中尚不完全清楚系统是什么以及它承载什么功能。例如这样(伪代码):
ISystems {
ISystem system(systemId) {...}
}
ISystem {
// operations
ISystemReport report() {...}
}
第3步. 定义中间件层,其职责包括:调用实体并将其传递给API层、安全性、缓存等。简化一下,像这样(伪代码):
SystemResource {
ISystems iSystems;
// constructors
@GET(/systems/{systemId})
SystemResponse getSystem(systemId) {
ISystem iSystem = iSystems.system(systemId);
// mapping iSystem to systemResponse and return systemResponse
}
}
SystemReportResource {
ISystems iSystems;
// constructors
@GET(/systems/{systemId}/report)
SystemReportResponse getSystemReport(systemId) {
ISystemReport iSystemReport = iSystems.system(systemId).report();
// mapping iSystemReport to systemReportResponse and return systemReportResponse
}
}