नमस्कार प्रिय पाठकों! इस लेख में मैं अपनी परियोजना की वास्तुकला के बारे में बात करना चाहता हूं, जिसे मैंने इसके लॉन्च पर 4 बार रिफलेक्ट किया था, क्योंकि मैं परिणाम से संतुष्ट नहीं था। मैं लोकप्रिय दृष्टिकोणों के नुकसान के बारे में बात करूँगा और अपना खुद का प्रदर्शन करूँगा।
मैं तुरंत कहना चाहता हूं कि यह मेरा पहला लेख है, मैं यह नहीं कह रहा हूं कि मुझे क्या करना है - सही है। मैं केवल यह दिखाना चाहता हूं कि मैंने क्या किया, बताएं कि मैं अंतिम परिणाम के लिए कैसे आया, और सबसे महत्वपूर्ण बात - दूसरों की राय लें।
मैंने कई अभियानों में काम किया और हर चीज का एक गुच्छा देखा जो मैंने अलग तरीके से किया होगा।
उदाहरण के लिए, मैं अक्सर एन-लेयर आर्किटेक्चर को देखता हूं, डेटा (डीए) के साथ काम करने के लिए एक परत होती है, व्यापार तर्क (बीएल) के साथ एक परत होती है जो डीए और संभवतः कुछ अन्य सेवाओं का उपयोग करके काम करती है, और एक दृश्य परत \ एपीआई भी है जिसमें एक अनुरोध प्राप्त किया जाता है, जिसे बीएल का उपयोग करके संसाधित किया जाता है। यह सुविधाजनक लगता है, लेकिन कोड को देखकर मुझे यह स्थिति दिखाई देती है:
- [डीए] एक जटिल क्वेरी - ठीक है, भले ही डेटा \ \ \ \ खींचती है
- [बीएल] above०% 1 विधि कहता है और परिणाम को ऊपर ले जाता है - यह खाली परत क्यों?
- [देखें] the०% कॉल 1 बीएल विधि ऊपर परिणाम को निकालती है - यह खाली परत क्यों?
इसके अलावा, इंटरफेस में लपेटना फैशनेबल है ताकि बाद में आप लॉक और टेस्ट कर सकें - वाह, बस वाह!
- क्यों भीग जाओ?
- खैर, परीक्षणों की अवधि के लिए साइड इफेक्ट्स में कटौती करने के लिए।
- यही है, हम दुष्प्रभावों के बिना विरोध करेंगे, लेकिन उनके साथ ठेस में?
...
यह एक बुनियादी बात है जो मुझे इस वास्तुकला में पसंद नहीं आई, क्योंकि एक समस्या को हल करने के लिए: "उपयोगकर्ता की पसंद पसंद" एक बड़ी प्रक्रिया है, लेकिन वास्तव में डेटाबेस में 1 क्वेरी और संभवतः मैपिंग है।
नमूना समाधान1) [डीए] डीए के लिए अनुरोध जोड़ें
2) [बीएल] फॉरवर्ड डीए प्रतिक्रिया
3) [देखें] आगे बीए परिणाम, को बढ़ावा देने सकता है
यह मत भूलो कि इन सभी तरीकों को अभी भी इंटरफ़ेस में जोड़ने की आवश्यकता है, हम गीला होने के लिए एक परियोजना लिख रहे हैं, और समाधान के लिए नहीं।
अन्य जगहों पर, मैंने CQRS दृष्टिकोण के साथ एक एपीआई कार्यान्वयन देखा।
समाधान खराब नहीं दिखता था, 1 फ़ोल्डर - 1 सुविधा। एक सुविधा बनाने वाला एक डेवलपर अपने फ़ोल्डर में बैठता है और लगभग हमेशा अन्य विशेषताओं पर अपने कोड के प्रभाव के बारे में भूल सकता है, लेकिन बहुत सारी फाइलें थीं कि यह सिर्फ एक बुरा सपना था। अनुरोध / प्रतिक्रिया मॉडल, सत्यापनकर्ता, सहायक, तर्क स्वयं। स्टूडियो में खोज के लिए व्यावहारिक रूप से काम करने से इनकार कर दिया गया था, कोड में आवश्यक चीजों को खोजने के लिए एक्सटेंशन लगाए गए थे।
अभी बहुत कुछ कहा जाना बाकी है, लेकिन मैंने उन मुख्य कारणों पर प्रकाश डाला, जिन्होंने मुझे इससे इंकार किया
और अंत में मेरे प्रोजेक्ट के लिए
जैसा कि मैंने कहा, मैंने कई बार अपनी परियोजना को रद्द कर दिया, उस समय मुझे "प्रोग्रामर डिप्रेशन" था, मैं सिर्फ अपने कोड से खुश नहीं था, और इसे फिर से दोहराया, अंत में मैंने आवेदन की वास्तुकला के बारे में एक वीडियो देखना शुरू किया कि कैसे देखें दूसरे करते हैं। मैं डीडीडी और कार्यात्मक प्रोग्रामिंग के बारे में एंटोन मोल्दोवन की रिपोर्ट में आया, और सोचा: "यहाँ यह है, मुझे एफ # की जरूरत है!"।
एफ # पर कुछ दिन बिताने के बाद, मुझे एहसास हुआ कि, सिद्धांत रूप में, मैं सी # में एक ही काम करूंगा और कोई भी बदतर नहीं होगा। दिखाया गया वीडियो:
- यहां सी # कोड है, यह गंदगी है
- यहाँ F # कूल है, कम लिखा है - सुपर।
लेकिन चाल यह है कि एफ # पर समाधान अलग तरीके से लागू किया गया था, और इसके खिलाफ उन्होंने सी # पर एक खराब कार्यान्वयन दिखाया। मुख्य सिद्धांत यह था कि बीएल एक ऐसी चीज नहीं है जो डीए सेवाओं को बुलाती है और सभी काम करती है, लेकिन यह एक शुद्ध कार्य है ।
बेशक एफ # अच्छा है, मुझे कुछ विशेषताएं पसंद हैं लेकिन, सी # की तरह, यह सिर्फ एक उपकरण है जिसे विभिन्न तरीकों से उपयोग किया जा सकता है।
और मैं C # पर वापस चला गया और बनाना शुरू कर दिया।
मैंने समाधान में ऐसी परियोजनाएँ बनाईं:
- एपीआई
- कोर
- सेवाएं
- टेस्ट
मैंने C # 8 फीचर्स का भी इस्तेमाल किया, विशेष रूप से नॉलेबल रिफेंस टाइप, मैं इसका एप्लिकेशन दिखाऊंगा।
परतों के कार्यों के बारे में संक्षेप में जो मैंने उन्हें दिया था।
एपीआई
1) अनुरोध प्राप्त करना, अनुरोध मॉडल + सत्यापन, प्रतिबंध
2) कोर और सेवाओं से कॉलिंग फ़ंक्शन
अधिक जानकारी
यहां हम एक सरल, पठनीय कोड देखते हैं, मुझे लगता है कि हर कोई समझ जाएगा कि यहां क्या लिखा गया है।
स्पष्ट पैटर्न का अवलोकन किया
1) डेटा प्राप्त करें
2) प्रक्रिया, संशोधित, आदि - इस भाग का परीक्षण करने की आवश्यकता है।
3) बचाओ।
3) जरूरत पड़ने पर मैपिंग
4) त्रुटि से निपटने (लॉगिंग + मानव प्रतिक्रिया)
अधिक जानकारीइस वर्ग में सभी संभावित अनुप्रयोग त्रुटियां हैं, जिनका अपवाद हैंडलर करता है।


