DDD로 개발할 때 알아야 할 4가지 기본사항
20016 단어 TypeScriptDDDtech
이 글에서 저는 먼저 DDD의 모델링 부분을 한쪽에 놓고 코드를 실현하는 토대에서 비교적 좋은 것을 알고 소개하고자 합니다.이것들은 모두 기본적인 내용이기 때문에 DDD를 장악한 사람은 새로운 발견이 없을 수도 있다.
또한 예로 사용되는 언어는 Type Script입니다.
DDD로 설치해봤는데 뭐가 좋을까
주제에 들어가기 전에 먼저 DDD에서 실현되는 동력을 높이기 위해 실제 DDD에서 실현되는 몇 가지 장점을 열거했다.
파악해야 할 4가지 기본 사항
1. 도메인 레이어에서 ORM 솔리드와 다른 솔리드 준비
도메인 객체는 기본적으로 솔리드로 표시됩니다.실체를 듣자마자 ORM 실체가 생각날지도 모르지만 전혀 별개의 일이다.ORM의 실체는 특정한 프로그램 라이브러리, 예를 들어 TypeORM에 의존하지만 역층의 실체는 평면 대상이기 때문에 어떤 것도 의존할 수 없다.ORM의 실체에 논리를 쓰지 말고 역층을 위한 다른 실체를 준비하는 것을 포기하세요.
다음은 간단한 예이다.
domain/entity/User.ts
export default class User {
id: number;
familyName: string;
givenName: string;
constructor(id: number, familyName: string, givenName: string) {
this.id = id;
this.familyName = familyName;
this.givenName = givenName;
}
}
infra/entity/User.ts
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
@Entity()
export default class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: "varchar", default: "" })
familyName: string;
@Column({ type: "varchar", default: "" })
givenName: string;
constructor(id: number, familyName: string, givenName: string) {
this.id = id;
this.familyName = familyName;
this.givenName = givenName;
}
}
2. 창고 획득 방법으로 필드 대상으로 바꾸고 값을 되돌려줍니다
저장소에서 시스템을 가져오는 방법(find 등)은 DB에서 얻은 값을 직접 되돌려주는 것이 아니라 도메인 대상으로 변환해서 되돌려주는 것이다.따라서 창고에서 값을 받는 용례는 역 대상을 즉시 호출할 수 있습니다.다음은 예이다.
infra/repository/User.ts
public async findById(id: number): Promise<UserEntity | undefined> {
const user = await this.repository.findOne({ id }); // this.repositoryはTypeORMのリポジトリ
if (user == null) return;
return this.makeEntity(user);
}
// DBから取得した値をドメインオブジェクトに詰め替える処理
makeEntity(infraUser: User): UserEntity {
const user = new UserEntity(
infraUser.id,
infraUser.familyName,
infraUser.givenName
);
return user;
}
3. 대상과 창고는 일대일의 관계가 아니다
2의 설명을 보면 기본적으로 역 대상과 창고가 1대1로 연결되어 있다고 오해할 수 있지만 그렇지 않다.창고와 1대1의 연관성은 집약적인 개념이다.집합이란 교과서에서'통합성이 필요한 대상의 집합'이다.
상세한 설명은 생략하고 예를 들어 설명하다.
다음과 같은 경우 Article(글) 엔티티·Section(장) 엔티티는 개별적으로 존재할 수 없으며 그룹화를 전제로 해야 하는 경우 동일한 집합으로 그 집합 단위로 창고를 만들 수 있다.
전체 경로 Artical 엔티티
domain/entity/Article.ts
import Section from "./Section";
export default class Article {
id: number | null;
title: string;
sections: Section[];
constructor(id: number | null, title: string, sections: Section[]) {
this.id = id;
this.title = title;
this.sections = sections;
}
}
집계 경로와 연관된 Section 엔티티
domain/entity/Section.ts
export default class Section {
id: number | null;
title: string;
constructor(id: number | null, title: string) {
this.id = id;
this.title = title;
}
}
통합 루트 웨어하우스
infra/repository/Article.ts
public async save(article: ArticleEntity): Promise<void> {
// Article(記事)とそれに紐づくSection(章)をセットで保存する
const result = await this.repository.save(article);
return;
}
4. 도메인 객체의 생성 방법과 DB의 값을 재구성하는 방법으로 분리
도메인 객체를 생성하는 방법에서 초기 값 등의 규칙을 설정하면 저장소에서 인스턴스를 DB 값으로 어셈블할 수 없습니다.
이 경우 도메인 객체의 생성 방법과 DB의 값에서 재구성하는 방법을 분리합니다.
다음은 예이다.
이 예에서, 필드 대상이 생성될 때create 방법을 호출하고, DB에서 재구성할 때 구조기라고 부른다.
domain/entity/User.ts
export default class User {
id?: number;
familyName: string;
givenName: string;
status: number;
constructor(
id: number | undefined,
familyName: string,
givenName: string,
status: number
) {
this.id = id;
this.familyName = familyName;
this.givenName = givenName;
this.status = status;
}
create(familyName: string, givenName: string): User {
return new User(
undefined, // 初期生成時にはidは決まらない
familyName,
givenName,
1 // 初期生成時のstatusは必ず1
);
}
}
덤
최종적으로 디렉터리는 다음과 같다.
.
├── domain
│ ├── entity
│ ├── repository
├── infra
│ ├── entity
│ └── repository
├── presentation
│ ├── middleware
│ ├── route
├── tests
│ ├── factory
│ ├── feature
│ └── unit
└── use-case
Reference
이 문제에 관하여(DDD로 개발할 때 알아야 할 4가지 기본사항), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/hisamitsu/articles/2937fc4dd9bd4c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)