クリーンアーキテクチャとは何ですか? Nodeで実装するにはどうすればいいでしょうか?
クリーン アーキテクチャとは何ですか?この記事では、クリーン アーキテクチャについて説明し、Node.js を使用してクリーン アーキテクチャを実装する方法について説明します。
クリーン アーキテクチャ
クリーン アーキテクチャは、Robert C. Martin によって提案された、システムを層に分割して目的を達成するソフトウェア アーキテクチャ パターンです。関心事の分離により、システムの理解、維持、拡張が容易になります。このアーキテクチャでは、システムが内部から外部に向かって、エンティティ層、ユースケース層、プレゼンテーション層、インフラストラクチャ (リポジトリ、フレームワークなど) の 4 つのレベルに分割されます。
この記事では、Node.js を使用してクリーン アーキテクチャを実装する方法を紹介し、アーキテクチャの主要な概念を示すサンプル コードをいくつか提供します。
次に、TypeScript プロジェクトの例 (github.com/lulusir/cle…) を使用します。プロジェクトは Monorepo 構造を使用し、Rush.js を使用して管理されます。サーバー フォルダーには、core、koa、nestjs-app という 3 つのサブプロジェクトが含まれています。Core はコア ビジネス ロジックであり、koa は基礎となるフレームワーク Web プロジェクトとして koa prisma を使用し、nestjs-app は基礎となるフレームワークとして nestjs typeorm を使用します。 。目的は、同じビジネス ロジックが異なるフレームワークをどのように橋渡しできるかを示すことです。 [関連チュートリアルの推奨事項: nodejs ビデオ チュートリアル 、プログラミング教育 ]
このプロジェクトでは、エンティティ レイヤーにはエンティティ オブジェクトと関連するビジネス ルールとロジックが含まれており、ケース層にはシステムのユースケースとビジネスロジックが含まれます。リポジトリ層はデータの保存と取得を担当し、プレゼンテーション層は外部に公開される http インターフェイスです。
プロジェクト機能:
投稿公開・閲覧機能の実現
ユーザー作成・クエリ
- #投稿の公開、編集、クエリ、削除
#├── server
│ ├── core // 核心业务逻辑
│ │ └── src
│ │ ├── domain
│ │ ├── repository
│ │ └── useCase
│ ├── koa
│ │ └── src
│ │ ├── post
│ │ └── user
│ └── nestjs-app
│ ├── src
│ ├── post
│ │ ├── dto
│ │ └── entities
│ └── user
│ └── entities
└── web
ログイン後にコピー #コア: コアはコア ビジネス ロジックのコードです。
├── server │ ├── core // 核心业务逻辑 │ │ └── src │ │ ├── domain │ │ ├── repository │ │ └── useCase │ ├── koa │ │ └── src │ │ ├── post │ │ └── user │ └── nestjs-app │ ├── src │ ├── post │ │ ├── dto │ │ └── entities │ └── user │ └── entities └── web
- ドメイン: ビジネス固有のモデルなどのエンティティ関連コードを格納します。 ユース ケース: 格納します。ビジネス ロジック関連コード ビジネス ロジックの処理、データ検証、リポジトリの呼び出しなどのコード。
- リポジトリ: 外部ストレージ システムのストレージおよび関連インターフェイス #koa/nestjs-app: core の実際のコンシューマー
- core のインターフェイスに基づいて特定のルーターとリポジトリを実装します
DDD とクリーン アーキテクチャのアイデアを使用して、ビジネス ロジックをフレームワークの実装から分離します。
モノリポジトリ プロジェクト構造を使用して、複数の関連プロジェクトの管理を容易にします。- 簡単にすぐに始められるように、複数のサンプル アプリケーションが提供されています。
- TypeScript に基づいており、コードの可読性と保守性が向上しています。 コアには、コア ビジネス ロジック コードがあります。このレベルには、ドメイン、リポジトリ インターフェイス、およびユースケースが含まれます。ドメインには、特定のビジネス モデルなどのエンティティに関連するコードが含まれています。リポジトリには、外部ストレージ システムへの関連インターフェイスが含まれています。ユースケースには、ビジネス ロジックの処理、データ検証、リポジトリの呼び出しなど、ビジネス ロジックに関連するコードが含まれています。 koa/nestjs-app レベルでは、コア レベルに実際のコンシューマーがいます。これらは、コア層によって提供されるインターフェイスに基づいて特定のルーターとリポジトリを実装します。 クリーン アーキテクチャを使用する主な利点の 1 つは、ビジネス ロジックを技術的な実装から分離できることです。これは、コアのビジネス ロジックを変更せずに、さまざまなフレームワークやライブラリを簡単に切り替えることができることを意味します。この例では、同じコア ビジネス ロジックを維持しながら、koa とnesjs-app を切り替えることができます。
エンティティ レイヤーの定義
// 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 }
ストレージ インターフェイスの定義
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");
}
}
ログイン後にコピー
#koa プロジェクト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"); } }
koa プロジェクトにストレージ レイヤー インターフェイスを実装する
// 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");
}
}
ログイン後にコピー
koa プロジェクトでの HTTP ルーティング (プレゼンテーション層) の実装// 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();
});
ログイン後にコピー
nest-js プロジェクト// 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(); });
nestjs プロジェクトの例ここにあります。パス内にあります (
github.com/lulusir/cle…コードはここには投稿しません最後に
実際のプロジェクトでは、コア ビジネス ロジックを別のウェアハウス (つまりコア) に配置しないことに注意してください。これは、別の環境でパフォーマンスを実証するためだけです。フレームワーク 同じビジネス ロジックを使用する
ビジネス ロジックをフレームワークから切り離すことにより、コア ビジネス ロジックを変更せずに、異なるフレームワークやライブラリを簡単に切り替えることができます。スケーラブルで保守可能なアプリケーションを構築したい場合は、クリーン アーキテクチャを検討する価値があります。
他のフレームワークに接続する方法をデモしたい場合は、コメント領域に
プロジェクト アドレス (github.com/lulusir/cle...#) を入力してください。 ## 良いアイデアだと思います。星を付けていただけます。ありがとうございます。
ノード関連の詳細については、nodejs チュートリアルをご覧ください。!
以上がクリーンアーキテクチャとは何ですか? Nodeで実装するにはどうすればいいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

SpringDataJPA は JPA アーキテクチャに基づいており、マッピング、ORM、トランザクション管理を通じてデータベースと対話します。そのリポジトリは CRUD 操作を提供し、派生クエリによりデータベース アクセスが簡素化されます。さらに、遅延読み込みを使用して必要な場合にのみデータを取得するため、パフォーマンスが向上します。

論文のアドレス: https://arxiv.org/abs/2307.09283 コードのアドレス: https://github.com/THU-MIG/RepViTRepViT は、モバイル ViT アーキテクチャで優れたパフォーマンスを発揮し、大きな利点を示します。次に、この研究の貢献を検討します。記事では、主にモデルがグローバル表現を学習できるようにするマルチヘッド セルフ アテンション モジュール (MSHA) のおかげで、軽量 ViT は一般的に視覚タスクにおいて軽量 CNN よりも優れたパフォーマンスを発揮すると述べられています。ただし、軽量 ViT と軽量 CNN のアーキテクチャの違いは十分に研究されていません。この研究では、著者らは軽量の ViT を効果的なシステムに統合しました。

Go フレームワーク アーキテクチャの学習曲線は、Go 言語とバックエンド開発への慣れ、選択したフレームワークの複雑さ、つまり Go 言語の基本の十分な理解によって決まります。バックエンドの開発経験があると役立ちます。フレームワークの複雑さが異なると、学習曲線も異なります。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

1. Llama3 のアーキテクチャ このシリーズの記事では、llama3 を最初から実装します。 Llama3 の全体的なアーキテクチャ: Llama3 のモデル パラメーターをイメージします: Llama3 モデルのこれらのパラメーターの実際の値を見てみましょう。図[1] コンテキストウィンドウ (context-window) LlaMa クラスをインスタンス化する際、変数 max_seq_len によって context-window が定義されます。クラスには他にもパラメータがありますが、このパラメータは変圧器モデルに最も直接関係しています。ここでの max_seq_len は 8K です。図[2] 語彙サイズと注意力L