यह पता चला है कि एप्लिकेशन या तो काम करता है, या एक विशिष्ट त्रुटि देता है, न कि संसाधित त्रुटियां या तो एक साइड इफेक्ट या बग हैं, इस तरह की त्रुटियों का लॉग बॉट के साथ चैट में टेलीग्राम में मेरे पास तुरंत उड़ जाता है।
मेरे पास AppError है। एक अस्पष्ट मामले के लिए इस त्रुटि को पूरा करें।
मेरे पास किसी अन्य सेवा से कॉलबैक है, इसमें मेरे सिस्टम में एक userId होगा, और अगर मुझे इस आईडी वाला कोई उपयोगकर्ता नहीं मिलता है, या तो उपयोगकर्ता के साथ कुछ हुआ है या यह बिल्कुल भी स्पष्ट नहीं है, तो ऐसी त्रुटि मेरे लिए CRICICAL की तरह उड़ती है, सिद्धांत रूप में यह नहीं होना चाहिए उत्पन्न होना, लेकिन अगर ऐसा होता है, तो इसके लिए मेरे हस्तक्षेप की आवश्यकता है।

कोर, सबसे दिलचस्प
मेरे दिमाग में हमेशा यह बात थी कि बीएलएस केवल ऐसे कार्य हैं जो एक ही इनपुट के साथ एक ही परिणाम देते हैं। इस परत में कोड की जटिलता प्रयोगशाला के काम के स्तर पर थी, न कि महान कार्य जो स्पष्ट रूप से और त्रुटियों के बिना अपना काम करते हैं। और यह महत्वपूर्ण था कि फ़ंक्शन के अंदर कोई साइड इफेक्ट नहीं थे, सभी आवश्यक फ़ंक्शन इसके पैरामीटर थे।
यदि फ़ंक्शन को उपयोगकर्ता संतुलन की आवश्यकता होती है, तो हम शेष राशि प्राप्त करते हैं, और इसे फ़ंक्शन में स्थानांतरित करते हैं, और उपयोगकर्ता सेवा को बीएल में धक्का नहीं देते हैं।
1) संस्थाओं की बुनियादी कार्रवाई
अधिक जानकारी

