我正在开发一个DDD项目,我有一个UseCase(ApplicationService),需要将项目部署到Kubernetes。因此,我有一个名为DeployProjectUseCase
的输入(projectId,databaseType),它首先需要检查应用程序使用的数据库类型,以便创建特定的pods、secrets等。它将调用Kubernetes的外部服务,但根据类型,它必须使用其中一些特定方法。我认为这个逻辑不应该在useCase中出现,而是使用DomainService,它将依赖注入外部服务。我不知道Domain Services是否可以进行远程过程调用,但我从Vaughn Vernon的书中找到了这个:
There are times when a Domain Service is concerned with remote invocations on
a foreign Bounded Context (2). Yet, the focus here is different in that the Domain
Service is not itself providing a remote procedure call interface but is rather the
client of the RPC.
所以,我想实现如下:
我有一个工厂,根据数据库类型返回适当的域服务。 DeployProjectUseCase
调用此工厂并将工作委托给域服务。 我创建了一个 NetworkServicePort
和一个适配器,使用 Kubernetes 库用于 Nodejs,以便注入到 useCase 中,然后再注入到域服务中:
NetworkServicePort
export interface NetworkServicePort {
createSecret(namespace: string, body: TCreateSecretBody): Promise<void>;
createStatefulSet(namespace: string, body: TCreateStatefulSetBody): Promise<void>;
createConfigMap(...): Promise<void>;
createPersistentVolume(...): Promise<void>;
...
}
部署项目用例
export class DeployProjectUseCase {
constructor(
private projectRepo: ProjectWriteRepoPort,
private networkService: NetworkServicePort,
) {}
async execute(requestDTO: DeployProjectRequestDTO): Promise<DeployProjectUseCaseResponse> {
const projectFound = await this.projectRepo.getById(projectId);
if (!projectFound) {
return fail(...);
}
const domainNetworkService = DomainNetworkServiceFactory.createDomainNetworkService(requestDTO.databaseType, this.networkService);
await domainNetworkService.deploy(projectFound);
...
await this.projectRepo.update(projectFound);
return ok();
}
}
DomainNetworkServiceFactory
export interface DomainNetworkService {
deploy(project: ProjectEntity): Promise<void>;
}
export class DomainNetworkServiceFactory {
static createDomainNetworkService(
type: string,
networkService: NetworkServicePort,
): DomainNetworkService {
switch (type) {
case 'mongo': {
return new MongoNetworkService(networkService);
}
case 'postgreSQL': {
return new PostgreSQLNetworkService(networkService);
}
default: {
...
}
}
}
}
MongoNetworkService
export class MongoNetworkService implements DomainNetworkService {
constructor(private networkService: NetworkServicePort) {}
public async deploy(project: ProjectEntity): Promise<void> {
// here have a mapper from Project aggregate to the DTO that service accepts
await this.networkService.createNamespace(...);
generatePassword(); // generate username and password from a library
await this.networkService.createSecret(...);
...
await this.networkService.createStatefulSet(...);
...
const infraNetworkService = InfraNetworkServiceEntity.create({
type: INFRA_NETWORK_SERVICE_TYPES.MONGO,
});
project.addInfraNetworkService(infraNetworkService);
}
}
PostgreSQL 网络服务
export class PostgreSQLNetworkService implements DomainNetworkService {
constructor(private networkService: NetworkServicePort) {}
public async deploy(project: ProjectEntity): Promise<void> {
// here have a mapper from Project aggregate to the DTO that service accepts
await this.networkService.createNamespace(...);
await this.networkService.createConfigMap(...);
await this.networkService.createPersistentVolume(...);
...
const infraNetworkService = InfraNetworkServiceEntity.create({
type: INFRA_NETWORK_SERVICE_TYPES.POSTGRESQL,
});
project.addInfraNetworkService(infraNetworkService);
}
}
在我看来,上述内容具有可以放在领域服务内的领域逻辑,但是领域服务能够进行远程过程调用吗?否则,这个逻辑可以放在应用服务中,但是这样做似乎不对,会污染应用服务。这种情况有意义吗?您如何使用DDD实现它?任何想法都将非常有帮助。
提前感谢您!