XML एक सस्ता DSL है
(unplannedobsolescence.com)- अमेरिकी IRS ने नया Tax Withholding Estimator(TWE) ओपन सोर्स के रूप में जारी किया है, और इसकी मुख्य डिज़ाइन सिद्धांत अमेरिकी टैक्स क़ानून को XML-आधारित declarative specification के रूप में मॉडल करना है
- TWE का टैक्स कैलकुलेशन लॉजिक Fact Graph नामक लॉजिक इंजन पर बना है, और हर टैक्स आइटम को XML में परिभाषित "Fact" के dependency graph के रूप में व्यक्त किया गया है
- JavaScript जैसी imperative language में टैक्स लॉजिक लागू करने पर execution order management, intermediate values के खो जाने, और implementation details के उजागर होने जैसी समस्याएँ आती हैं, इसलिए declarative approach आवश्यक है
- JSON arbitrary nested expressions को संभालने के लिए उपयुक्त नहीं है, जबकि XML में टैग खुद object type को दर्शाते हैं, इसलिए DSL बनाने के लिए यह कहीं अधिक अनुकूल है
- XML के साथ XPath जैसी mature tool ecosystem का मुफ़्त उपयोग किया जा सकता है, इसलिए cross-platform declarative specifications के लिए यह सबसे cost-effective विकल्प है
Fact Graph: XML में व्यक्त अमेरिकी टैक्स क़ानून
- IRS द्वारा जारी Tax Withholding Estimator(TWE) एक ऐसा टूल है जिसमें करदाता अपनी आय और deductions दर्ज करके टैक्स और withholding राशि का अनुमान लगा सकते हैं
- यह प्रोजेक्ट open source है, और आम लोगों के योगदान भी स्वीकार करता है
- TWE दो XML configurations से बनने वाली एक static site है, जिनमें पहला अमेरिकी टैक्स क़ानून को व्यक्त करने वाला Fact Dictionary है
- Fact Graph मूल रूप से IRS Direct File प्रोजेक्ट के लिए बनाया गया लॉजिक इंजन है, जो करदाता की टैक्स देनदारी और withholding को Fact Dictionary में परिभाषित facts के आधार पर गणना करता है
- हर fact XML में परिभाषित होता है; उदाहरण के लिए
/totalOwedको/totalTaxमें से/totalPaymentsघटाने वाले derived fact के रूप में व्यक्त किया गया है- "कुल देय राशि(total owed)" आय पर कुल टैक्स(total tax) और पहले से चुकाई गई राशि(total payments) के अंतर के बराबर है
- Refundable credits ऐसे tax credits हैं जो टैक्स बैलेंस को नकारात्मक बना सकते हैं; इनमें Earned Income Credit, Child Tax Credit, American Opportunity Credit आदि को
<Add>से जोड़ा जाता है - Non-refundable credits टैक्स देनदारी को केवल 0 तक ही घटा सकते हैं, और
<GreaterOf>operator के ज़रिए 0 और (tentative tax - non-refundable credits) में से बड़ा मान चुना जाता है - User input values के लिए
<Derived>की जगह<Writable>टैग का उपयोग होता है, और<Dollar/>,<Boolean/>आदि से value type निर्दिष्ट किया जाता है - Facts एक-दूसरे पर निर्भर रहते हैं और अंतिम टैक्स संख्या निकालने वाली graph structure बनाते हैं
टैक्स लॉजिक के लिए declarative specification क्यों ज़रूरी है
- वही गणना JavaScript में
const totalOwed = totalTax - totalPaymentsकी तरह संक्षिप्त दिख सकती है, लेकिन यह imperative शैली है, जिसमें sequential execution के बाद intermediate steps खो जाते हैं - Dependency संबंध गहरे होने पर execution order की समस्या आती है:
getInput()जैसी user input function आगे की सारी गणना रोक सकती है, और spouse की मौजूदगी जैसी शर्तों के आधार पर पूछे जाने वाले सवाल भी बदलने चाहिए - Social Security आय जोड़ने वाले लॉजिक में JavaScript के
map/reduceजैसी implementation details सामने आ जाती हैं, जबकि XML का<CollectionSum>सीधे टैक्स गणित की अवधारणा को व्यक्त करता है<Dependency path="/socialSecuritySources/*/totalFederalTaxesPaid"/>से collection के भीतर के आइटम जोड़े जाते हैं
- Fact Dictionary declarative शैली अपनाती है: इसमें गणना के ठोस execution steps या order नहीं लिखे जाते, केवल named calculations और dependency relations लिखे जाते हैं, और इंजन खुद execution तरीका तय करता है
- Declarative tax model का सबसे महत्वपूर्ण लाभ auditability और introspection है: आप प्रोग्राम से पूछ सकते हैं, "यह संख्या कैसे निकली?"
- Imperative प्रोग्रामों में intermediate values पहले ही हट चुके होते हैं, इसलिए उन्हें केवल logs या debugger से ही देखा जा सकता है; अमेरिकी टैक्स क़ानून जैसे मामलों में, जहाँ सैकड़ों intermediate calculations होती हैं, यह scalable नहीं है
- Fact Graph के मूल लेखक Chris Given के अनुसार, Fact Graph "यह साबित करने का साधन" है कि जिन बातों के बारे में पूछा नहीं गया, उन्होंने टैक्स रिटर्न के परिणाम को नहीं बदला, और कि पात्र व्यक्ति को सभी उपलब्ध टैक्स लाभ मिल रहे हैं
- TurboTax बनाने वाली Intuit भी इसी निष्कर्ष पर पहुँची थी और उसने 2020 में "Tax Knowledge Graph" श्वेतपत्र प्रकाशित किया, लेकिन उसका implementation सार्वजनिक नहीं है
- IRS Fact Graph open source और public domain में है, इसलिए कोई भी इसका अध्ययन, साझा या विस्तार कर सकता है
XML, JSON की तुलना में DSL के लिए कहीं अधिक उपयुक्त क्यों है
- टैक्स क़ानून के declarative data representation format के रूप में JSON आज़माने पर arbitrary nested expressions को संभालना बहुत असुविधाजनक हो जाता है
- JSON की एकमात्र composite data structure object है, इसलिए हर child object को
"type","kind"आदि के ज़रिए अपना प्रकार खुद बताना पड़ता है - XML में टैग का नाम ही object type को दर्शाता है, इसलिए अलग से घोषणा की ज़रूरत नहीं होती
- JSON की एकमात्र composite data structure object है, इसलिए हर child object को
- उसी
/tentativeTaxNetNonRefundableCreditsfact का JSON representation, XML की तुलना में, उल्टा और लंबा व अधिक जटिल हो जाता है - XML में comments का समर्थन है, whitespace/line break handling भी उचित है, इसलिए JSON में आम तौर पर मानी जाने वाली असुविधाएँ यहाँ नहीं हैं
- Attributes और named child elements भाषा डिज़ाइन में किस बात पर ज़ोर देना है, यह चुनने की अभिव्यक्तिक क्षमता देते हैं
- "Dollar" और "Integer" जैसे custom data types परिभाषित किए जा सकते हैं
- लंबे explanatory text को संभालते समय XML, JSON की तुलना में, पढ़ने और manually edit करने में कहीं अधिक आरामदायक है
XML की सार्वभौमिकता और tool ecosystem
- S-expression, Prolog, KDL जैसी वैकल्पिक syntaxes XML से अधिक पठनीय हो सकती हैं, लेकिन XML अपनाने पर parser और general-purpose tool ecosystem मुफ़्त में मिल जाता है
- S-expression Lisp में, Prolog terms Prolog में अच्छे से काम करते हैं, लेकिन XML को किसी भी फ़ॉर्मेट में बदला जा सकता है
- Prolog में XML को Prolog terms में बदलना सिर्फ एक predicate से संभव है
- Hacker News उपयोगकर्ता ok123456 का "क्या Prolog/Datalog का उपयोग नहीं किया जा सकता?" सवाल भी उल्लेखित है; यह संभव है, लेकिन सार्वभौमिकता के मामले में XML आगे है
- Chris Given ने YAML के बारे में कहा कि "अमेरिकी टैक्स क़ानून के लॉजिक को YAML में व्यक्त करने की कोशिश कभी मत करना"
- XPath के उपयोग का एक वास्तविक उदाहरण: shell command की एक पंक्ति से fact paths को fuzzy search करना और चुने गए path की definition तुरंत देख लेने वाला script
cat facts.xml | xpath -q -e '//Fact/@path' | grep -o '/[^"]*' | fzfसे fact search- Dependency chain को उल्टी दिशा में ट्रेस करके यह देखना कि कौन-सा fact उस fact पर निर्भर है, यह सुविधा भी जोड़ी गई
- लगभग 60 लाइनों के bash script से यह लगभग रोज़ इस्तेमाल होने वाले debugging tool में बदल गया
- टीम के सदस्यों ने भी इसी तरह के तेज़ debugging tools अपने-अपने तरीके से बनाए, और सभी ने XML को मामूली स्तर पर parse करके Fact Graph की Scala implementation को छुए बिना अपनी पसंद की भाषा में काम किया
- मुख्य सीख: general-purpose data representation बहुत मूल्यवान है, और इस श्रेणी में केवल JSON और XML ही आते हैं
- ज़्यादातर मामलों में JSON चुनना चाहिए, लेकिन अगर DSL चाहिए तो XML सबसे सस्ता विकल्प है, और उसकी cost-efficiency की वजह से टीम अपना innovation budget दूसरी जगह खर्च कर सकती है
अतिरिक्त बातें
- यदि schema design अच्छा हो, तो non-programmer लोग भी XML पढ़ सकते हैं, हालांकि वैकल्पिक view अलग से बनाना बेहतर रहेगा
- हाल में XML के प्रति रुचि फिर बढ़ती दिख रही है: Jake Low का XML documents को flat line-oriented representation में बदलने वाला टूल
grex, और Martijn Faassen का Rust में बना आधुनिक XPath/XSLT engine Xee आदि - TWE के facts withholding estimation के लिए हैं, इसलिए इन्हें सीधे टैक्स फाइलिंग में उपयोग नहीं करना चाहिए
1 टिप्पणियां
Hacker News की राय
XML को कई भाषाओं में सही तरह से parse करना महंगा फ़ॉर्मैट है
व्यवहार में, standard के क़रीब implementation के लिए libxml2, expat, Xerces जैसे तीन open source implementations पर निर्भर होना पड़ता है
SGML family की भाषाओं का मूल यह है कि वे “list” को first-class object और nesting को second-class object की तरह मानती हैं, और tag name तथा attribute इन दो axes के ज़रिए metadata जोड़ा जा सकता है
XML एक DSL के रूप में अब भी उपयोगी है, लेकिन अगर सच में XML इस्तेमाल करना है, तो “cheap” शब्द छोड़ना होगा
और declarative DSL को imperative expression जैसा दिखने वाला भी बनाया जा सकता है। उदाहरण के लिए
totalOwed = totalTax - totalPaymentsजैसी expression का वही अर्थ हो सकता है जो XML DSL का होता हैMETAFONT जैसी भाषाएँ यह approach दिखाती हैं (उदाहरण लिंक)
XML को बार-बार वही गलती दोहराते हुए अक्सर देखता हूँ
लोग अक्सर यह सरल सच भूल जाते हैं कि फ़ॉर्मैट में जितनी ज़्यादा features डालोगे, parsing उतनी कठिन होगी
JSON के लोकप्रिय होने की वजह यह है कि उसमें features कम हैं, इसलिए parse करना आसान है
इसके उलट XML में attributes, namespaces, CDATA, DTDs वगैरह बहुत कुछ ठूँस दिया गया
SQLite को interchange format की तरह इस्तेमाल करने की चर्चा भी हुई थी, लेकिन उसमें भी XML जैसी complexity आ जाने का ख़तरा है
CSV आज भी सिर्फ़ इसकी simplicity की वजह से पसंद किया जाता है
आजकल JSON में comments या type information ज़बरदस्ती डालने की कोशिशें XML की ख़राब attributes वाली सोच की पुनरावृत्ति हैं
लेखक होने के नाते, मैं सहमत हूँ
declarative specification को गणितीय expression जैसा दिखाना संभव है, लेकिन आख़िरकार वह नई भाषा बनाने का काम ही है
फिर parser को हर environment में port करने की समस्या आती है
operator precedence या switch expression जैसी syntactic decisions भी ख़ुद लेनी पड़ती हैं, और अंत में complexity तेज़ी से बढ़ती है
इसलिए मैंने “cheap” शब्द इस्तेमाल किया — cost बचाने का मतलब है ऐसा फ़ॉर्मैट चुनना जिसके parser और tooling पहले से हर environment में मौजूद हों
expressiveness कम हो सकती है, लेकिन छोटी टीमों के लिए यह समझदारी भरा विकल्प है
enterprise Java में XML बहुत इस्तेमाल किया है, और यह memory और CPU bottleneck का बड़ा कारण था
XML बिल्कुल भी cheap नहीं है
SGML का सार element के regular-expression-based content model में है
यह सिर्फ़ list structure नहीं है, बल्कि BNF की तरह grammar production rules भी define कर सकता है
“XML proper” की जगह “XML lookalike” कहना कुछ ज़्यादा ही नुक्ताचीनी लगता है
XML की हर feature न इस्तेमाल करने पर भी वह XML ही रहता है
जैसे cupholder न होने पर school bus को “बस जैसा दिखने वाला” नहीं कहेंगे
मुझे लगता है XML की जगह ऐसी भाषाएँ इस्तेमाल करनी चाहिए जो eDSL को अच्छे से support करती हों
Haskell, OCaml, Scala जैसी भाषाएँ applicative या arrow जैसे concepts से parallel computation को आसानी से व्यक्त कर सकती हैं
JavaScript में भी
.reduce()की जगहsumजैसी abstraction बनाई जा सकती हैXML DSL बनाने पर आख़िरकार parallelization, readability और नई syntax invent करने जैसी समस्याएँ फिर से सुलझानी पड़ती हैं
जटिल domains में Greenspun का 10वाँ नियम सामने आ सकता है
लेकिन Haskell जैसी भाषाओं की समस्या यह है कि उन्हें सीखना कठिन है
30 साल के अनुभव वाला developer भी entry barrier ऊँचा महसूस कर सकता है
Raku भी अच्छा विकल्प है
इसकी शुरुआत Haskell आधारित सोच से हुई थी, और यह built-in Grammar और functional style support करता है, इसलिए DSL लिखने के लिए अनुकूल है
HTML! (मज़ाकिया छोटा जवाब)
Lisp भी संभव है
S-expression देखते ही समझ आ जाता है कि XML कितना verbose और भारी महसूस होता है
JSON structure को और बेहतर डिज़ाइन किया जा सकता है
हर node को एक type key और array value से बनाया जाए तो उसे S-expression की तरह व्यक्त किया जा सकता है
इससे streaming parsing संभव होती है और type पहले ही पता चल जाता है
बड़े datasets में यह उपयोगी है
JSON, XML की तुलना में कहीं ज़्यादा simple है और parsing cost कम है
XML में tag matching, attribute handling जैसी state management जटिल होती है
जबकि JSON में बस
{},[]को match करना होता हैयह simplicity जमा होकर latency कम होने में बदलती है
लेकिन JSON में quotes बहुत ज़्यादा होते हैं, इसलिए वह visual noise जैसा लगता है
निजी तौर पर मुझे Clojure का EDN ज़्यादा साफ़-सुथरा लगता है
ऐसी JSON structure सौंदर्य की दृष्टि से एक पतित रूप जैसी लगती है
अगर data को tags चाहिए, तो उसके लिए उपयुक्त representation का इस्तेमाल करना बेहतर है
The Lost Art of XML लेख मुझे ज़्यादा दिलचस्प लगा
यह दृष्टिकोण प्रभावशाली था कि web development tools का बड़ा हिस्सा browser wars में XML की हार का नतीजा है
लेकिन “XML को इसलिए छोड़ा गया क्योंकि JavaScript जीत गया” यह दावा मानना मुश्किल है
browser मूल रूप से XML को भी support करते थे (AJAX का X, XML ही है)
बस developers XML को पसंद नहीं करते थे
मुझे लगता है XML को overengineering और complexity की वजह से नज़रअंदाज़ किया गया
पुराने XML API दौर को सीधे झेलने वाले के रूप में कहूँ तो, XML सच में तकलीफ़देह था
हर भाषा में encoder/decoder अलग बनाना पड़ता था, और maintenance भी मुश्किल था
JSON बस array और object में map हो जाता है, इसलिए language interoperability बहुत बेहतर है
XML schema design meetings में समय बर्बाद करने वाले दौर को याद करूँ तो, JSON ने API design को वैसे सरल किया जैसे Prettier ने tabs vs spaces बहस ख़त्म कर दी
आख़िरकार यह पैटर्न वही है: शुरुआत “जटिल चीज़ें सीखना नहीं चाहते” से होती है, लेकिन समय के साथ फिर features की ज़रूरत लौट आती है
पोलैंड का tax authority XML से प्यार करता है
लेकिन उनका XML इतना पेचीदा है कि इंसान पढ़ ही न सके
field names
P_19Nजैसे होते हैं, और असली मतलब समझने के लिए schema देखना पड़ता हैयहाँ तक कि क़ानूनी धाराओं के नंबर भी घुसे होते हैं
विडंबना यह है कि VAT law draft करने वाला व्यक्ति अब tax consulting कर रहा है
मैं खुद S-expression आधारित DSL इस्तेमाल कर रहा हूँ
यह WebAssembly आधारित desktop browser runtime में HTML और CSS की भूमिका निभाता है,
और document synchronization की समस्या हल करने वाली एक custom markup language में भी दोबारा इस्तेमाल होता है
इससे जुड़े उदाहरण CanvasUI example code, style file, और documentation tool में देखे जा सकते हैं
उम्मीदवार जब खुद एक छोटी भाषा implement कर लेते थे, तो उनकी प्रतिक्रिया काफ़ी यादगार होती थी
XML, DSL से ज़्यादा एक सामान्य parser/lexer tool है
यह सिर्फ़ text को AST में बदलता है; असली DSL उसके ऊपर define की गई specification होती है
इसमें features बहुत हैं और यह complex है, लेकिन tooling ecosystem समृद्ध है
हाथ से लिखने के बजाय generated text को process करने के लिए यह ज़्यादा उपयुक्त है
XSD schema validation built-in होने की वजह से document की consistency तुरंत जाँची जा सकती है
automation tools का इस्तेमाल किए बिना XML को कठिन कहना वैसा है जैसे disassembler के बिना binary संभालना
लेकिन सिर्फ़ schema validation से content की correctness की गारंटी नहीं मिलती
जैसे type checking से program की correctness की गारंटी नहीं मिलती
XSD उपयोगी है, लेकिन यह complex है और इसमें काफ़ी restrictions हैं
इसलिए XML community के कुछ हिस्से RELAX-NG की ओर चले गए, लेकिन वह पूरी तरह उसका स्थान नहीं ले सका
जिज्ञासा है कि कौन-से कामों में XSD validation वास्तव में अनिवार्य होता है
XML markup language के रूप में ठीक है, और data interchange format के रूप में भी काम का है, लेकिन programming language के रूप में यह भयानक है
JSON भी ऐसा ही है: data interchange के लिए अच्छा, लेकिन भाषा की तरह इस्तेमाल करो तो पछताओगे
Ansible जैसी YAML-आधारित भाषाएँ इसका उदाहरण हैं
दूसरी ओर Lisp का S-expression, JSON जैसी structure रखते हुए भी एक शानदार भाषा के रूप में विकसित हुआ
XML की समस्या XML ख़ुद से ज़्यादा अच्छा XML बनाना कठिन होना है
standard जटिल है, और हर producer का representation अलग होता है, इसलिए consistency कम होती है
JSON में यह standard deviation काफ़ी कम है
financial institutions के XML को देखकर तो निराशा होने लगती है
XML की समस्या आख़िरकार tooling की धीमी गति और अधूरे validators थे
data representation की complexity से ज़्यादा tool quality बड़ा bottleneck थी
असल समस्या “अच्छा XML” से ज़्यादा यह थी कि “बेहद ख़राब XML” बहुत आसानी से बनाया जा सकता था
इसलिए community ने namespaces, validation, transformation, semantic web वगैरह के ज़रिए interoperability हासिल करने की कोशिश की
यह ऐसे माहौल में काम आगे बढ़ाने के लिए किया गया समझौता था जहाँ पूर्ण सहमति संभव नहीं थी