मैं विस्तार विधियों के रूप में तरीकों के साथ आया था ताकि वर्ग फूले नहीं, और कार्यक्षमता को सुविधाओं द्वारा समूहीकृत किया जा सके।


मैं इकाई मॉडल का एक अच्छा निर्माण एक समान रूप से महत्वपूर्ण विषय मानता हूं।
उदाहरण के लिए, मेरे पास एक उपयोगकर्ता है, उपयोगकर्ता के पास कई मुद्राओं में संतुलन है। बिना किसी हिचकिचाहट के मैंने जो विशिष्ट निर्णय लिए, उनमें से एक है "बैलेंस" का सार और उपयोगकर्ता में संतुलन की एक सरणी। लेकिन इस तरह का फैसला किस तरह की सुविधा लेकर आया?
1) मुद्राओं को जोड़ना / हटाना। इस कार्य का तात्पर्य हमारे लिए न केवल नए कोड लिखना है, बल्कि सभी मौजूदा उपयोगकर्ताओं को भरने / हटाने के साथ माइग्रेशन भी है, और यह सबसे आसान विकल्प है। भगवान न करें, एक नई मुद्रा जोड़ने के लिए, आपको उपयोगकर्ता के लिए एक बटन बनाना होगा, जिसे वह क्लिक करता है और किसी प्रकार की व्यावसायिक प्रक्रिया के लिए एक नया बटुआ बनाने की पहल करता है। नतीजतन, नई मुद्रा के लिए केवल एनम का विस्तार करना आवश्यक था, और उन्होंने एक बटन द्वारा पर्स बनाने के लिए एक और विशेषता लिखी, उन्होंने एक और कार्य सामने की ओर फेंक दिया।
2) कोड में, FirstOrDefault constants (s => s.Currency == करेंसी) और null के लिए जाँच
मेरा फैसला
मॉडल द्वारा मैं खुद को गारंटी देता हूं कि कोई अशक्त संतुलन नहीं होगा, और अनुक्रमणिका ऑपरेटर बनाकर मैंने शेष के साथ बातचीत के सभी स्थानों में अपने कोड को सरल बनाया।
सेवाएं
यह परत मुझे विभिन्न सेवाओं के साथ काम करने के लिए सुविधाजनक उपकरण प्रदान करती है।
अपनी परियोजना में मैं MongoDB का उपयोग करता हूं और इसके साथ सुविधाजनक काम के लिए, मैंने इस तरह के भंडार में संग्रह को लपेटा।
अधिक जानकारीरिपोजिटरी ही

मोंगा क्रमशः इसके साथ काम करने के समय दस्तावेज़ को अवरुद्ध करता है, इससे हमें अनुरोधों की प्रतियोगिता में समस्याओं को हल करने में मदद मिलेगी। और मोंग में एक इकाई के लिए खोज करने के लिए तरीके हैं + उस पर अभिनय, उदाहरण के लिए: "आईडी के साथ एक उपयोगकर्ता ढूंढें और अपने वर्तमान संतुलन में 10 जोड़ें"
और अब C # 8 की सुविधा के बारे में।


विधि हस्ताक्षर मुझे बताता है कि उपयोगकर्ता वापस आ सकता है, और शायद नल, क्रमशः, जब मैं उपयोगकर्ता को देखूंगा? मुझे तुरंत एक संकलक चेतावनी मिलती है, और एक शून्य जांच करते हैं।

जब विधि उपयोगकर्ता वापस आती है, तो मैं आत्मविश्वास के साथ काम करता हूं।

