Clean Architecture中仓储实现及用例与控制器构建位置咨询
Clean Architecture 医疗API实现疑问解答
1. Clean Architecture中如何实现仓储?
- 抽象定义在核心层(应用/领域层):你当前在应用层定义的
AbstractPatientRepository和AbstractTreatmentPlanRepository完全符合规则。这些抽象只需要包含业务逻辑所需的方法(比如findById、save),绝对不能掺杂任何框架、数据库相关的细节(比如SQL语句、ORM注解)。 - 具体实现放在基础设施层:在项目的
infrastructure/repositories目录下,编写对应抽象的具体实现类,比如PostgresPatientRepository、MongoTreatmentPlanRepository。这里是处理具体数据库操作的地方——不管用TypeORM、Prisma还是原生SQL,所有和外部存储相关的细节都封装在这里,对外只暴露抽象定义的接口。 - 严格遵守依赖方向:应用层只依赖仓储抽象,基础设施层依赖应用层的抽象,绝对不能反过来。比如
PostgresPatientRepository要import应用层的AbstractPatientRepository,而不是让应用层去import这个具体实现。
示例:基础设施层的仓储实现
// infrastructure/repositories/PostgresPatientRepository.ts import { AbstractPatientRepository } from '../../application/repositories/AbstractPatientRepository'; import { Patient } from '../../domain/entities/Patient'; export class PostgresPatientRepository implements AbstractPatientRepository { async findById(id: string): Promise<Patient | null> { // 这里写具体的Postgres查询逻辑,比如用Prisma // return await prisma.patient.findUnique({ where: { id } }); } // 实现抽象类中定义的其他业务方法 }
2. 应在何处构造CreateTreatmentPlanUseCase和CreateTreatmentPlanController?
这些对象的依赖组装必须放在框架/基础设施层的入口处,比如Express应用的启动文件(src/server.ts)或者专门的依赖注入配置文件(src/bootstrap.ts),绝对不能在接口适配层(比如Controller所在的web目录)里做这件事。
具体步骤:
- 先实例化基础设施层的具体仓储实现:
const patientRepo = new PostgresPatientRepository(); const treatmentPlanRepo = new PostgresTreatmentPlanRepository(); - 用仓储实例创建UseCase:
const createTreatmentPlanUseCase = new CreateTreatmentPlanUseCase(patientRepo, treatmentPlanRepo); - 再用UseCase创建Controller:
const createTreatmentPlanController = new CreateTreatmentPlanController(createTreatmentPlanUseCase); - 最后把Controller挂载到Express路由上:
app.post('/treatment-plans', async (req, res) => { await controller.execute(req, res); });
为什么不能在接口适配层组装?因为接口适配层的职责是把外部请求(HTTP)转换为应用层能处理的DTO,它只应该依赖应用层的抽象(比如UseCase),如果在这里实例化具体的仓储实现,会打破Clean Architecture的依赖规则——核心层(应用/领域)不依赖外层(接口适配、基础设施),外层可以依赖核心层。
内容的提问来源于stack exchange,提问作者z0mbieKale
相关产品推荐
相关产品推荐

