* In this article, examples will be in TypeScript
Brief preface
DDD (Domain Driven Design) , ( ) — , , , . , , , , ( 1).
.
, DDD.
— DDD.
.
, , .
(.1):
.1
, ?
, , .
, , .
, .
, .
, DDD .
:
- . , .
- , , , . :
- , , , ..
- .
- — , .
, , :
- , , , .
.
.
, , , , , ..?
(.2):
.2
, , , , , , — , , , .
, , .
.
(.2), , , — .
:
- — , . , . .
- — , . .
- — , . , . .
- — , . , . .
- — , , . . , .
, , :
- .
, . , , — , . . 2 — . - . . .
- , .
- , .
- , ( data-transfer-object- DTO-).
- unit . (DI) , → .
,
- , , .
- , ().
- — , . , ORM, , , ORM . API, , , 2 : , .
- , .
CRM, , ORM TypeORM, — PostgresSQL.
, ,
.
:
.3
:
@clients = src/domains/clients @clientsEnities = src/adapters/typeorm/entities/clients @adapters = src/adapters
:
, , .
, . 2 :
domains/clients/models/Client.ts
import { Contact } from './Contact';
export interface Client {
id: number;
title: string;
contacts?: Contact[];
}
domains/clients/models/Contact.ts
import { Client } from './Client';
export enum ContactType {
PHONE = 'phone',
EMAIL = 'email',
}
export interface Contact {
client?: Client;
type: ContactType;
value: string;
}
TypeORM enitity
adapters/typeorm/entities/clients/Client.ts
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Client as ClientModel } from '@clients/models/Client';
import { Contact } from './Contact';
@Entity({ name: 'clients' })
export class Client implements ClientModel {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@OneToMany((_type) => Contact, (contact) => contact.client)
contacts?: Contact[];
}
adapters/typeorm/entities/clients/Contact.ts
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { Contact as ContactModel, ContactType } from '@clients/models/Contact';
import { Client } from './Client';
@Entity({ name: 'contacts' })
export class Contact implements ContactModel {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'string' })
type: ContactType;
@Column()
value: string;
@ManyToOne((_type) => Client, (client) => client.contacts, { nullable: false })
client?: Client;
}
: .. , . , - — .
.
domains/clients/methods/createClient.ts
import { Repository } from 'typeorm';
import { Client as ClientModel } from '@clients/models/Client';
import { Client } from '@clientsEnities/Client';
export async function createClient(repo: Repository<Client>, clientData: ClientModel) {
const client = await repo.save(clientData);
return client;
}
domains/clients/index.ts
import { Connection } from 'typeorm';
import { Client } from '@clientsEnities/Client';
import { Client as ClientModel } from '@clients/models/Client';
import { createClient } from './methods/createClient';
export class Clients {
protected _connection: Connection;
constructor(connection: Connection) {
if (!connection) {
throw new Error('No connection!');
}
this._connection = connection;
}
protected getRepository<T>(Entity: any) {
return this._connection.getRepository<T>(Entity);
}
protected getTreeRepository<T>(Entity: any) {
return this._connection.getTreeRepository<T>(Entity);
}
public async createClient(clientData: ClientModel) {
const repo = this.getRepository<Client>(Client);
const client = await createClient(repo, clientData);
return client;
}
}
.. TypeORM , ( DI) , connection, .
.
businessProcesses/createClient.ts
import { Client as ClientModel } from '@clients/models/Client';
import { Clients } from '@clients';
import { db } from '@adapters/typeorm'; // TypeORM db
export function createClient(clientData: ClientModel) {
const clients = new ClientService(db.connection)
const client = await clients.createClient(clientData)
return client
}
, , . .
?
- .
- . . . — , .
- . , — ( , ), , .
- . . DTO , , , , . — , .
- . , . ,
notifications
notifications.notifyClient({ client: client.id, type:’SUCCESS_REGISTRATION’ })
, , !