परिचय: आपका कोड व्यवसाय की भाषा क्यों बोलना चाहिए
\n\nकल्पना करें: आप एक जटिल ट्रेडिंग रोबोट के लिए कॉन्फ़िगरेशन लिख रहे हैं। सैकड़ों if-else लाइनों और मैजिक नंबरों के बजाय, आप बस लिखते हैं: BuyWhen(Price.CrossesAbove(MA(50)))। आपका मैनेजर, जो C# नहीं जानता, इस कोड को देखकर लॉजिक समझ जाता है। यह जादू नहीं है — यह C# में DSL है।
डोमेन-विशिष्ट भाषाएं (Domain-Specific Languages, DSL) सिर्फ एक ट्रेंड नहीं हैं। यह एक ऐसा टूल है जो तकनीकी विवरणों की अराजकता को सुरुचिपूर्ण, पढ़ने योग्य कोड में बदल देता है। इस लेख में हम सिर्फ थ्योरी नहीं करेंगे — हम स्क्रैच से एक रियल DSL C# में बनाएंगे, सामान्य गलतियों को समझेंगे और दिखाएंगे कि इस प्रैक्टिस को आज ही अपने प्रोजेक्ट में कैसे लागू करें।
\n\nDSL क्या है और डेवलपर को इसकी आवश्यकता क्यों है?
\n\nDSL एक प्रोग्रामिंग भाषा है जो किसी विशिष्ट समस्या को हल करने के लिए बनाई गई है। सामान्य भाषा (C#, Java, Python) के विपरीत, DSL अपने डोमेन की भाषा बोलता है। C# में दो मुख्य दृष्टिकोण हैं:
\n\n- \n
- आंतरिक DSL — Fluent API और Expression Trees के माध्यम से C# के ऊपर बनाए जाते हैं। आप अपने मूल वातावरण में रहते हैं। \n
- बाहरी DSL — पार्सिंग (अक्सर Roslyn के माध्यम से) की आवश्यकता होती है और C# कोड जनरेट करते हैं। \n
DSL के वास्तविक लाभ: संज्ञानात्मक भार कम करना, बग्स की संख्या घटाना (बिजनेस लॉजिक तकनीकी कार्यान्वयन से अलग होता है) और नए डेवलपर्स के ऑनबोर्डिंग में तेजी लाना।
\n\nC# में आंतरिक DSL बनाना: चरण-दर-चरण गाइड
\n\nचरण 1: डोमेन और सिंटैक्स परिभाषित करें
\n\nमान लीजिए, हम डेटा वैलिडेशन के लिए DSL बना रहे हैं। इसके बजाय:
\n\nif (user.Age < 18 || user.Name == null || user.Email == null)\n throw new ValidationException();\n\nहम ऐसा लिखना चाहते हैं:
\n\nValidate.User(user)\n .MustBeAdult()\n .MustHaveName()\n .MustHaveEmail();\n\nचरण 2: Fluent Interface — C# में DSL का आधार
\n\nमुख्य तत्व प्रत्येक मेथड से this लौटाना है। एक वैलिडेटर क्लास बनाएं:
public class UserValidator\n{\n private readonly User _user;\n private readonly List<string> _errors = new();\n\n public UserValidator(User user) => _user = user;\n\n public UserValidator MustBeAdult()\n {\n if (_user.Age < 18)\n _errors.Add("उपयोगकर्ता नाबालिग है");\n return this;\n }\n\n public UserValidator MustHaveName()\n {\n if (string.IsNullOrWhiteSpace(_user.Name))\n _errors.Add("नाम आवश्यक है");\n return this;\n }\n\n public void Validate()\n {\n if (_errors.Any())\n throw new ValidationException(string.Join("; ", _errors));\n }\n}\n\nऔर सुरुचिपूर्ण प्रवेश के लिए एक फैक्ट्री मेथड:
\n\npublic static class Validate\n{\n public static UserValidator User(User user) => new UserValidator(user);\n}\n\nचरण 3: सशर्त निर्माण और संदर्भ जोड़ें
\n\nएक वास्तविक DSL C# में ब्रांचिंग का समर्थन करना चाहिए। When लागू करें:
public UserValidator When(bool condition, Func<UserValidator, UserValidator> validatorFunc)\n{\n if (condition)\n return validatorFunc(this);\n return this;\n}\n\nउपयोग:
\n\nValidate.User(user)\n .MustHaveName()\n .When(user.Age > 18, v => v.MustBeAdult());\n\nउन्नत स्तर: C# में Expression Trees के साथ DSL
\n\nडायनामिक क्वेरी (ORM, नियम) बनाने के लिए Expression<Func<T, bool>> का उपयोग करें। एक रूल बिल्डर बनाएं:
public class RuleBuilder<T>\n{\n private Expression<Func<T, bool>> _expression;\n\n public RuleBuilder(Expression<Func<T, bool>> expression) => _expression = expression;\n\n public RuleBuilder<T> And(Expression<Func<T, bool>> other)\n {\n var andExpression = Ex