Nestjs:DDD实现 - IS
#javascript #typescript #体系结构 #nestjs

您可以阅读英文版本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体系结构中定义的层之间的依赖项。

ddd-image

域层

在此文件夹中,我们将定义将在应用程序中管理服务的实体和接口。
他们希望以这种方式看到它,我们正在创建应用程序中存在的数据库的实体,而无需导入或注入我们将占用的数据库的依赖项。
请记住,没有类型的类型存储库可以处理。

我们创建实体:

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!

我让您记得您可以使用aquí代码看到存储库。