घोषणात्मक दृष्टिकोण और एमडीए वास्तुकला में कई फायदे हैं जो सूचना प्रणाली (आईपी: सीआरएम, डब्ल्यूएमएस, परियोजना प्रबंधन, आदि) के विकास और रखरखाव की लागत को काफी कम कर सकते हैं। यह दृष्टिकोण पहले से ही कई उत्पादों में उपयोग किया जाता है (जैसे कि 1 सी, उदाहरण के लिए)। फिर भी, उनमें घोषणात्मक दृष्टिकोण का उपयोग कार्यों के एक चक्र को संकीर्ण करने के लिए किया जाता है। इस लेख में हम घोषणात्मक दृष्टिकोण के फायदों पर विचार करेंगे, यह दर्शाएंगे कि आप आईपी के निर्माण में इसके आवेदन के दायरे का विस्तार कैसे कर सकते हैं, वास्तविक समस्याओं पर बनाए गए मॉडल की जांच करें और प्रोटोटाइप के संचालन का प्रदर्शन करें।
मेरे स्नातक और मास्टर डिग्री एमडीए से जुड़े थे, और हम इन विचारों को लागू करने के लिए इन पूर्व सहपाठी के साथ एक साल से काम कर रहे हैं। हम किसी भी वाणिज्यिक उत्पाद का प्रतिनिधित्व नहीं करते हैं, हमने जो कुछ भी किया / किया वह हमारे खाली समय में "मेरे घुटनों पर" विकसित किया गया था।
हमारे विचारों को सूचना प्रणालियों के जटिल डिजाइनरों (जैसे 1 सी) और वेब फ्रेमवर्क (Django, RoR) दोनों में लागू किया जा सकता है। आपकी राय और टिप्पणियों को जानना दिलचस्प है। इसके अलावा, हम उन कंपनियों की तलाश कर रहे हैं जो अपने उत्पादों में हमारी सर्वोत्तम प्रथाओं का उपयोग करने के लिए सहयोग में रुचि रखते हैं।
यह सब कैसे शुरू हुआ
यह सब इस तथ्य से शुरू हुआ कि संयोग से कार्य एक वर्कफ़्लो कार्यालय के लिए एक छोटा सा सीआरएम ग्राउंड बनाने के लिए उत्पन्न हुआ। मैंने MS Access से लेकर वेब फ्रेमवर्क (Django, RoR) तक विभिन्न समाधानों को देखना शुरू किया। लेकिन वे सभी बहुत निम्न स्तर के थे। मैं "उपयोगकर्ताओं", "घटनाओं", "कार्यों", आदि के संदर्भ में काम करना चाहता था, और डेटाबेस ऑब्जेक्ट्स नहीं, और इसके अनुरूप दृश्य अभ्यावेदन (कैलेंडर, फिल्टर के साथ सूचियां, आदि) हैं।
हम क्या प्रदान करते हैं
सूचना प्रणालियों के विकास के लिए, सबसे अधिक उपयोग की जाने वाली वस्तु-संबंधपरक संकेतन (OORDBMS, ORM), जिसमें व्यावसायिक नियमों को पीएल में से एक में अनिवार्य रूप से वर्णित किया गया है। हम नई अवधारणाओं के साथ वस्तु-संबंधपरक संकेतन का विस्तार करने का प्रस्ताव करते हैं जो कि व्यावसायिक नियमों को
घोषित करने की अनुमति देगा। हम आवश्यकताओं के औपचारिककरण की भाषा के जितना संभव हो सके "कार्यान्वयन" की भाषा लाने का प्रयास करते हैं।
व्यापार नियमों का घोषणात्मक विवरण क्यों महत्वपूर्ण है?
उच्च-स्तरीय अमूर्त का उपयोग, एक घोषणात्मक दृष्टिकोण के साथ मिलकर, न केवल आईपी के विकास और अनुकूलन को सरल और तेज करने की अनुमति देता है। कोड स्तर से डेटा लेयर तक व्यावसायिक नियमों का स्थानांतरण गुणात्मक रूप से न केवल विकास प्रक्रिया को प्रभावित करता है, बल्कि उत्पाद गुण भी:
- नए संस्करणों के लिए डेटाबेस अपडेट का आंशिक स्वचालन
- ऑन-द-फ्लाई सिस्टम अपडेट
- व्यापार विश्लेषक या अंतिम उपयोगकर्ता द्वारा दृश्य डिजाइनर में प्रणाली का अनुकूलन
- एक सास सेवा के भीतर, विन्यास का एक गतिशील विस्तार सेट का समर्थन किया जा सकता है
अंतिम बिंदु विशेष रूप से ध्यान देने योग्य है - फिलहाल, क्लाउड समाधानों की "कॉन्फ़िगरेशन" बेहद निम्न स्तर पर बनी हुई है - सबसे अच्छी स्थिति में, आप मौजूदा संस्थाओं में अपनी कई विशेषताओं को जोड़ सकते हैं। व्यावसायिक नियमों को डेटा क्षेत्र में स्थानांतरित करना सेवा के विभिन्न उपयोगकर्ताओं को सर्वर के साथ हस्तक्षेप किए बिना, इस डेटा को पूरी तरह से अलग करने की अनुमति देता है। क्लाउड में प्रत्येक उपयोगकर्ता विशेष रूप से उसके लिए अनुकूलित एक सिस्टम कर सकेगा।
कार्यों के उदाहरण
IP के डिज़ाइन में उत्पन्न होने वाले विशिष्ट कार्यों के एक सेट पर विचार करें और जिससे हम एक भाषा का निर्माण करते समय निरस्त हुए:
- प्रदर्शन लागत (मूल्य * मात्रा), मूल्य सहित वैट और मूल्य दर आदि। उपयोगकर्ता इंटरफ़ेस में, इन मानों को स्वचालित रूप से पुनर्गणना किया जाना चाहिए, और सर्वर को प्राप्त डेटा की शुद्धता की जांच करनी चाहिए (या उन्हें स्वयं)
- एक अधिक जटिल उदाहरण: सभी सामानों के लिए कुल खरीद मूल्य, एक दी गई मूल्य सूची में अनुमानित है। समर्थन क्लाइंट और सर्वर दोनों तरफ होना चाहिए।
- कैलेंडर पर विभिन्न स्रोतों द्वारा उत्पन्न घटनाओं को प्रदर्शित करें: उपयोगकर्ता का जन्मदिन, रैली की शुरुआत, मील का पत्थर की समाप्ति आदि।
- सिस्टम के "उपयोगकर्ता" की संरचना को विशेष करें
- उपयोगकर्ताओं की विभिन्न श्रेणियों के लिए मापदंडों का एक अलग सेट, उदाहरण के लिए, ग्राहकों और कंपनी के कर्मचारियों के लिए
- विभिन्न संरचनाओं के साथ वस्तुओं पर कोड का पुन: उपयोग।
उदाहरण के लिए, राइट-ऑफ, माल की चाल और पोस्टिंग में अलग-अलग संरचनाएं हैं लेकिन समान क्रियाएं हैं - व्यावसायिक नियम:
- इसके निष्पादक के लिए प्रत्येक अतिदेय कार्य दिवस के लिए जुर्माना
- उपयोग की अवधि और दैनिक लागत के आधार पर किराए की गणना
- सूचनाएं:
- इसके पूर्ण होने के कार्य के निदेशक
- महंगे उपकरण बंद लिखने पर निर्देशक
- इसकी मंजूरी के बाद मूल्य सूची का निर्धारण
- प्रबंधक केवल उन ग्राहकों को देख सकते हैं जिन्हें उन्हें सौंपा गया है।
नई अवधारणाएँ
उन मूल अवधारणाओं पर विचार करें जिन्हें हम ऑब्जेक्ट-रिलेशनल मॉडल में जोड़ते हैं:
कक्षाएं
कक्षाएं पहले से ही ऑब्जेक्ट-रिलेशनल भाषा में मौजूद हैं, हालांकि, हमने इस अवधारणा को काफी हद तक बदल दिया है (एक ही समय में विस्तारित और छंटनी की गई है), इसे
ईआर संकेतन में "सार" की अवधारणा के करीब लाया गया है:
- कक्षाओं में केवल फ़ील्ड होते हैं (कोई विधियाँ नहीं)
- कक्षाएं वंशानुक्रम की अनुमति देती हैं (और, ऑब्जेक्ट-रिलेशनल एक्सटेंशन SQL में, जब किसी बेस क्लास को क्वेरी करते हैं, तो ऑब्जेक्ट न केवल बेस क्लास के, बल्कि व्युत्पन्न वर्ग के भी वापस आ जाते हैं)
- कक्षाएं अमूर्त हैं (यानी जिनके उदाहरण नहीं हो सकते)। अमूर्त कक्षाओं में सार क्षेत्र हो सकते हैं जिन्हें गैर-सार बच्चे वर्ग में "कार्यान्वित" किया जाना चाहिए: या तो एक कम्प्यूटेशनल अभिव्यक्ति निर्दिष्ट करें या एक साधारण संग्रहीत फ़ील्ड घोषित करें
क्षेत्र प्रकार वंशानुक्रम के दौरान निर्दिष्ट किया जा सकता है (यदि वर्ग फ़ील्ड वर्ग A को संदर्भित करता है, तो वंशानुक्रम के दौरान, आप वर्ग B का संदर्भ निर्दिष्ट कर सकते हैं, यदि B, A का उत्तराधिकारी है) - संदर्भ क्षेत्रों को वर्गीकृत किया गया है
- संदर्भ
- रचनाएँ (यूएमएल में रचनाओं का एक एनालॉग) - एक "कंपोज़ेबल" ऑब्जेक्ट का जीवनकाल "कंपोज़" ऑब्जेक्ट के जीवनकाल तक सीमित होता है
- निष्कर्ष (मैं अच्छी तरह से ज्ञात प्रोग्रामिंग या मॉडलिंग भाषाओं में एनालॉग्स से नहीं मिला हूं) रचना की वृद्धि है - एक अंतर्निहित वस्तु की कल्पना इसके माता-पिता के दायरे से बाहर नहीं की जाती है
"समावेश" के उदाहरण रिश्ते हैं: एक वर्ग और उसके क्षेत्र, एक तालिका और उसकी विशेषताएँ, एक उपयोगकर्ता और उसकी प्रोफ़ाइल। ऑब्जेक्ट "क्लास फील्ड" स्वतंत्र नहीं है, यह अपने मूल वर्ग के बाहर मौजूद नहीं हो सकता है।
संगणक क्षेत्र
एक्सपीथ जैसी भाषा में किसी ऑब्जेक्ट फ़ील्ड के लिए एक मूल्य के रूप
में एक
अभिव्यक्ति सेट करने की क्षमता। कम्प्यूटेशनल एक्सप्रेशन और कम्प्यूटेबल फील्ड्स की अवधारणा का उपयोग हमारी भाषा के अन्य सभी एक्सटेंशन में किया जाता है। यह ध्यान दिया जाना चाहिए कि ओआरएम फ्रेमवर्क या पीएल / एसक्यूएल के उपयोगकर्ता अपनी भाषा की क्षमताओं का उपयोग करते हैं, जब वे / सेट के तरीकों को लागू करते हैं, लेकिन यह बिल्कुल भी नहीं है, क्योंकि कम्प्यूटिंग जानकारी ट्यूरिंग-पूर्ण भाषा में वर्णित है। हम विशेष रूप से गैर-ट्यूरिंग-पूर्ण करने के लिए अभिव्यक्ति की भाषा को सरल बनाते हैं ताकि:
- विभिन्न प्लेटफार्मों (क्लाइंट, सर्वर) पर प्रभावी ढंग से व्याख्या करें जो डेटा तक पहुंचने के एक अलग तरीके का उपयोग करते हैं
- निर्भर वस्तुओं के निर्भर क्षेत्रों को बदलते समय एक अभिव्यक्ति को पुन: कंप्यूटिंग के लिए निर्भरता का स्वचालित रूप से पता लगाएं
इस प्रकार, क्षेत्र की गणना करने की विधि की जानकारी ऑब्जेक्ट की संरचना के विवरण में निहित है, जो इस संरचना को स्वचालित रूप से अनुमति देता है
- सर्वर पर ऑब्जेक्ट को मान्य करें
- उपयोगकर्ता इंटरफ़ेस में कम्प्यूटेड फ़ील्ड को स्वचालित रूप से अपडेट करें
इंटरफेस
इंटरफेस ओओपी में अच्छी तरह से जाना जाता है, लेकिन डेटाबेस का वर्णन करते समय गलत तरीके से भूल जाते हैं। हम निम्नानुसार इंटरफेस शुरू करते हैं:
- एक इंटरफ़ेस एक सार वर्ग है जिसमें सभी फ़ील्ड सार हैं
- इंटरफ़ेस कार्यान्वयन विरासत के समान है
- कक्षाओं के साथ इंटरफेस पूरी तरह से विनिमेय हैं: जहां भी कक्षाएं इस्तेमाल की जा सकती हैं, इंटरफेस का उपयोग किया जा सकता है (संबंधपरक सिद्धांत में अभ्यावेदन के साथ सादृश्य द्वारा)।
यानी आप कर सकते हैं
- इंटरफ़ेस द्वारा चयन करें (चयन का परिणाम सभी ऑब्जेक्ट हैं जो निर्दिष्ट इंटरफ़ेस को लागू करते हैं)
- इंटरफ़ेस के माध्यम से एक वस्तु को संशोधित करें (यदि इंटरफ़ेस फ़ील्ड को वर्ग फ़ील्ड से बाइंडिंग के माध्यम से कार्यान्वित किया जाता है)
- इंटरफेस के लिए ट्रिगर बनाएँ (इस मामले में, ट्रिगर सभी कार्यान्वयन वर्गों के लिए काम करेगा)
- एक वर्ग एक इंटरफ़ेस "प्रदान" कर सकता है। इसके लिए, एक "कनेक्टेड" वर्ग का वर्णन किया जाता है, जो कि इंटरफ़ेस प्रदान करने वाले वर्ग के क्षेत्रों का उपयोग करके निर्दिष्ट इंटरफ़ेस को लागू करता है।
- एक वर्ग एक ही इंटरफ़ेस कई बार प्रदान कर सकता है ("अनुदान" के लिए संदर्भित हैं)
- वंशानुक्रम के विपरीत, "अनुदान" को कक्षा के बाहर वर्णित किया जा सकता है (आप "एडाप्टर" पैटर्न के साथ एक सादृश्य आकर्षित कर सकते हैं)
- एक "जुड़े" वर्ग की संरचना के लिए, किसी भी विरासत के रूप में, खेतों के प्रकारों को निर्दिष्ट करने की अनुमति है
"एक इंटरफ़ेस प्रदान करना" की अवधारणा एक महत्वपूर्ण पुन: उपयोग उपकरण है। यह, साथ ही इंटरफ़ेस के कार्यान्वयन की तुलना संबंधपरक अभ्यावेदन के साथ की जा सकती है। एक "प्रस्तुति" और एक प्रस्तुति के बीच एक महत्वपूर्ण अंतर गणना पद्धति है: चूंकि विभिन्न इकाइयां एक ही इंटरफ़ेस को एक से अधिक बार प्रदान कर सकती हैं, इसलिए एक कैलेंडर (सभी उदाहरणों के लिए, एक कैलेंडर पर सभी घटनाओं को प्रदर्शित करने के लिए "डिलीवरी" की सूची प्राप्त करना बेहद मुश्किल है) ।
भाषा अभिव्यक्ति परीक्षण
विचार करें कि हमारे द्वारा डिज़ाइन किए गए डिज़ाइनों का उपयोग करके उपरोक्त कार्यों को कैसे लागू किया गया है:
मूल्य के उत्पाद के रूप में मूल्य प्रदर्शित करें, वैट सहित मूल्य
यह पूरी तरह से "कम्प्यूटेबल फ़ील्ड्स" की अवधारणा पर पड़ता है, और अभिव्यक्ति का वर्णन करने के लिए भाषा, ज़ाहिर है, हमें योग और उत्पाद का वर्णन करने की अनुमति देता है :)एक अधिक जटिल उदाहरण: सभी सामानों के लिए कुल खरीद मूल्य, एक दी गई मूल्य सूची में अनुमानित है।
फ़ील्ड को "कुल लागत" और फ़ील्ड "वस्तुओं" के साथ ऑब्जेक्ट के रूप में वर्णित किया जाना चाहिए, जिसमें "सामान-मात्रा-मूल्य" वस्तुओं की एक सूची शामिल है।
हम अभिव्यक्ति द्वारा प्रत्येक वस्तु "उत्पाद-मात्रा-मूल्य" में फ़ील्ड "लागत" निर्धारित करते हैं:
- खरीद से मूल्य सूची ले लो
- एक उत्पाद के लिए मूल्य सूची को फ़िल्टर करें जो मुझे मेल खाना चाहिए
- परिणामी सूची से पहला और एकमात्र तत्व लें
- मूल्य क्षेत्र उससे ले लो।
"खरीद" वर्ग में, "कुल लागत" फ़ील्ड में, "परिकलित फ़ील्ड" लागत "द्वारा सभी उत्पाद रिकॉर्ड-मात्रा का योग" अभिव्यक्ति सेट करें।
सिस्टम का कार्य निर्भरता के एक सकर्मक समापन का निर्माण करना है, ताकि प्रविष्टियों में से एक "उत्पाद-मात्रा-मूल्य" में परिवर्तन से कुल लागत की एक कमी हो जाए
कैलेंडर पर विभिन्न स्रोतों से उत्पन्न घटनाओं को प्रदर्शित करें
ऐसा करने के लिए, फ़ील्ड "नाम", "तिथि", "अवधि", "अवधि" के साथ "इवेंट" इंटरफ़ेस दर्ज करें। उपयोगकर्ता इंटरफ़ेस कोड हमेशा ईवेंट इंटरफ़ेस का उपयोग घटनाओं को खोजने और प्रदर्शित करने के लिए करता है।
उपयोगकर्ताओं के जन्मदिन को "खोजने" के लिए कैलेंडर के लिए, उपयोगकर्ता द्वारा "इवेंट" इंटरफ़ेस के "प्रावधान" का वर्णन करना आवश्यक है:
- "नाम" - अभिव्यक्ति "जन्मदिन $ नाम $ अंतिम नाम",
- "तिथि" - user.birthday
- "अवधि" - निरंतर अभिव्यक्ति "1 वर्ष"
- "अवधि" निरंतर अभिव्यक्ति "पूरे दिन" है
सिस्टम के "उपयोगकर्ता" की संरचना को विशेष करें
ऐसा करने के लिए, हम इंटरफ़ेस के साथ "उपयोगकर्ता" की अवधारणा का वर्णन करते हैं (उदाहरण के लिए, फ़ील्ड "लॉगिन" और "पासवर्ड")। जोड़तोड़ के मामले में कक्षाएं कक्षाओं से अप्रभेद्य हैं, और एक इंटरफ़ेस एक वर्ग द्वारा एक मनमाना संरचना के साथ लागू किया जा सकता हैउपयोगकर्ताओं की विभिन्न श्रेणियों के लिए मापदंडों का एक अलग सेट, उदाहरण के लिए, ग्राहकों और कंपनी के कर्मचारियों के लिए
चूंकि विभिन्न वर्ग एक ही इंटरफ़ेस को लागू कर सकते हैं, इसलिए किसी भी उपयोगकर्ता वर्ग की संख्या हो सकती है। इसके लिए एकमात्र बात यह है कि प्राधिकरण कोड इंटरफ़ेस के माध्यम से उपयोगकर्ताओं के साथ सभी काम करता है।विभिन्न संरचनाओं के साथ वस्तुओं पर कोड का पुन: उपयोग।
स्पष्ट रूप से इंटरफेस या अमूर्त वर्गों द्वारा लागू किया गया।
यह ध्यान रखना महत्वपूर्ण है कि कार्यान्वयन के दौरान फ़ील्ड के प्रकारों को स्पष्ट किया जा सकता है: यदि कोई इंटरफ़ेस "आंदोलन" है और इसमें एक सूची फ़ील्ड है जैसे "इन्वेंट्री रिकॉर्ड" फ़ील्ड "इन्वेंट्री", "मात्रा" के साथ, तो इकाई "खरीद" जब इंटरफ़ेस लागू हो सकता है एक सूची फ़ील्ड "इन्वेंट्री", "मात्रा", "खरीद मूल्य" के साथ "खरीद रिकॉर्ड" प्रकार के साथ एक क्षेत्र है, और यह हस्तांतरण के प्रसंस्करण कोड को प्रभावित नहीं करेगा।
व्यावसायिक प्रक्रियाओं और एक्सेस अधिकारों के प्रबंधन से संबंधित शेष वस्तुओं को उन अवधारणाओं की आवश्यकता होती है जिन्हें हम अगले लेख में विचार करेंगे, यदि यह विषय आपके लिए दिलचस्प है।
हमने क्या लागू किया है
हम "पहले-खेलने योग्य" के स्तर पर पहुंच गए और अपने दोस्त की सफाई कंपनी के लिए एक कॉन्फ़िगरेशन बनाया, जो इन्वेंट्री अकाउंटिंग को लागू करता है। आप इसे यहां देख सकते हैं।
Demo.meta4.info (लॉगिन / पासवर्ड रूट / रूट)। प्रपत्रों, संवादों, और कार्य के तर्क का संपूर्ण रूप निम्न कॉन्फ़िगरेशन द्वारा निर्धारित किया जाता है (हालांकि, इसमें एक्सेस राइट्स प्रतिबंधों का विवरण शामिल नहीं है):
XML कॉन्फ़िगरेशन<projectDescription name="CleaningWMS"> <interface name="Ware class"> <attribute name="in stock" type="float"/> <attribute name="local count" type="float"/> </interface> <interface name="Wares"> <attribute name="amount" type="float"/> <relation name="clazz" to="WareClass" kind="reference"/> </interface> <interface name="Warehouse"> <relation name="entries" to="Wares" kind="embedding" list="true"/> </interface> <interface name="Transfer"> <attribute name="approved" type="boolean"/> <relation name="from" to="Warehouse" kind="reference"/> <relation name="to" to="Warehouse" kind="reference"/> <relation name="entries" to="Wares" kind="embedding" list="true"/> </interface> <trigger class="com.meta4.cms.warehouse.TransferTrigger" on="Transfer.approved"/> <trigger class="com.meta4.cms.warehouse.WareClassTrigger" on="Transfer.approved"/> <trigger class="com.meta4.cms.warehouse.RequestTrigger" on="."/> <trigger class="com.meta4.cms.warehouse.RequestTrigger" on="."/> <enum name=""> <value name=""/> <value name=""/> <value name=""/> </enum> <enum name=" "> <value name=""/> <value name=""/> <value name=""/> </enum> <enum name=" "> <value name=" "/> <value name=" "/> <value name=""/> <value name=""/> <value name=""/> <value name=""/> </enum> <enum name=""> <value name=""/> <value name=""/> </enum> <enum name=""> <value name=""/> <value name=".."/> <value name=""/> <value name=""/> </enum> <enum name=""> <value name=""/> <value name=""/> <value name=" "/> <value name=" "/> <value name=" "/> <value name=""/> </enum> <entity name="" parent="BaseUser"> <attribute name="__label" type="string" template="$_" specialize="__label"/> <attribute name=" " optional="false" type="string" specialize="login"/> <attribute name="" type=""/> <attribute name="" type="password" specialize="password"/> <attribute name="" type="" list="true" expressionClass="com.meta4.cms.warehouse.DepartmentExpression"/> <presentation tableColumns="_, "> <l10n> = = </l10n> <table> <row> <subordinate name="_"/> <subordinate name=""/> </row> <row> <subordinate name=""/> </row> </table> </presentation> </entity> <entity name="" parent="Warehouse"> <attribute name="" optional="false" type="string" specialize="__label"/> <attribute name="" type="address"/> <relation name="" kind="embedding" list="true" to="" specialize="Warehouse.entries" readonly="true"/> <presentation> <l10n> = = </l10n> </presentation> </entity> <entity name="" parent="WareClass"> <attribute name="" type="" optional="false"/> <attribute name="" type="string" optional="false" specialize="__label" filterable="true"/> <attribute name="" type="" list="true" optional="false"/> <attribute name=" " type="integer" optional="false"/> <attribute pname=" , " name=" " type="float"/> <attribute name=" " type="float" optional="false" specialize="WareClass.in_stock" default="0" readonly="true"/> <attribute name=" " type="float" optional="false" specialize="WareClass.local_count" default="0" readonly="true"/> <attribute name="" type="integer" optional="false"/> <attribute name=" " type="integer"/> <attribute name=" " type="integer" value="it. / it._"/> <attribute name=" " type="integer"/> <attribute name=" " type="integer" value="it. / it._"/> <presentation tableColumns=", , , _, _, , __, __"> <l10n> = </l10n> <table> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> </row> <row> <subordinate name="_"/> <subordinate name="_" label=" , "/> </row> <row> <subordinate name=""/> </row> <row> <subordinate name="_"/> <subordinate name="__"/> </row> <row> <subordinate name="_"/> <subordinate name="__"/> </row> </table> <query title=" " ofType=""> <parameter subordinate="entries.clazz" operator="in" value="it"/> </query> </presentation> </entity> <entity name="" parent="Wares"> <attribute name="" type="float" specialize="Wares.amount" optional="false"/> <relation name="" kind="reference" to="" specialize="Wares.clazz" optional="false"/> </entity> <entity name="" parent="Warehouse"> <attribute name="" type="string" optional="false" specialize="__label"/> <attribute name="" type="address"/> <relation name="" kind="embedding" list="true" to="" specialize="Warehouse.entries" readonly="true"/> <presentation> <l10n> = </l10n> </presentation> </entity> <action name="it.approved ? '': ''" class="com.meta4.cms.warehouse.ApproveActionLogic" accept="" logMessage=" "/> <entity name="" parent="Transfer" abstract="true"> <attribute name="" type="" expressionClass="com.meta4.cms.warehouse.OperationTypeExpression"/> <attribute name="" type="boolean" specialize="Transfer.approved" readonly="true"/> <attribute name=" " type="date" readonly="true"/> <relation name="" kind="reference" to="" optional="false"/> <relation name="" kind="reference" to="Warehouse" specialize="Transfer.from"/> <relation name="" kind="reference" to="Warehouse" specialize="Transfer.to"/> </entity> <entity name="" parent=""> <attribute name="" type="boolean" specialize="."/> <relation name="" kind="reference" to="Warehouse" specialize="." optional="false"/> <relation name="" kind="reference" to="Warehouse" specialize="." optional="false"/> <relation name="" list="true" kind="embedding" to="" specialize="Transfer.entries"/> <relation pname="№ " name="" kind="reference" to="" oppositeTo="." readonly="true"/> <relation name="" kind="embedding" list="true"> <to> <entity name=""> <presentation> <l10n>=</l10n> </presentation> <attribute name="" type="integer" default="0"/> <attribute name=" " type="integer" default="7"/> <attribute name=" " type="integer" default="0"/> <attribute name="" type="integer" value="it. * it.__ + it._"/> <relation name="" kind="reference" to="" optional="false"/> </entity> </to> </relation> <presentation tableColumns=", _, , , , "> <l10n>=</l10n> <table> <row> <subordinate name=""/> <subordinate name=""/> </row> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name=""/> </row> </table> <single subordinate=""/> <single subordinate=""/> </presentation> </entity> <entity name="" parent=""> <attribute name="" type="boolean" specialize="."/> <attribute name="" type="string" optional="false"/> <relation name="" pname="№ " kind="reference" to="" oppositeTo="." readonly="true"/> <relation name="" list="true" kind="embedding" to="" specialize="Transfer.entries"/> <relation name="" kind="reference" to="Warehouse" specialize="." optional="false"/> <presentation tableColumns=", _, , , , "> <l10n>=</l10n> <table> <row> <subordinate name=""/> <subordinate name=""/> </row> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name=""/> </row> </table> <single subordinate=""/> </presentation> </entity> <entity name="" parent=""> <attribute name=" " type="date" optional="false" default="now"/> <attribute name=" " type="date"/> <attribute name="" type="string"/> <attribute name=" " type="float" value="sum(._)"/> <relation name="" kind="reference" to="" specialize="." optional="false"/> <relation name="" list="true" kind="embedding" specialize="Transfer.entries"> <to> <entity name="" parent=""> <relation name="" kind="reference" to="" specialize="Wares.clazz" optional="false"/> <attribute name="" type="float"/> <attribute name="" type="float" specialize="Wares.amount" optional="false" default="1"/> <attribute name=" " type="float" value="it. * it."/> </entity> </to> </relation> <presentation tableColumns=", _, , _, _, _"> <l10n> = = </l10n> <table> <row> <subordinate name="_"/> <subordinate name=""/> </row> <row> <subordinate name="_"/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name=""/> </row> <row> <subordinate name="_"/> </row> </table> <single subordinate=""/> </presentation> </entity> <entity name=""> <attribute name=" " type="datetime"/> <attribute name="" type="" optional="false" default=""/> <attribute name="__label" type="string" template="$_" specialize="__label"/> <attribute name=" " type="string" optional="false"/> <attribute name="" type="string"/> <attribute name="" type="string"/> <attribute name="" type="" optional="false" default=" "/> <attribute name=" " type="date" default="now"/> <relation name="" kind="reference" to="" optional="false"/> <relation name="" kind="reference" to=""/> <relation name="" kind="composition" to="" list="true"> <constructor name=' ' class="com.meta4.cms.warehouse.CreateTransfer" primary="true"> <attribute pname=" " name="auto_add" type="boolean" default="true"/> </constructor> </relation> <relation name="" kind="composition" to="" list="true"> <constructor name=' ' class="com.meta4.cms.warehouse.CreateRetirement" primary="true"> <attribute pname=" " name="auto_add" type="boolean" default="true"/> </constructor> </relation> <relation name="" kind="embedding" list="true"> <to> <entity name=""> <attribute name="" type="float" default="0" optional="false"/> <attribute name="" type="float" readonly="true" default="0"/> <attribute name="" type="float" readonly="true" default="0"/> <attribute name="" type="float" readonly="true" default="0"/> <relation name="" kind="reference" to="" optional="false"/> </entity> </to> </relation> <constructor name=' ' class="com.meta4.cms.warehouse.RequestConstructorLogic" primary="true"> <attribute name="" type="" list="true" optional="false" defaultExpression="user."/> <relation name="" kind="reference" to="" optional="false"/> </constructor> <presentation tableColumns="_, , _, , , "> <l10n> = = </l10n> </presentation> </entity> </projectDescription>
हमने एक सिस्टम बनाया, ताकि यह SaaS मोड को सपोर्ट करे, ताकि एक सर्वर में कई "प्रोजेक्ट्स" हो सकें, जिनमें से प्रत्येक में संचालित वस्तुओं की अपनी कक्षाएं हों। यही है, उपयोगकर्ताओं के एक समूह में CRM हो सकता है, दूसरे में इन्वेंट्री है, और तीसरे में इन्वेंट्री भी है, लेकिन रेस्तरां व्यवसाय के लिए विशेष, और यह सब एक सर्वर पर है।
हमारे काम के परिणामस्वरूप, हमने 3 "कलाकृतियों" का गठन किया:
- सूचना प्रणाली विवरण भाषा
- संरचना विवरण
- प्रस्तुति विवरण
- ट्रिगर विवरण
- सर्वर: जावा + जेट्टी + मोंगोडीबी। MongoDB का उपयोग इसकी स्कीमा-रहित डिज़ाइन के कारण किया जाता है, जिससे हमें एक संग्रह में विभिन्न संरचनाओं के साथ डेटा संग्रहीत करना आसान हो गया। हालाँकि, महत्वपूर्ण कमियों (लेन-देन में कमी और JOINs, धीमा एकत्रीकरण) के कारण, हम RDBMS पर स्विच करने की योजना बनाते हैं जब हम "बड़े और वयस्क" बन जाते हैं।
- ग्राहक: जावास्क्रिप्ट + मूट्स। पूरी प्रस्तुति क्लाइंट पर बनाई गई है, REST API सर्वर के माध्यम से डेटा तक पहुंच है। ग्राहक भाषा मॉडल के साथ काम करने के कार्यान्वयन को दोहराता है, लेकिन सरलीकृत रूप में, विशेष रूप से दृश्य के गठन के लिए, इस तथ्य को देखते हुए कि ग्राहक "पतला" है। पारंपरिक "टेक्स्टुअल" टेम्प्लेटाइजेशन के विपरीत, हम ट्री के DOM स्तर पर टेम्प्लेटिंग का उपयोग करते हैं (यह दृष्टिकोण बहुत दुर्लभ है और अगर यह दिलचस्प है तो मैं इसके बारे में लिखूंगा)
बेशक, हम अपने विचारों की पूर्ण प्राप्ति से बहुत दूर हैं। उदाहरण के लिए, "संचय रजिस्टर" के रूप में इस तरह की अवधारणा को लागू नहीं किया जाता है, अब इसे मैन्युअल रूप से ट्रिगर द्वारा अनुकरण किया जाता है। फिर भी, इस वर्ष हमने भाषा और उस प्रणाली की वास्तुकला की दृष्टि का गठन किया है जो इसे लागू करता है।