Rust में DDD: बिना दर्द और मैक्रोज़ के डोमेन कोड कैसे लिखें

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Rust प्रोजेक्ट्स में Domain-Driven Design: जब प्रकार आपके सहयोगी बन जाते हैं

\n\n

क्या आपने कभी Rust एप्लिकेशन लिखा है जिसमें व्यावसायिक तर्क संरचनाओं, ट्रेट्स और मैक्रोज़ के समुद्र में डूब गया हो? वह परिचित भावना जब कोड को देखकर आप तुरंत नहीं बता सकते कि कोई फ़ंक्शन विषय क्षेत्र के संदर्भ में क्या करता है? यदि हाँ — तो क्लब में आपका स्वागत है। Domain-Driven Design (DDD) इस समस्या को हल करने के लिए बनाया गया है, और Rust अपनी प्रकार प्रणाली के साथ DDD सिद्धांतों को लागू करने के लिए एक आदर्श मैदान है।

\n\n

इस लेख में हम इवांस की पुस्तक को दोबारा नहीं बताएंगे। इसके बजाय, मैं दिखाऊंगा कि वास्तविक उदाहरणों के साथ Rust प्रोजेक्ट्स में Domain-Driven Design कैसे लागू करें। आप सीखेंगे कि कैसे रैपर प्रकारों, मॉड्यूलर आर्किटेक्चर और अभिव्यंजक संरचनाओं की मदद से डोमेन कोड को स्वच्छ, सुरक्षित और समझने योग्य बनाया जाए। चलिए शुरू करते हैं!

\n\n

Rust और DDD एक आदर्श जोड़ी क्यों हैं

\n\n

Domain-Driven Design के लिए डोमेन लॉजिक को इन्फ्रास्ट्रक्चर से सख्ती से अलग करना आवश्यक है। Rust इसके लिए शक्तिशाली उपकरण प्रदान करता है:

\n\n
    \n
  • प्रकार प्रणाली — कंपाइलर स्तर पर व्यावसायिक नियमों को मॉडल करने की अनुमति देती है। गलती? कंपाइलर इसे होने नहीं देगा।
  • \n
  • स्वामित्व और उधार — गारंटी देता है कि एग्रीगेट्स और एंटिटीज़ गलती से अप्रत्याशित स्थान पर संशोधित नहीं होंगी।
  • \n
  • मॉड्यूलर प्रणाली — डोमेन लेयर, इन्फ्रास्ट्रक्चर और एप्लिकेशन को स्पष्ट रूप से अलग करती है।
  • \n
\n\n

लेकिन कुछ चुनौतियाँ भी हैं। Rust बहुत अधिक म्यूटेबल स्टेट वाली "भारी" वस्तुओं को माफ नहीं करता है। इसलिए Rust में DDD के लिए Java या C# की तुलना में मॉडलिंग के लिए एक अलग दृष्टिकोण की आवश्यकता होती है।

\n\n

मुख्य विचार: अमान्य अवस्थाओं को अप्रस्तुत करें

\n\n

DDD में हम प्रयास करते हैं कि व्यावसायिक नियम डेटा संरचना में ही एन्कोडेड हों। Rust में यह एक मंत्र बन जाता है: "यदि कोई स्थिति अमान्य है — तो इसे बनाना असंभव बना दें"।

\n\n

यह लिखने के बजाय:

\n\n
struct User {\n    name: String,\n    email: String,\n    age: u8,\n}
\n\n

हम ऐसे प्रकार बनाते हैं जो पहले से ही कंपाइलेशन चरण में शुद्धता की गारंटी देते हैं:

\n\n
pub struct Email(String);\npub struct Age(u8);\npub struct UserName(String);\n\npub struct User {\n    name: UserName,\n    email: Email,\n    age: Age,\n}
\n\n

क्या यह सिर्फ रैपर लगता है? वास्तव में यह Rust पर DDD की ओर पहला कदम है, जहाँ प्रकार दस्तावेज़ीकरण और इनवेरिएंट के संरक्षक बन जाते हैं।

\n\n

डोमेन मॉडलिंग: Value Object और Entity

\n\n

DDD की केंद्रीय अवधारणाएँ — Entity (सत्ता) और Value Object (मान-वस्तु) हैं। Rust में इन्हें अलग-अलग तरीके से लागू किया जाता है।

\n\n

Rust में Value Object: अपरिवर्तनीयता और मान द्वारा समानता

\n\n

Value Object की कोई पहचान नहीं होती। दो वस्तुएँ समान होती हैं यदि उनके फ़ील्ड समान हों। Rust में यह #[derive(PartialEq)] और अपरिवर्तनीय फ़ील्ड वाली संरचनाओं पर पूरी तरह से फिट बैठता है।

\n\n
use std::fmt;\n\n#[derive(Debug, Clone, PartialEq)]\npub struct Money {\n    amount: i64,\n    currency: Currency,\n}\n\n#[derive(Debug, Clone, PartialEq)]\npub enum Currency {\n    USD,\n    EUR,\n    RUB,\n}\n\nimpl Money {\n    pub fn new(amount: i64, currency: Currency) -> Self {\n        // व्यावसायिक नियम: पैसा नकारात्मक नहीं हो सकता\n        assert!(amount >= 0, "Amount must be non-negative");\n        Self { amount, currency }\n    }\n\n    pub fn add(&self, other: &Money) -> Result<Self, String> {\n        if self.currency != other.currency {\n            return Err("Cannot add different currencies".into());\n        }\n        Ok(Self::new(self.amount + other.amount, self.currency.clone()))\n    }\n}
\n\n

ध्यान दें: Money अपरिवर्तनीय है। कोई भी ऑपरेशन एक नई वस्तु लौटाता है। यह Rust में DDD के दर्शन के अनुरूप है: कोई सेटर नहीं, केवल वे विधियाँ जो नए उदाहरण बनाती हैं।

\n\n

Entity: पहचान

ब्लॉग

पुस्तक अनुशंसाएँ