Rumah >hujung hadapan web >tutorial js >TypeScript untuk Reka Bentuk Dipacu Domain (DDD)

TypeScript untuk Reka Bentuk Dipacu Domain (DDD)

Patricia Arquette
Patricia Arquetteasal
2024-12-25 17:18:14506semak imbas

Reka Bentuk Dipacu Domain (DDD) ialah pendekatan yang berkuasa untuk menangani sistem perisian yang kompleks dengan memfokuskan pada domain perniagaan teras dan logiknya yang berkaitan. TypeScript, dengan ciri penaipan yang kukuh dan moden, ialah alat yang sangat baik untuk melaksanakan konsep DDD dengan berkesan. Artikel ini meneroka sinergi antara TypeScript dan DDD, menawarkan cerapan praktikal, strategi dan contoh untuk merapatkan jurang antara reka bentuk dan kod.

Memahami Reka Bentuk Didorong Domain

Konsep Teras

1. Bahasa Ubiquitous
Kerjasama antara pembangun dan pakar domain menggunakan bahasa yang dikongsi untuk mengurangkan miskomunikasi.

2. Konteks Terbatas
Pemisahan yang jelas bagi bahagian domain yang berlainan, memastikan autonomi dan kejelasan dalam konteks tertentu.

3. Entiti dan Objek Nilai

  • Entiti: Objek dengan identiti unik.
  • Objek Nilai: Objek tidak berubah ditakrifkan oleh atributnya.

4. Agregat
Kelompok objek domain dianggap sebagai satu unit untuk perubahan data.

5. Repositori
Abstrak logik kegigihan, menyediakan akses kepada agregat.

6. Acara Domain
Isyarat dipancarkan apabila tindakan penting berlaku dalam domain.

7. Perkhidmatan Aplikasi
Merangkumkan aliran kerja perniagaan dan logik orkestrasi.

Mengapa TypeScript Sesuai dengan DDD

1. Penaipan Statik: Pemeriksaan jenis yang kuat membantu memodelkan logik domain secara eksplisit.
2. Antara Muka: Menguatkuasakan kontrak antara komponen.
3. Kelas: Mewakili entiti, objek nilai dan agregat secara semula jadi.
4. Pengawal Jenis: Pastikan keselamatan taip semasa masa jalankan.
5. Jenis Utiliti: Dayakan transformasi jenis yang berkuasa untuk domain dinamik.

Perlaksanaan Praktikal

1. Entiti Pemodelan
Entiti mempunyai identiti unik dan merangkum gelagat.

class Product {
  constructor(
    private readonly id: string,
    private name: string,
    private price: number
  ) {}

  changePrice(newPrice: number): void {
    if (newPrice <= 0) {
      throw new Error("Price must be greater than zero.");
    }
    this.price = newPrice;
  }

  getDetails() {
    return { id: this.id, name: this.name, price: this.price };
  }
}



2. Mencipta Objek Bernilai
Objek Nilai tidak boleh diubah dan dibandingkan mengikut nilai.

class Money {
  constructor(private readonly amount: number, private readonly currency: string) {
    if (amount < 0) {
      throw new Error("Amount cannot be negative.");
    }
  }

  add(other: Money): Money {
    if (this.currency !== other.currency) {
      throw new Error("Currency mismatch.");
    }
    return new Money(this.amount + other.amount, this.currency);
  }
}



3. Mentakrifkan Agregat
Agregat memastikan ketekalan data dalam sempadan.

class Order {
  private items: OrderItem[] = [];

  constructor(private readonly id: string) {}

  addItem(product: Product, quantity: number): void {
    const orderItem = new OrderItem(product, quantity);
    this.items.push(orderItem);
  }

  calculateTotal(): number {
    return this.items.reduce((total, item) => total + item.getTotalPrice(), 0);
  }
}

class OrderItem {
  constructor(private product: Product, private quantity: number) {}

  getTotalPrice(): number {
    return this.product.getDetails().price * this.quantity;
  }
}



4. Melaksanakan Repositori
Akses data abstrak repositori.

interface ProductRepository {
  findById(id: string): Product | null;
  save(product: Product): void;
}

class InMemoryProductRepository implements ProductRepository {
  private products: Map<string, Product> = new Map();

  findById(id: string): Product | null {
    return this.products.get(id) || null;
  }

  save(product: Product): void {
    this.products.set(product.getDetails().id, product);
  }
}



5. Menggunakan Acara Domain
Peristiwa Domain memberitahu sistem perubahan keadaan.

class DomainEvent {
  constructor(public readonly name: string, public readonly occurredOn: Date) {}
}

class OrderPlaced extends DomainEvent {
  constructor(public readonly orderId: string) {
    super("OrderPlaced", new Date());
  }
}

// Event Handler Example
function onOrderPlaced(event: OrderPlaced): void {
  console.log(`Order with ID ${event.orderId} was placed.`);
}



6. Perkhidmatan Aplikasi
Perkhidmatan aplikasi menyelaras aliran kerja dan menguatkuasakan kes penggunaan.

class OrderService {
  constructor(private orderRepo: OrderRepository) {}

  placeOrder(order: Order): void {
    this.orderRepo.save(order);
    const event = new OrderPlaced(order.id);
    publishEvent(event); // Simulated event publishing
  }
}

7. Bekerja dengan Konteks Terbatas

Gunakan keupayaan modular TypeScript untuk mengasingkan konteks bersempadan.

  • Gunakan direktori berasingan untuk setiap konteks.
  • Tentukan secara eksplisit antara muka untuk komunikasi merentas konteks.

Contoh struktur:

class Product {
  constructor(
    private readonly id: string,
    private name: string,
    private price: number
  ) {}

  changePrice(newPrice: number): void {
    if (newPrice <= 0) {
      throw new Error("Price must be greater than zero.");
    }
    this.price = newPrice;
  }

  getDetails() {
    return { id: this.id, name: this.name, price: this.price };
  }
}

Ciri Lanjutan

Jenis Bersyarat untuk Pemodelan Fleksibel

class Money {
  constructor(private readonly amount: number, private readonly currency: string) {
    if (amount < 0) {
      throw new Error("Amount cannot be negative.");
    }
  }

  add(other: Money): Money {
    if (this.currency !== other.currency) {
      throw new Error("Currency mismatch.");
    }
    return new Money(this.amount + other.amount, this.currency);
  }
}

Jenis Tersurat Templat untuk Pengesahan

class Order {
  private items: OrderItem[] = [];

  constructor(private readonly id: string) {}

  addItem(product: Product, quantity: number): void {
    const orderItem = new OrderItem(product, quantity);
    this.items.push(orderItem);
  }

  calculateTotal(): number {
    return this.items.reduce((total, item) => total + item.getTotalPrice(), 0);
  }
}

class OrderItem {
  constructor(private product: Product, private quantity: number) {}

  getTotalPrice(): number {
    return this.product.getDetails().price * this.quantity;
  }
}

Tapak web peribadi saya: https://shafayet.zya.me


Nah, ini menunjukkan betapa aktifnya anda dalam Git-toilet...

TypeScript for Domain-Driven Design (DDD)


Imej Muka Depan dibuat dengan menggunakan OgImagemaker oleh

@eddyvinck .Terima kasih kerana menghadiahkan kami alat itu???...

Atas ialah kandungan terperinci TypeScript untuk Reka Bentuk Dipacu Domain (DDD). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn