您可以阅读英文版本here
嘿!在本文中,我们将讨论域驱动的设计的清洁架构的实现(ddd) nestjs ,从处理文件夹的处理中看到了点为了在“层”之间注入依赖项,我们将处理ODM mongoose
,尽管您可以使用自己喜欢的ORM/HAC!
全部文章,看看喷泉喷泉aquí!
为什么这些?
Nestjs是一个NodeJS框架,除了向我们提供基于图层的体系结构(Módulos)以在应用程序中分开职责外,还为我们提供了一个相当完整的工具箱。毫无疑问,在创建基于Nodejs的项目中要考虑的框架。
为什么要DDD?
域驱动的设计是一种软件设计方法,专注于 Leaws 和建模应用程序的域,围绕关键业务概念构建软件。
此外,作为“架构模式”,它使代码的实现和读取更加容易。
如果您以前没有关于DDD的知识,我建议您este articulo。
项目解释
,因为有些人通过实践学习更好。
多个组织中的猫采用系统
不同猫的收养组织可以录制可用于采用的猫的系统。应该注意的是,猫不属于任何特定组织,而是所有猫共享数据。该信息将存储在MongoDB数据库中,其中有两个无关的集合, cats 和组织。。
文件夹架构
.
└──src
├──application
| ├──cat (module)
| └──organization (module)
├──domain
| ├──entities
| └──interfaces
└──infrastructure
├──schemas
└──services
一旦看到了这一点,我们就必须记住DDD体系结构中定义的层之间的依赖项。
域层
在此文件夹中,我们将定义将在应用程序中管理服务的实体和接口。
他们希望以这种方式看到它,我们正在创建应用程序中存在的数据库的实体,而无需导入或注入我们将占用的数据库的依赖项。
请记住,没有类型的类型存储库可以处理。
我们创建实体:
export enum CatStatus {
AVAILABLE = 'available',
PENDING = 'pending',
ADOPTED = 'Adopted',
}
export class CatEntity {
id?: string;
name: string;
age: number;
color: string;
status: CatStatus;
}
现在接口:
import { CatEntity } from "../Entities/Cat.entity";
export interface ICatRepository {
findById(id: string): Promise<CatEntity>;
create(cat: CatEntity): Promise<string>;
delete(id: string): Promise<boolean>;
}
export const ICatRepository = Symbol('ICatRepository');
在此层中,我们将定义(在这种情况下)和与数据库相关的服务,所有这些元素都继承了我们在域层中创建的实体和接口的属性。
我们创建了继承kude1实体字段的方案:
@Schema()
export class Cats implements CatEntity {
@Prop({
type: String,
required: true
})
name: string;
@Prop({
type: Number,
required: true
})
age: number;
@Prop({
type: String,
required: true
})
color: string;
@Prop({
type: String,
required: true
})
status: CatStatus;
}
export type CatDocument = Cats & Document;
export const CatSchema = SchemaFactory.createForClass(Cats);
现在您可能会问您,您是否有必要重新创建处理数据库的实体?答案仅是答案。我们需要将实体的属性映射到我们的ORM/ODM可以解释的语言中,您可以看到它们是如何是配置文件的。
现在他们触摸服务:
@Injectable()
export class CatMongoRepository implements ICatRepository {
constructor(
@InjectModel(Cats.name)
private catModel: Model<CatDocument>
) { }
async create(cat: CatEntity): Promise<string> {
const result = await this.catModel.create(cat);
return result._id;
}
async findById(id: string): Promise<CatEntity> {
const cat = await this.catModel.findById(id);
return cat;
}
async delete(id: string): Promise<boolean> {
const result = await this.catModel.deleteOne({ _id: new Types.ObjectId(id) });
return result.deletedCount > 0;
}
}
在这方面,我们将处理数据库的所有咨询。
从这里添加业务规则!
注入依赖项
准备就绪,我们已经配置了域和基础架构层,现在只需要配置依赖的注入。
首先,我们必须在基础架构层中导出服务,以及kouude2:
const mongooseSchemas = [{
name: Cats.name,
schema: CatSchema
}, {
name: Organizations.name,
schema: OrganizationSchema
}];
@Module({
imports: [
MongooseModule.forRoot(`mongodb://admin:password123@mongo-ddd:27017/accounts?authSource=admin&readPreference=primary&ssl=false&directConnection=true`),
MongooseModule.forFeature(mongooseSchemas)
],
controllers: [],
providers: [
OrganizationMongoRepository,
CatMongoRepository
],
exports: [
MongooseModule.forFeature(mongooseSchemas),
OrganizationMongoRepository,
CatMongoRepository,
]
})
export class InfrastructureModule { };
现在,在域层中,要处理单元的注入,我们必须导入基础架构层并配置要注入域层接口的基础结构服务:
@Module({
imports: [InfrastructureModule],
controllers: [],
providers: [{
provide: ICatRepository,
useClass: CatMongoRepository
}, {
provide: IOrganizationRepository,
useClass: OrganizationMongoRepository
}],
exports: [{
provide: ICatRepository,
useClass: CatMongoRepository
}, {
provide: IOrganizationRepository,
useClass: OrganizationMongoRepository
}]
})
export class DomainModule { };
对于似乎更矛盾的是,我们正在破坏DDD规则之一,因此没有人必须依赖基础架构层,但是,由于Nestjs的局限性,这是我发现执行此任务的唯一途径。
依赖性很小!而且它仅限于domain.module.ts
中的配置。
使用服务
在我们的cat
模块中,在应用程序层中,我们必须以这种方式导入域模块,我们可以通过注入依赖项来使用界面!:
@Injectable()
export class CatService {
constructor(
@Inject(ICatRepository)
private catRepository: ICatRepository
) { }
async create(data: CatCreateDto): Promise<string> {
const cat = new CatEntity();
cat.name = data.name;
cat.age = data.age;
cat.color = data.color;
cat.status = CatStatus.AVAILABLE;
return await this.catRepository.create(cat);
}
async findById(id: string): Promise<any> {
const result = await this.catRepository.findById(id);
return result;
}
async delete(id: string): Promise<boolean> {
const result = await this.catRepository.delete(id);
return result;
}
}
结论
这是Nestjs中DDD实现的非常重要的视图,这是您使用SQL是否使用的数据库的Agnóstica。
毫无疑问,没有看到很多东西,例如我们在这方面管理模拟文章的事实,我希望您能够更好地了解这种建筑设计在Nestjs中的实现,并见到您,Frengers! P>
我让您记得您可以使用aquí代码看到存储库。