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.
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
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.
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.
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 } }
Gunakan keupayaan modular TypeScript untuk mengasingkan konteks bersempadan.
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 }; } }
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...
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!