मैं इस तथ्य पर भी ध्यान आकर्षित करना चाहता हूं कि कोई भी पकड़ने की कोशिश नहीं है क्योंकि केवल "अजीब परिस्थितियों" से अपवाद हो सकते हैं और गलत डेटा जो यहां तक नहीं पहुंचना चाहिए क्योंकि सत्यापन है। एपीआई लेयर में भी कोई पकड़ने की कोशिश नहीं है, केवल एक वैश्विक अपवाद हैंडलर है।
केवल एक विधि है जो अपवाद फेंकता है अद्यतन विधि है।
यह बहु-थ्रेडेड मोड में डेटा हानि के खिलाफ सुरक्षा को लागू करता है।

आपने ऊपर उल्लिखित मोंगा विधियों का उपयोग क्यों नहीं किया?
ऐसी जगहें हैं जहां मैं अभी भी यह सुनिश्चित करने के लिए नहीं जानता कि क्या मैं उपयोगकर्ता के साथ काम कर सकता हूं, शायद उसके पास इस क्रिया के लिए पैसे नहीं हैं, इसलिए शुरुआत में मैं उपयोगकर्ता को बाहर निकालता हूं और जांच करता हूं, फिर उसे म्यूट करें और सहेजें।

सिद्धांत रूप में मेरा एप्लिकेशन उपयोगकर्ता के संतुलन को प्रति सेकंड 1 से अधिक बार बदल देगा, क्योंकि ये तेज गेम होंगे।
लेकिन उपयोगकर्ता का मॉडल स्वयं, यह स्पष्ट रूप से दिखाई देता है कि उपयोगकर्ता का संदर्भ वैकल्पिक है, और आप अशक्त के बारे में सोचने के बिना बाकी सब के साथ काम कर सकते हैं।

अंत में टेस्ट
जैसा कि मैंने कहा, आपको केवल तर्क का परीक्षण करने की आवश्यकता है, और हमारे कार्य का तर्क दुष्प्रभाव के बिना है।
इसलिए, हम अपने परीक्षणों को बहुत जल्दी और विभिन्न मापदंडों के साथ चला सकते हैं।
अधिक जानकारीमैंने nuget FSCheck डाउनलोड किया है जो यादृच्छिक रूप से आने वाले डेटा को उत्पन्न करता है और कई अलग-अलग मामलों के लिए अनुमति देता है।
मुझे बस विभिन्न उपयोगकर्ताओं को बनाने, उनके परीक्षण को खिलाने और परिवर्तनों की जांच करने की आवश्यकता है।
ऐसे उपयोगकर्ताओं को बनाने के लिए एक छोटा बिल्डर है, लेकिन इसका विस्तार करना आसान है।

और यहाँ परीक्षण स्वयं हैं



कुछ परिवर्तनों के बाद, मैं परीक्षण चलाता हूं, 1-2 सेकंड के बाद मैं देखता हूं कि सब कुछ क्रम में है।
यह बाहर से संपूर्ण एपीआई की जांच करने के लिए E2E परीक्षण लिखने की योजना में है और यह सुनिश्चित करने के लिए है कि यह अनुरोध के अनुसार, प्रतिक्रिया के लिए काम करता है।
चिप्स
आप की आवश्यकता हो सकती है शांत सामानमेरे प्रत्येक अनुरोध को डोप किया जाता है, जब एक बग होता है, तो मैं requestId ढूंढता हूं और अनुरोध को दोहराकर आसानी से बग को पुन: उत्पन्न कर सकता हूं, क्योंकि मेरे एपीआई में एक राज्य नहीं है, और प्रत्येक अनुरोध केवल अनुरोध पैरामीटर पर निर्भर करता है।

संक्षेप में देना।
हमने वास्तव में एक समाधान लिखा था, न कि एक रूपरेखा जिसमें अतिरिक्त अमूर्त का एक गुच्छा, साथ ही मोक। हमने एक स्थान पर त्रुटि से निपटने के लिए किया और वे बहुत कम ही होने चाहिए। हमने बीएल और साइड इफेक्ट्स को अलग किया, अब बीएल केवल एक स्थानीय तर्क है जिसे पुन: उपयोग किया जा सकता है। हमने अतिरिक्त फ़ंक्शन नहीं लिखे जो कॉल को अन्य फ़ंक्शन के लिए अग्रेषित करते हैं। मैं सक्रिय रूप से टिप्पणियों को पढ़ूंगा और लेख को पूरक करूंगा, धन्यवाद!