Qu’est-ce que l’architecture propre ? Cet article vous présentera Clean Architecture et expliquera comment implémenter Clean Architecture à l'aide de Node.js. J'espère que cela vous sera utile !
Clean Architecture est un modèle d'architecture logicielle proposé par Robert C. Martin. Le but est de superposer le système et de parvenir à une séparation des préoccupations, rendant le système plus facile à comprendre, à maintenir et à développer. Cette architecture divise le système en quatre niveaux, de l'intérieur vers l'extérieur : couche entité, couche cas d'utilisation, couche présentation, infrastructure (référentiel, framework, etc.).
Dans cet article, nous présenterons comment implémenter une architecture propre à l'aide de Node.js et fournirons des exemples de code pour démontrer les concepts clés de l'architecture.
Ensuite, nous utiliserons l'exemple de projet TypeScript (github.com/lulusir/cle… ). Le projet utilise une structure Monorepo et est géré à l'aide de Rush.js. Le dossier du serveur contient trois sous-projets, à savoir core, koa et nestjs-app. Core est la logique métier de base, koa utilise koa+prisma comme projet Web de cadre sous-jacent et nestjs-app utilise nestjs + typeorm. cadre sous-jacent. L’objectif est de démontrer comment la même logique métier peut relier différents frameworks. [Tutoriels associés recommandés : Tutoriel vidéo Nodejs, Enseignement de la programmation]
Dans ce projet, la couche d'entité contient les objets d'entité et les règles et logiques métier associées, la couche de cas d'utilisation contient les cas d'utilisation et la logique métier du système, et la couche référentiel est responsable Pour enregistrer et récupérer les données, la couche de présentation est exposée à l'interface http externe.
Implémenter une fonction de publication de publication, de navigation
création d'utilisateur, requête
publication de publication, édition, interrogation, suppression
├── server │ ├── core // 核心业务逻辑 │ │ └── src │ │ ├── domain │ │ ├── repository │ │ └── useCase │ ├── koa │ │ └── src │ │ ├── post │ │ └── user │ └── nestjs-app │ ├── src │ ├── post │ │ ├── dto │ │ └── entities │ └── user │ └── entities └── web
core : core est le code de la logique métier de base
// server/core/src/domain/post.ts import { User } from "./user"; export class Post { author: User | null = null; content: string = ""; updateAt: Date = new Date(); // timestamp; createdAt: Date = new Date(); // timestamp; title: string = ""; id: number = -1; } // server/core/src/domain/user.ts export class User { name: string = '' email: string = '' id: number = -1 }
Définir l'interface de stockage
import { Post } from "../domain/post"; export interface IPostRepository { create(post: Post): Promise<boolean>; find(id: number): Promise<Post>; update(post: Post): Promise<boolean>; delete(post: Post): Promise<boolean>; findMany(options: { authorId: number }): Promise<Post[]>; } ... import { User } from "../domain/user"; export interface IUserRepository { create(user: User): Promise<boolean>; find(id: number): Promise<User>; }
import { User } from "../domain/user"; import { IUserRepository } from "../repository/user"; export class UCUser { constructor(public userRepo: IUserRepository) {} find(id: number) { return this.userRepo.find(id); } create(name: string, email: string) { if (email.includes("@test.com")) { const user = new User(); user.email = email; user.name = name; return this.userRepo.create(user); } throw Error("Please use legal email"); } }
// server/koa/src/user/user.repo.ts import { PrismaClient } from "@prisma/client"; import { IUserRepository, User } from "core"; export class UserRepository implements IUserRepository { prisma = new PrismaClient(); async create(user: User): Promise<boolean> { const d = await this.prisma.user_orm_entity.create({ data: { email: user.email, name: user.name, }, }); return !!d; } async find(id: number): Promise<User> { const d = await this.prisma.user_orm_entity.findFirst({ where: { id: id, }, }); if (d) { const u = new User(); u.email = d?.email; u.id = d?.id; u.name = d?.name; return u; } throw Error("user id " + id + "not found"); } }
// server/koa/src/user/user.controller.ts import Router from "@koa/router"; import { UCUser } from "core"; import { UserRepository } from "./user.repo"; export const userRouter = new Router({ prefix: "/user", }); userRouter.get("/:id", async (ctx, next) => { try { const service = new UCUser(new UserRepository()); if (ctx.params.id) { const u = await service.find(+ctx.params.id); ctx.response.body = JSON.stringify(u); } } catch (e) { ctx.throw(400, "some error on get user", e.message); } await next(); });
Veuillez noter que dans le projet réel, nous ne placerons pas la logique métier de base dans un entrepôt séparé (c'est-à-dire le noyau), il s'agit simplement de démontrer l'utilisation de la même logique métier dans différents cadres
En mettant la logique métier La logique est séparée du framework et vous pouvez facilement basculer entre différents frameworks et bibliothèques sans modifier la logique métier principale. Si vous souhaitez créer des applications évolutives et maintenables, l’architecture propre mérite certainement d’être envisagée.
Si vous souhaitez démontrer comment vous connecter à d'autres frameworks, vous pouvez le proposer dans la zone de commentaire
Adresse du projet (github.com/lulusir/cle… Si vous pensez que c'est bien, vous pouvez lui donner une étoile , merci
Plus de détails sur les nœuds Pour plus de connaissances, veuillez visiter : tutoriel Nodejs !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!