当前位置: 首页 > 后端技术 > Node.js

如何使用Node.js实现CleanArchitecture

时间:2023-04-03 19:36:42 Node.js

项目地址(https://github.com/lulusir/clean-architecture)如果觉得不错可以给个star,谢谢CleanArchitectureCleanArchitecturewas由RobertC.Martin提出的一种软件架构模式,其目的是对系统进行分层,实现关注点分离,使系统更易于理解、维护和扩展。该体系结构将系统分为四个层次,从内到外:实体层、用例层、表示层、基础设施(存储库、框架等)。在本文中,我们描述了如何使用Node.js实现CleanArchitecture,并提供了一些示例代码来演示该架构的关键概念。接下来我们将使用TypeScript项目示例(https://github.com/lulusir/clean-architecture)。该项目采用了Monorepo结构,并使用Rush.js进行管理。server文件夹包含三个子项目,分别是core、koa和nestjs-app,其中core是核心业务逻辑,koa是使用koa+prisma的底层框架web项目,nestjs-app是使用nestjs+typeorm作为Items的底层框架。目的是演示相同的业务逻辑如何桥接不同的框架。在这个项目中,实体层包含实体对象和相关的业务规则和逻辑,用例层包含系统用例和业务逻辑,存储层负责保存和检索数据,表现层暴露给外部http界面。项目功能:实现帖子发布、浏览功能、用户创建、查询帖子发布、编辑、查询、删除项目结构├──服务器│├──core//核心业务逻辑││└──src│├──domain││├──存储库││└──useCase│├──koa││└──src││├──post││└──user│└──nestjs-app│├──src│├──post││├──dto││└──entities│└──user│└──entities└──webcore:core是核心业务逻辑的代码Domain:存储实体相关的代码,比如业务具体models等UseCases:存放业务逻辑相关代码,如处理业务逻辑、数据校验、调用Repository等Repository:存放与外部存储系统Router、Repository项目的相关接口,使用DDD和CleanArchitecture思想将业务逻辑分离从框架实施。使用monorepo项目结构,方便管理多个相关项目。提供了几个示例应用程序以供快速启动。基于TypeScript,提高代码可读性和可维护性。在核心中,我们有核心业务逻辑代码。此级别包含域、存储库接口和用例。域包含与实体相关的代码,例如特定的业务模型。存储库包含与外部存储系统的相关接口。用例包含与业务逻辑相关的代码,例如处理业务逻辑、数据验证和调用存储库。在koa/nestjs-app层面,我们有核心层面的实际消费者。它们根据核心层提供的接口实现特定的路由器和存储库。使用CleanArchitecture的主要优点之一是它将业务逻辑与技术实现分开。这意味着您可以轻松地在不同的框架和库之间切换,而无需更改核心业务逻辑。在我们的示例中,我们可以在koa和nestjs-app之间切换,同时保持相同的核心业务逻辑。代码实际定义实体层//server/core/src/domain/post.tsimport{User}from"./user";exportclassPost{author:User|空=空;内容:字符串=“”;更新时间:日期=新日期();//时间戳;创建时间:日期=新日期();//时间戳;标题:字符串=“”;id:number=-1;}//server/core/src/domain/user.tsexportclassUser{name:string=''email:string=''id:number=-1}定义存储接口import{Post}来自“../domain/post”;导出接口IPostRepository{create(post:Post):Promise;find(id:number):Promise<帖子>;更新(发布:发布):承诺<布尔值>;删除(发布:发布):承诺<布尔值>;findMany(options:{authorId:number}):Promise;}...从"../domain/user"导入{User};exportinterfaceIUserRepository{create(user:User):Promise;find(id:number):Promise;}确定使用示例层import{User}from"../domain/user";从“../repository/user”导入{IUserRepository};导出类UCUser{构造函数(publicuserRepo:IUserRepository){}find(id:number){returnthis.userRepo.find(id);}create(name:string,email:string){if(email.includes("@test.com")){constuser=newUser();user.email=电子邮件;user.name=名字;返回this.userRepo.create(user);}throwError("请使用合法邮箱");}}koa项目在koa项目中实现存储层接口//server/koa/src/user/user.repo.tsimport{PrismaClient}from"@prisma/client";import{IUserRepository,User}from"core";export类UserRepository实现IUserRepository{prisma=newPrismaClient();asynccreate(user:User):Promise{constd=awaitthis.prisma.user_orm_entity.create({data:{email:user.email,name:user.name,},});}返回!!d;}asyncfind(id:number):Promise<用户>{constd=awaitthis.prisma.user_orm_entity.findFirst({其中:{id:id,},});如果(d){constu=newUser();u.email=d?.email;你.id=d?.id;u.name=d?.name;返回你;}throwError("用户id"+id+"未找到");}}在koa项目中实现HTTP路由(表示层)"./user.repo";exportconstuserRouter=newRouter({prefix:"/user",});userRouter.get("/:id",async(ctx,next)=>{try{constservice=newUCUser(newUserRepository());if(ctx.params.id){constu=awaitservice.find(+ctx.params.id);ctx.response.body=JSON.stringify(u);}}catch(e){ctx.throw(400,"someerrorongetuser",e.message);}等待下一个();});nest-js项目nestjs项目的示例可以在这个路径中找到(https://githubb.com/lulusir/clean-architecture/tree/main/server/nestjs-app)这里就不贴代码了最后请注意,在实际项目中,我们不会将核心业务逻辑放在单独的仓库(即core),这只是为了演示在不同的框架下使用相同的业务逻辑通过将业务逻辑与框架分离,你可以在不改变核心业务逻辑的情况下轻松地在不同的框架和库之间切换如果你想构建可伸缩和可维护的应用程序,那么CleanArchitecture绝对值得考虑。如果想演示如何接入其他框架,可以在评论区提交项目地址(https://github.com/lulusir/clean-architecture)。觉得不错的朋友可以给个star,谢谢