यह कहना अभिनव नहीं होना चाहिए कि सॉफ्टवेयर लिखना केवल कोड लिखने के बारे में नहीं है - यह किसी विशेष समस्या को हल करने के बारे में है। भले ही यह डेवलपर्स ही हैं जो अंततः समाधान लागू करते हैं, लेकिन यह डेवलपर्स नहीं हैं जो सबसे पहले यह परिभाषित करते हैं कि समस्या क्या है। यह कार्य विभिन्न व्यावसायिक लोगों द्वारा किया जाता है, जो यह बताने के लिए प्रक्रियाओं, जोखिमों और परिणामों पर विचार करते हैं कि समस्या क्या है, यह क्यों मौजूद है और इसे कैसे संबोधित किया जाना चाहिए। डोमेन-संचालित संदर्भ में, इन व्यवसायियों को डोमेन विशेषज्ञ कहा जाता है।
इंजीनियरिंग के दृष्टिकोण से, ऐसा प्रतीत होता है कि डोमेन विशेषज्ञों के पास एक मूल्यवान संपत्ति है: डोमेन के बारे में उनका ज्ञान। हालाँकि, इस ज्ञान को इसके कच्चे रूप में शायद ही कभी साझा किया जाता है। इसके बजाय, इसे आमतौर पर आवश्यकताओं में अनुवादित किया जाता है ताकि डेवलपर्स इसे समझ सकें और लागू कर सकें। इस दृष्टिकोण के साथ समस्या यह है कि व्यावसायिक लोगों और डेवलपर्स के डोमेन ज्ञान में भिन्नता हो सकती है। इसका मतलब यह है कि जो लोग समस्या को परिभाषित करते हैं और जो लोग इसे हल करने पर काम करते हैं, उनके दृष्टिकोण एक समान नहीं हो सकते हैं, जिससे गलतफहमी और संघर्ष हो सकता है।
तो फिर रास्ता क्या है? सुनिश्चित करें कि व्यावसायिक और तकनीकी लोग समान भाषा और शब्दावली का उपयोग करें।
डोमेन-संचालित डिज़ाइन (डीडीडी) एक पद्धति है जो डोमेन विशेषज्ञों और तकनीकी हितधारकों के बीच साझा समझ बनाने और अंतर्निहित व्यावसायिक आवश्यकताओं के साथ सॉफ़्टवेयर समाधान को संरेखित करने के महत्व पर जोर देती है। यह एक उच्च स्तरीय, गैर-तकनीकी परिभाषा प्रतीत होती है, लेकिन इसे अधिक डेवलपर-अनुकूल में भी विभाजित किया जा सकता है:
डीडीडी कोड में वास्तविक दुनिया की अवधारणाओं का प्रतिनिधित्व कर रहा है, और सर्वव्यापी भाषा का विकास और उपयोग करके इसकी संरचना, जो कि व्यावसायिक डोमेन को मॉडलिंग करके बनाई गई है।
अभी भी कुछ शब्दावली का परिचय दिया जाना बाकी है, इसलिए यह अभी 100% स्पष्ट नहीं हो सकता है। सबसे महत्वपूर्ण बात यह है कि डीडीडी ऐसे उपकरण और गतिविधियाँ प्रदान करता है जो व्यावसायिक दृष्टिकोण के अनुरूप कोड लिखने और संरचना करने की अनुमति देते हैं। यह न केवल संचार के बारे में है बल्कि डिज़ाइन निर्णय लेने के बारे में भी है जो वास्तव में आम भाषा को आकार देता है।
इसमें कोई आश्चर्य नहीं होना चाहिए कि DDD दुनिया में सबसे महत्वपूर्ण शब्द डोमेन है। "लर्निंग डोमेन-ड्रिवेन डिज़ाइन" के लेखक व्लाद खोनोनोव इसका वर्णन इस प्रकार करते हैं:
एक व्यावसायिक डोमेन किसी कंपनी की गतिविधि के मुख्य क्षेत्र को परिभाषित करता है।
इसका मतलब है कि व्यवसाय डोमेन को इस प्रकार भी माना जा सकता है:
डोमेन को उपडोमेन में भी विभाजित किया जा सकता है - गतिविधियों की अधिक विशिष्ट श्रेणियाँ। जबकि तीन अलग-अलग प्रकार के उपडोमेन हैं, सबसे महत्वपूर्ण एक है कोर । यह बताता है कि कंपनी व्यावसायिक लाभ कैसे प्राप्त करती है। अन्य दो अधिक सामान्य, सामान्य समस्याओं के बारे में हैं, जैसे प्रमाणीकरण प्रणाली या आंतरिक व्यवस्थापक पैनल।
डोमेन-संचालित डिज़ाइन के लाभों का पूरी तरह से उपयोग करने के लिए किसी कंपनी के व्यावसायिक डोमेन की गहरी समझ होना अत्यंत महत्वपूर्ण है। इस समझ का सबसे अच्छा स्रोत कोई और नहीं बल्कि डोमेन विशेषज्ञ हैं। ये वे व्यक्ति हैं जिनकी समस्या का समाधान सॉफ़्टवेयर के साथ किया जा रहा है - हितधारक, विभिन्न व्यावसायिक लोग और यहां तक कि उपयोगकर्ता भी। इसका मतलब यह नहीं है कि इंजीनियरों को उस डोमेन के बारे में जानकारी नहीं है जिस पर वे काम कर रहे हैं, बल्कि यह है कि विशेषज्ञ ही उस डोमेन के ज्ञान की सच्चाई का स्रोत हैं। डोमेन विशेषज्ञों के साथ मिलकर काम करके, डेवलपर्स यह सुनिश्चित कर सकते हैं कि डोमेन के मॉडल सटीक और अद्यतित रहें।
यह एक और महत्वपूर्ण लेकिन संभावित रूप से अस्पष्ट शब्द की ओर ले जाता है: मॉडल । एरिक इवांस ने डीडीडी के बारे में अपनी पुस्तक में मॉडल का वर्णन इस प्रकार किया है:
यह वास्तविकता की व्याख्या है जो मौजूदा समस्या को हल करने के लिए प्रासंगिक पहलुओं को अमूर्त कर देती है और बाहरी विवरणों को नजरअंदाज कर देती है।
व्लाद खोनोनोव इस विचार को ऐसे शब्दों में समझाते हैं जो अधिक प्रासंगिक हैं:
एक मॉडल वास्तविक दुनिया की नकल नहीं है, बल्कि एक मानवीय निर्माण है जो हमें वास्तविक दुनिया की प्रणालियों को समझने में मदद करता है।
अंत में, एक मॉडल एक व्यावसायिक अवधारणा या प्रक्रिया का प्रतिनिधित्व है जो डोमेन की अंतर्निहित जटिलता की समझ और संचार की सुविधा प्रदान करता है।
व्लाद ने एक डोमेन मॉडल की अवधारणा को प्रभावी ढंग से चित्रित करने के लिए एक मानचित्र का उपयोग किया। मानचित्र इस बात का एक आदर्श उदाहरण हैं कि कैसे वे केवल वही जानकारी प्रदर्शित करते हैं जो मानचित्र के प्रकार, जैसे स्थलाकृति, सड़कें या सीमाओं से संबंधित है। एक नक्शा जो एक ही बार में सभी विवरण प्रदर्शित करता है वह भारी और काफी हद तक बेकार होगा। डोमेन मॉडल अन्य रूपों में भी पाए जा सकते हैं, जैसे:
डोमेन-संचालित डिज़ाइन (डीडीडी) शब्दावली पहेली का अंतिम भाग सर्वव्यापी भाषा है। यह किसी परियोजना में तकनीकी और व्यावसायिक दोनों हितधारकों द्वारा उपयोग की जाने वाली साझा भाषा को संदर्भित करता है। डोमेन मॉडल से प्राप्त व्यावसायिक डोमेन का वर्णन करने के लिए एक सामान्य भाषा का होना DDD में महत्वपूर्ण है। यह सुनिश्चित करने में मदद करता है कि टीम के सभी सदस्यों को समस्या स्थान, उसकी अवधारणाओं और उनके संबंधों की स्पष्ट समझ है। इससे बेहतर संरेखण होता है और गलतफहमी का खतरा कम हो जाता है। सर्वव्यापी भाषा का उपयोग करके, सॉफ़्टवेयर समाधान अंतर्निहित व्यावसायिक आवश्यकताओं को सटीक रूप से प्रतिबिंबित कर सकता है, जिससे यह DDD का एक महत्वपूर्ण घटक बन जाता है।
अधिकांश शब्दावली को कवर करने के साथ, यह समझना आसान हो जाएगा कि डोमेन-संचालित डिज़ाइन क्या है । अब समय आ गया है कि डीडीडी के निर्माण खंडों के वास्तविक स्वरूप पर गौर किया जाए।
डीडीडी बिल्डिंग ब्लॉक एक प्रभावी और कुशल डोमेन मॉडल बनाने के लिए नींव के रूप में काम करते हैं। व्लाद खोनोनोव डोमेन मॉडल को इस प्रकार परिभाषित करते हैं:
एक डोमेन मॉडल डोमेन का एक ऑब्जेक्ट मॉडल है जिसमें व्यवहार और डेटा दोनों शामिल होते हैं।
डोमेन मॉडल में विभिन्न बिल्डिंग ब्लॉक और संरचनाएं शामिल हैं। सबसे महत्वपूर्ण ये हैं:
वैल्यू ऑब्जेक्ट उपलब्ध सबसे बुनियादी बिल्डिंग ब्लॉक हैं। ये ऐसी वस्तुएं हैं जिन्हें विशेषताओं और मूल्यों के एक सेट द्वारा परिभाषित किया गया है। उनके पास कोई विशिष्ट पहचानकर्ता नहीं है - उनके मूल्य उनकी पहचान को परिभाषित करते हैं। वे इस अर्थ में अपरिवर्तनीय हैं कि विभिन्न मूल्य पहले से ही एक अलग मूल्य वस्तु का प्रतिनिधित्व कर रहे हैं। मूल्य वस्तुओं के उदाहरणों में शामिल हैं:
यहां बताया गया है कि पायथन में एक सरल वैल्यू ऑब्जेक्ट कैसे लागू किया जा सकता है:
from pydantic import BaseModel class Address(BaseModel): """Customer address.""" country: str city: str street: str house_number: str class Config: frozen = True
इसका मतलब है कि दो पतों की तुलना करने के लिए समानता ऑपरेटर ( ==
) का उपयोग करने से केवल तभी True
वापस आएगा जब दोनों वस्तुओं में बिल्कुल समान मान निर्दिष्ट हों।
संस्थाएँ अगले प्रकार का बिल्डिंग ब्लॉक हैं। संस्थाएँ एक विशिष्ट पहचान के साथ डोमेन में व्यक्तिगत वस्तुओं का प्रतिनिधित्व करती हैं, जैसे कि कोई व्यक्ति या कोई आदेश। वे इस तरह से वैल्यू ऑब्जेक्ट के समान हैं कि वे डेटा भी संग्रहीत करते हैं, लेकिन उनकी विशेषताएं बदल सकती हैं और अपेक्षित हैं, और इस प्रकार उन्हें एक अद्वितीय पहचानकर्ता की आवश्यकता होती है। आदेश और व्यक्तिगत जानकारी संस्थाओं के केवल दो सरल उदाहरण हैं:
import uuid from pydantic import BaseModel, Field from practical_ddd.building_blocks.value_objects import Address class Person(BaseModel): """Personal data.""" id: uuid.UUID = Field(default_factory=uuid.uuid4) first_name: str last_name: str address: Address class Order(BaseModel): """Customer order.""" id: uuid.UUID = Field(default_factory=uuid.uuid4) description: str value: float
क्योंकि उदाहरणों के मान दोनों मामलों में परिवर्तनीय हैं, उन्हें एक पहचान की आवश्यकता है, जो यूयूआईडी हो सकती है। अधिक महत्वपूर्ण बात यह है कि, ज्यादातर मामलों में, संस्थाओं को सीधे प्रबंधित नहीं किया जाता है, बल्कि समग्र रूप से प्रबंधित किया जाता है।
एग्रीगेट एक प्रकार की इकाई है क्योंकि यह परिवर्तनशील है और इसके लिए एक विशिष्ट पहचानकर्ता की आवश्यकता होती है। हालाँकि, इसकी प्राथमिक ज़िम्मेदारी डेटा को संग्रहीत करना नहीं है, बल्कि संबंधित वस्तुओं (इकाईयों और मूल्य वस्तुओं) के एक समूह को एकरूपता की एकल इकाई के रूप में समूहित करना है। एग्रीगेट एक मूल वस्तु है, जिसमें एक अच्छी तरह से परिभाषित सीमा होती है जो इसकी आंतरिक स्थिति को समाहित करती है और पूरे समूह की स्थिरता सुनिश्चित करने के लिए अपरिवर्तनीयों को लागू करती है। समुच्चय वस्तुओं के बजाय वस्तुओं के बीच संबंधों पर ध्यान केंद्रित करके डोमेन के बारे में अधिक प्राकृतिक और सहज तरीके से तर्क करने की अनुमति देता है।
पिछले उदाहरणों के आधार पर, एक समुच्चय को एक ग्राहक के रूप में दर्शाया जा सकता है:
import uuid from pydantic import BaseModel, Field from practical_ddd.building_blocks.entities import Person, Order from practical_ddd.building_blocks.value_objects import Address class Customer(BaseModel): """Customer aggregate. Manages personal information as well as orders. """ id: uuid.UUID = Field(default_factory=uuid.uuid4) person: Person orders: list[Order] = Field(default_factory=list) def change_address(self, new_address: Address) -> None: self.person.address = new_address def add_order(self, order: Order) -> None: if self.total_value + order.value > 10000: raise ValueError("Order cannot have value higher than 10000") self.orders.append(order) def remove_order(self, order_id: uuid.UUID) -> None: order = next((order for order in self.orders if order.id == order_id), None) if order is None: raise IndexError("Order not found") self.orders.remove(order) @property def total_value(self) -> float: return sum(order.value for order in self.orders)
ग्राहक सीधे व्यक्तिगत डेटा से जुड़ा होता है, और यह सभी ऑर्डर संग्रहीत करता है। इसके अलावा, समग्रता व्यक्ति के पते को प्रबंधित करने के साथ-साथ ऑर्डर जोड़ने और हटाने के लिए एक इंटरफ़ेस को उजागर करती है। यह इस तथ्य के कारण है कि समुच्चय की स्थिति को केवल संबंधित तरीकों को क्रियान्वित करके ही बदला जा सकता है।
जबकि पिछला उदाहरण अपेक्षाकृत सीधा है, केवल एक बाधा के साथ (ऑर्डर मूल्य 10000 से अधिक नहीं हो सकता), इसे डीडीडी बिल्डिंग ब्लॉक्स और उनके संबंधों के उपयोग को प्रदर्शित करना चाहिए। वास्तविक प्रणालियों में, समुच्चय अक्सर अधिक जटिल होते हैं, जिनमें अधिक बाधाएँ, सीमाएँ और संभवतः अधिक संबंध होते हैं। आख़िरकार, उनका अस्तित्व ही इस जटिलता को प्रबंधित करने के लिए है। इसके अतिरिक्त, वास्तविक दुनिया में, समुच्चय आम तौर पर डेटाबेस जैसे डेटा स्टोर में बने रहेंगे। यहीं पर रिपॉजिटरी पैटर्न चलन में आता है।
समुच्चय की स्थिति में सभी बदलाव एक ही परमाणु ऑपरेशन में लेन-देन के आधार पर किए जाने चाहिए। हालाँकि, "खुद को कायम रखना" समुच्चय की ज़िम्मेदारी नहीं है। रिपोजिटरी पैटर्न डेटा भंडारण और पुनर्प्राप्ति के विवरणों को अलग करने की अनुमति देता है और इसके बजाय, उच्च स्तर के अमूर्तता पर समुच्चय के साथ काम करता है। सीधे शब्दों में कहें, एक रिपॉजिटरी को समुच्चय और डेटा भंडारण के बीच एक परत के रूप में माना जा सकता है। एक JSON फ़ाइल ऐसे स्टोर का एक काफी सरल उदाहरण है। ग्राहक समुच्चय में एक रिपॉजिटरी हो सकती है जो JSON फ़ाइलों पर काम करती है:
import json import uuid from practical_ddd.building_blocks.aggregates import Customer class CustomerJSONRepository: """Customer repository operating on JSON files.""" def __init__(self, path: str) -> None: self.path = path def get(self, customer_id: uuid.UUID) -> Customer: with open(self.path, "r") as file: database = json.load(file) customer = database["customers"].get(str(customer_id)) if customer is None: raise IndexError("Customer not found") person = database["persons"][str(customer["person"])] orders = [database["orders"][order_id] for order_id in customer["orders"]] return Customer( id=customer["id"], person=person, orders=orders, ) def save(self, customer: Customer) -> None: with open(self.path, "r+") as file: database = json.load(file) # Save customer database["customers"][str(customer.id)] = { "id": customer.id, "person": customer.person.id, "orders": [o.id for o in customer.orders], } # Save person database["persons"][str(customer.person.id)] = customer.person.dict() # Save orders for order in customer.orders: database["orders"][str(order.id)] = order.dict() file.seek(0) json.dump(database, file, indent=4, default=str)
बेशक, यह वर्ग और भी बहुत कुछ कर सकता है (और शायद करना भी चाहिए), लेकिन इसका उद्देश्य एक आदर्श, बहुक्रियाशील ओआरएम बनना नहीं है। इसे रिपॉजिटरी जिम्मेदारियों के बारे में एक विचार देना चाहिए, जो इस मामले में JSON फ़ाइल में ग्राहक समुच्चय का भंडारण और पुनर्प्राप्ति है। यह भी ध्यान देने योग्य है कि रिपॉजिटरी समुच्चय से जुड़ी संस्थाओं को कैसे संभालती है। चूँकि व्यक्तिगत डेटा और ऑर्डर ग्राहक के जीवनचक्र से मजबूती से जुड़े हुए हैं, इसलिए उन्हें ठीक उसी समय प्रबंधित किया जाना चाहिए जब कुल संसाधित किया जा रहा हो।
विचार करने के लिए एक और मामला यह है कि जब व्यावसायिक तर्क होता है जो कुल मिलाकर या इसकी किसी भी इकाई या मूल्य वस्तुओं में फिट नहीं होता है। यह तर्क हो सकता है जो एकाधिक समुच्चय या डेटा स्टोर की स्थिति पर निर्भर हो। ऐसे मामलों में, डोमेन सेवा नामक संरचना काम आ सकती है। डोमेन सेवा को समुच्चय को प्रबंधित करने में सक्षम होना चाहिए, उदाहरण के लिए, रिपॉजिटरी का उपयोग करके, और फिर यह डोमेन तर्क को संग्रहीत कर सकता है जो समुच्चय से संबंधित नहीं है। उदाहरण के लिए, एक ग्राहक को बहुत अधिक ऑर्डर खोने से बचने के लिए तर्क की आवश्यकता हो सकती है:
import uuid from typing import Protocol from practical_ddd.building_blocks.aggregates import Customer class CustomerRepository(Protocol): """Customer repository interface.""" def get(self, customer_id: uuid.UUID) -> Customer: ... def save(self, customer: Customer) -> None: ... class CustomerService: """Customer service.""" def __init__(self, repository: CustomerRepository) -> None: self.repository = repository def get_customer(self, customer_id: uuid.UUID) -> Customer | None: try: return self.repository.get(customer_id) except IndexError: return None def save_customer(self, customer: Customer) -> None: existing_customer = self.get_customer(customer.id) # If customer is already in the database and has more than 2 orders, # he cannot end up with half of them after a single save. if ( existing_customer is not None and len(existing_customer.orders) > 2 and len(customer.orders) < (len(existing_customer.orders) / 2) ): raise ValueError( "Customer cannot lose more than half of his orders upon single save!" ) self.repository.save(customer)
एग्रीगेट यह सुनिश्चित नहीं कर सकता कि उसकी स्थिति JSON फ़ाइल की स्थिति से किस प्रकार भिन्न है क्योंकि उसे पहली बार में JSON फ़ाइल के बारे में कोई जानकारी नहीं है। इसीलिए तुलना तर्क को डोमेन सेवा में शामिल किया जाना चाहिए। यह ध्यान रखना भी महत्वपूर्ण है कि डोमेन सेवा को रिपॉजिटरी एब्स्ट्रैक्शन के साथ काम करना चाहिए। इससे निर्भरता इंजेक्शन का उपयोग करके ठोस कार्यान्वयन को वैकल्पिक कार्यान्वयन से बदलना आसान हो जाता है।
चूँकि सभी टुकड़े अब कवर हो चुके हैं, अब उन्हें एक कार्यशील कार्यक्रम के रूप में देखा जा सकता है:
import uuid from practical_ddd.building_blocks import aggregates, entities, value_objects from practical_ddd.database.repository import CustomerJSONRepository from practical_ddd.service import CustomerService # Initialize domain service with json repository srv = CustomerService(repository=CustomerJSONRepository("test.json")) # Create a new customer customer = aggregates.Customer( person=entities.Person( first_name="Peter", last_name="Tobias", address=value_objects.Address( country="Germany", city="Berlin", street="Postdamer Platz", house_number="2/3", ), ), ) srv.save_customer(customer) # Add orders to existing customer customer = srv.get_customer(uuid.UUID("a32dd73a-6c1b-4581-b1d3-2a1247320938")) assert customer is not None customer.add_order(entities.Order(description="Order 1", value=10)) customer.add_order(entities.Order(description="Order 2", value=210)) customer.add_order(entities.Order(description="Order 3", value=3210)) srv.save_customer(customer) # Remove orders from existing customer # If there are only 3 orders, it's gonna fail customer = srv.get_customer(uuid.UUID("a32dd73a-6c1b-4581-b1d3-2a1247320938")) assert customer is not None customer.remove_order(uuid.UUID("0f3c0a7f-67fd-4309-8ca2-d007ac003b69")) customer.remove_order(uuid.UUID("a4fd7648-4ea3-414a-a344-56082e00d2f9")) srv.save_customer(customer)
हर चीज़ की अपनी ज़िम्मेदारियाँ और सीमाएँ होती हैं। एग्रीगेट अपनी संस्थाओं और मूल्य वस्तुओं के प्रबंधन के साथ-साथ अपनी बाधाओं को लागू करने का प्रभारी है। डोमेन सेवा JSON फ़ाइल में डेटा को बनाए रखने और अतिरिक्त डोमेन सीमाओं को लागू करने के लिए इंजेक्टेड JSON रिपॉजिटरी का उपयोग करती है। अंत में, निर्दिष्ट डोमेन के भीतर प्रत्येक घटक का एक अलग कार्य और महत्व होता है।
बिना किसी संदेह के, डोमेन-संचालित डिज़ाइन को समझना एक जटिल विचार है। यह सॉफ़्टवेयर टीमों को व्यावसायिक डोमेन पर ज़ोर देकर सबसे चुनौतीपूर्ण व्यावसायिक समस्याओं से निपटने में मदद करने के लिए अभ्यास, पैटर्न और उपकरण प्रदान करता है। हालाँकि, DDD बिल्डिंग ब्लॉक्स के एक सेट से कहीं अधिक है। यह एक मानसिकता है जिसके लिए तकनीकी और व्यावसायिक हितधारकों के बीच सहयोग और संचार की आवश्यकता होती है। सर्वव्यापी भाषा के माध्यम से व्यक्त डोमेन की साझा समझ, डीडीडी परियोजना की सफलता के लिए महत्वपूर्ण है। जब अच्छी तरह से किया जाता है, तो DDD ऐसे सॉफ़्टवेयर को जन्म दे सकता है जो व्यवसाय की ज़रूरतों के साथ बेहतर ढंग से संरेखित होता है और जटिल समस्याओं को हल करने में अधिक प्रभावी होता है।
इस लेख का उद्देश्य कभी भी "डीडीडी: फ्रॉम ज़ीरो टू हीरो" जैसा कुछ नहीं था, बल्कि इसका उद्देश्य डीडीडी ब्रह्मांड का परिचय देना था। मैं डोमेन-संचालित डिज़ाइन की सबसे महत्वपूर्ण अवधारणाओं को बहुत ही सरल और व्यावहारिक तरीके से प्रदर्शित करना चाहता था। मेरा मानना है कि डोमेन-संचालित डिज़ाइन सीखना प्रोग्रामिंग विशेषज्ञता को बढ़ावा देने का एक उत्कृष्ट तरीका है। हालाँकि, आप इसके बारे में अक्सर नहीं सुनते हैं - कम से कम "11 पागल जावास्क्रिप्ट टिप्स और ट्रिक्स - एक थ्रेड 🧵" जितना नहीं।
किसी भी मामले में, यदि आपको इनमें से कुछ भी दिलचस्प लगता है, तो आप उन पुस्तकों और लेखों के स्रोत अनुभाग को देख सकते हैं जिन्होंने मुझे सबसे पहले यह लेख लिखने के लिए प्रेरित किया। कुछ अवधारणाएँ हैं जिन्हें मैंने कवर नहीं किया क्योंकि मुझे लगा कि वे इस परिचय के दायरे से बाहर हैं, लेकिन वे जांच के लायक हैं:
आप निस्संदेह उन्हें नीचे सूचीबद्ध स्रोतों में पाएंगे।
लेख में प्रयुक्त कोड उदाहरण यहां पाए जा सकते हैं: लिंक ।
व्लाद खोनोनोव द्वारा डोमेन-संचालित डिज़ाइन सीखना । एक अद्भुत पुस्तक जो मेरे लिए प्रेरणा का प्रमुख स्रोत रही। इस आलेख में चर्चा की गई सभी अवधारणाओं को अधिक गहराई से समझाता है।
हैरी पर्सीवल और बॉब ग्रेगरी द्वारा पायथन में आर्किटेक्चर पैटर्न । मैंने यह किताब लगभग दो साल पहले पढ़ी थी और एक डेवलपर के रूप में इसका मुझ पर महत्वपूर्ण प्रभाव पड़ा। इस लेख को लिखते समय मैं इस पर दोबारा गया और इससे मुझे एक बार फिर मदद मिली।
प्रेज़ेमिस्लाव गोरेकी द्वारा पायथन में डीडीडी । लेख लिखने के अंत में मुझे यह ब्लॉग मिला, लेकिन इसने मेरी रुचि बढ़ा दी क्योंकि यह अत्यधिक पेशेवर है। मज़ेदार तथ्य: मैंने प्रेज़ेमिस्लाव की ही कंपनी में काम किया था और मैं इससे पूरी तरह अनजान था।
यहाँ भी प्रकाशित किया गया है.