क्या आपको इस तरह के मामलों में फ़ंक्शन में आवश्यक नंगे न्यूनतम डेटा को हमेशा पास करना चाहिए


81

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

मेरे सिर में इसके लिए दो संभावित फ़ंक्शन हस्ताक्षर हैं:

public bool IsAdmin(User user);
public bool IsAdmin(int id, string name, string password);

मैं अक्सर दूसरे प्रकार के हस्ताक्षर के लिए जाता हूं, यह सोचकर कि:

  • फ़ंक्शन हस्ताक्षर पाठक को बहुत अधिक जानकारी देता है
  • फ़ंक्शन के अंदर निहित तर्क को Userकक्षा के बारे में जानना नहीं है
  • यह आमतौर पर फ़ंक्शन के अंदर थोड़ा कम कोड में परिणाम होता है

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

मैं या तो शैली के लिए किसी भी तर्क की सराहना करता हूं, साथ ही साथ आप जो भी सामान्य टिप्पणियों की पेशकश कर सकते हैं।

मैं दोनों वस्तु उन्मुख और कार्यात्मक शैलियों में कार्यक्रम करता हूं, इसलिए प्रश्न को किसी भी और सभी मुहावरों के रूप में देखा जाना चाहिए।


40
ऑफ-टॉपिक: जिज्ञासा से बाहर, उपयोगकर्ता के "एडमिन" की स्थिति उनके पासवर्ड पर क्यों निर्भर करती है?
स्टैक x

43
@ syb0rg गलत। C # में यह नामकरण सम्मेलन है
मैग्नेटिक

68
@ syb0rg राइट, उन्होंने भाषा को निर्दिष्ट नहीं किया, इसलिए मुझे लगता है कि यह बताने के लिए अजीब है कि वह एक निश्चित भाषा के सम्मेलन का उल्लंघन कर रहे हैं।
मैग्नेटिक

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

6
एक सामान्य बिंदु के रूप में, अपनी खुद की सुरक्षा को रोल करना आमतौर पर एक बुरी बात है (टीएम) । अधिकांश भाषाओं और रूपरेखाओं में एक सुरक्षा / अनुमति प्रणाली उपलब्ध है और जब आप कुछ सरल चाहते हैं तो भी उनके उपयोग करने के अच्छे कारण हैं।
जेम्स स्नेल

जवाबों:


123

मैं व्यक्तिगत रूप से सिर्फ पहली विधि पसंद करता हूं IsAdmin(User user)

इसका उपयोग करना बहुत आसान है, और यदि बाद के दिनांक में (शायद भूमिकाओं पर आधारित है, या isActive) IsAdmin के लिए आपके मानदंड बदल जाते हैं, तो आपको हर जगह अपने तरीके के हस्ताक्षर को फिर से लिखने की आवश्यकता नहीं है।

यह भी शायद अधिक सुरक्षित है क्योंकि आप विज्ञापन नहीं दे रहे हैं कि क्या गुण निर्धारित करते हैं कि उपयोगकर्ता व्यवस्थापक है या नहीं, या हर जगह पासवर्ड संपत्ति के आसपास से गुजर रहा है। और सीरियन एक अच्छा बिंदु बनाता है कि क्या होता है जब आपका / से idमेल नहीं खाता है ?namepassword

किसी फ़ंक्शन के अंदर कोड की लंबाई वास्तव में इस विधि को प्रदान करने से कोई मतलब नहीं होना चाहिए, और मैं बहुत कम बल्कि हेल्पी पद्धति कोड की तुलना में कम और सरल अनुप्रयोग कोड है।


3
मुझे लगता है कि रिफैक्टिंग मुद्दा बहुत अच्छा बिंदु है - धन्यवाद।
एंडर्स अरपी

1
यदि आप नहीं करते हैं, तो मैं विधि हस्ताक्षर तर्क बनाने जा रहा हूं। यह विशेष रूप से तब मददगार होता है जब आपकी विधि पर बहुत अधिक निर्भरता हो जो अन्य प्रोग्रामर द्वारा बनाए रखी जाती है। यह लोगों को एक दूसरे के रास्ते से बाहर रखने में मदद करता है। +1
jmort253

1
मैं इस उत्तर से सहमत हूं, लेकिन मुझे दो स्थितियों को चिह्नित करने दें जहां अन्य दृष्टिकोण ("न्यूनतम डेटा") बेहतर हो सकता है: (1) आप विधि परिणामों को कैश करना चाहते हैं। कैश ऑब्जेक्ट के रूप में पूरे ऑब्जेक्ट का उपयोग न करने के लिए बेहतर है, या प्रत्येक इनवोकेशन पर ऑब्जेक्ट के गुणों की जांच करना है। (2) आप चाहते हैं कि विधि / कार्य असिंक्रोनस रूप से निष्पादित हो, जिसमें तर्कों को क्रमबद्ध करना शामिल हो सकता है और, उन्हें तालिका में संग्रहीत करते हुए कहा जा सकता है। लंबित नौकरियों के प्रबंधन के दौरान ऑब्जेक्ट की तुलना में पूर्णांक को देखने में आसान और सरल।
ग्लैडस्टोन कीप

इकाई परीक्षण के लिए आदिम जुनून विरोधी पैटर्न भयानक हो सकता है।
शमूएल

82

पहला हस्ताक्षर बेहतर है क्योंकि यह उपयोगकर्ता से संबंधित तर्क के Userऑब्जेक्ट में ही एनकैप्सुलेशन की अनुमति देता है। अपने आईडी आधार के बारे में "आईडी, नाम, पासवर्ड" के निर्माण के लिए तर्क रखना फायदेमंद नहीं है। इसके अलावा, यह isAdminफ़ंक्शन को जटिल करता है: उदाहरण के लिए, यदि कोई idइसमें से नहीं गुजरता है तो क्या होता है name? क्या होगा यदि आप जांचना चाहते हैं कि क्या दिया गया उपयोगकर्ता किसी संदर्भ से व्यवस्थापक है जहां आपको उनका पासवर्ड नहीं पता होना चाहिए ?

इसके अलावा, अतिरिक्त तर्कों के साथ शैली के पक्ष में अपने तीसरे बिंदु पर एक नोट के रूप में; इसका परिणाम "फ़ंक्शन के अंदर कम कोड" हो सकता है, लेकिन वह तर्क कहां जाता है? यह सिर्फ गायब नहीं हो सकता! इसके बजाय, यह हर एक जगह पर फैलता है जहाँ फ़ंक्शन को कहा जाता है। एक ही स्थान पर पाँच लाइनों के कोड को सहेजने के लिए, आपने फ़ंक्शन के उपयोग के लिए पाँच लाइनों का भुगतान किया है!


45
अपने तर्क के बाद, user.IsAdmin()बेहतर नहीं होगा ?
एंडर्स अरपी

13
हाँ बिल्कुल।
एस्ट्रोसैट

6
@ AndersHolmström यह निर्भर करता है, क्या आप परीक्षण कर रहे हैं यदि उपयोगकर्ता सामान्य रूप से एक व्यवस्थापक है, या आपके द्वारा चालू पृष्ठ / फ़ॉर्म के लिए सिर्फ एक व्यवस्थापक है। यदि सामान्य तौर पर, तो हाँ यह बेहतर होगा, लेकिन यदि आप केवल IsAdminएक विशिष्ट रूप या फ़ंक्शन के लिए परीक्षण कर रहे हैं , तो उपयोगकर्ता से संबंधित नहीं होना चाहिए
राहेल

40
@ और: नहीं, यह नहीं होना चाहिए। एक उपयोगकर्ता को यह तय नहीं करना चाहिए कि यह एक व्यवस्थापक है या नहीं। प्रिविलेज या सिक्योरिटी सिस्टम चाहिए। किसी चीज को कसकर किसी वर्ग के साथ जोड़े जाने का मतलब यह नहीं है कि इसे उस कक्षा का हिस्सा बनाना एक अच्छा विचार है
मार्जन वेनमा

11
@MarjanVenema - यह विचार कि उपयोगकर्ता वर्ग को "निर्णय" नहीं करना चाहिए कि क्या एक उदाहरण है कि एक व्यवस्थापक मुझे एक बिट-कार्गो के रूप में हमला करता है। आप वास्तव में उस सामान्यीकरण को इतनी दृढ़ता से नहीं बना सकते। अपनी आवश्यकताओं जटिल कर रहे हैं, तो शायद यह फायदेमंद उन्हें एक अलग "प्रणाली" में संपुटित करने के लिए है, लेकिन हवाला KISS + YAGNI मुझे लगता है कि निर्णय वास्तव में उस जटिलता का सामना करना पड़ करना चाहते हैं, और नहीं एक सामान्य नियम के रूप में :-)। और ध्यान दें कि भले ही तर्क उपयोगकर्ता का "भाग" न हो, फिर भी यह व्यावहारिकता के रूप में उपयोगी हो सकता है कि उपयोगकर्ता के लिए एक पूर्वाग्रह हो जो कि एक अधिक जटिल प्रणाली को दर्शाता है।
ईमोन नेरबोन 21

65

दूसरों ने जो कारण बताए हैं उनमें से पहला, लेकिन (केवल) नहीं।

public bool IsAdmin(User user);

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

public bool IsAdmin(int id, string name, string password);

यहां, कोई भी इंट और दो तार करेंगे। आपको नाम और पासवर्ड को ट्रांसपोज़ करने से क्या रोकता है? दूसरा उपयोग करने के लिए अधिक काम है और त्रुटि के लिए अधिक अवसर देता है।

संभवतः, दोनों फ़ंक्शन के लिए आवश्यक है कि user.getId (), user.getName (), और user.getPassword () कहा जाए, या तो फ़ंक्शन के अंदर (पहले मामले में) या फ़ंक्शन को कॉल करने से पहले (दूसरे में), इसलिए युग्मन की मात्रा भी इसी तरह है। वास्तव में, चूंकि यह फ़ंक्शन केवल उपयोगकर्ताओं पर मान्य है, जावा में मैं सभी तर्कों को समाप्त करूंगा और उपयोगकर्ता वस्तुओं पर यह एक उदाहरण विधि बनाऊंगा:

user.isAdmin();

चूंकि यह फ़ंक्शन पहले से ही उपयोगकर्ताओं के लिए कसकर युग्मित है, इसलिए यह समझ में आता है कि उपयोगकर्ता क्या है।

PS मुझे यकीन है कि यह सिर्फ एक उदाहरण है, लेकिन ऐसा लगता है कि आप एक पासवर्ड स्टोर कर रहे हैं। आपको इसके बजाय केवल एक क्रिप्टोग्राफिक रूप से सुरक्षित पासवर्ड हैश को स्टोर करना चाहिए। लॉगिन के दौरान, आपूर्ति किए गए पासवर्ड को उसी तरह से हैश किया जाना चाहिए और संग्रहीत हैश के खिलाफ तुलना की जानी चाहिए। सादे-पाठ में आस-पास के पासवर्ड भेजने से बचना चाहिए। यदि आप इस नियम का उल्लंघन करते हैं और isAdmin (int Str Str) उपयोगकर्ता नाम लॉग इन करने के लिए थे, तो यदि आपने अपने कोड में नाम और पासवर्ड को ट्रांसपोज़ किया, तो पासवर्ड को लॉग इन किया जा सकता है जो सुरक्षा समस्या पैदा करता है (लॉग में पासवर्ड न लिखें ) और इसके घटक भागों (या एक वर्ग विधि का उपयोग करके) के बजाय एक वस्तु को पारित करने के पक्ष में एक और तर्क है।


11
एक उपयोगकर्ता को यह तय नहीं करना चाहिए कि यह एक व्यवस्थापक है या नहीं। प्रिविलेज या सिक्योरिटी सिस्टम चाहिए। किसी चीज को किसी वर्ग के साथ कसकर जोड़े जाने का मतलब यह नहीं है कि इसे उस कक्षा का हिस्सा बनाना एक अच्छा विचार है।
मार्जन वेनमा

6
@MarjanVenema उपयोगकर्ता कुछ भी तय नहीं कर रहा है। उपयोगकर्ता ऑब्जेक्ट / टेबल प्रत्येक उपयोगकर्ता के बारे में डेटा संग्रहीत करता है। वास्तविक उपयोगकर्ताओं को अपने बारे में सब कुछ बदलने के लिए नहीं मिलता है। यहां तक ​​कि जब उपयोगकर्ता किसी ऐसी चीज़ को बदलता है जिसकी उन्हें अनुमति होती है, तो यह ईमेल की तरह सुरक्षा अलर्ट ट्रिगर कर सकता है यदि वे अपना ईमेल पता या अपना उपयोगकर्ता आईडी या पासवर्ड बदलते हैं। क्या आप एक ऐसी प्रणाली का उपयोग कर रहे हैं जहां उपयोगकर्ताओं को जादुई रूप से कुछ वस्तु प्रकारों के बारे में सब कुछ बदलने की अनुमति है? मैं ऐसी व्यवस्था से परिचित नहीं हूं।
ग्लेनपेटर्सन

2
@GlenPeterson: क्या आप जानबूझकर मुझे गलत समझ रहे हैं? जब मैंने उपयोगकर्ता कहा था, तो मैं निश्चित रूप से उपयोगकर्ता वर्ग का मतलब था।
मार्जन वेनेमा

2
@GlenPeterson पूरी तरह से विषय से दूर है, लेकिन हैशिंग और क्रिप्टोग्राफ़िक कार्यों के कई दौर डेटा को कमजोर करेंगे।
9

3
@ मार्जनवीनेमा: मैं जानबूझकर मुश्किल नहीं हूं। मुझे लगता है कि हमारे पास बहुत अलग दृष्टिकोण हैं और मैं आपको बेहतर तरीके से समझना चाहूंगा। मैंने एक नया प्रश्न खोला है, जहां इस पर बेहतर चर्चा की जा सकती है: programmers.stackexchange.com/questions/216443/…
GlenPeterson

6

यदि आपकी पसंद की भाषा मूल्य द्वारा संरचनाओं को पारित नहीं करती है, तो (User user)संस्करण बेहतर लगता है। क्या होगा यदि किसी दिन आप उपयोगकर्ता नाम को स्क्रैप करने का निर्णय लेते हैं और उपयोगकर्ता की पहचान करने के लिए आईडी / पासवर्ड का उपयोग करते हैं?

इसके अलावा, इस दृष्टिकोण को अनिवार्य रूप से लंबी और ओवरब्लो विधि कॉल या असंगतता की ओर जाता है। क्या 3 तर्क देना ठीक है? 5 के बारे में कैसे? या 6? ऐसा क्यों लगता है, यदि किसी वस्तु को पास करना संसाधनों के लिहाज से सस्ता है (3 तर्क पास करने से भी सस्ता, शायद)?

और मैं (तरह का) असहमत हूं कि दूसरा दृष्टिकोण पाठक को अधिक जानकारी देता है - सहजता से, विधि कॉल पूछ रही है "क्या उपयोगकर्ता के पास व्यवस्थापक अधिकार हैं", न कि "दिए गए आईडी / नाम / पासवर्ड संयोजन में व्यवस्थापक अधिकार हैं"।

इसलिए, जब तक कि Userवस्तु को पारित करने के परिणामस्वरूप एक बड़ी संरचना की नकल नहीं होगी, पहला दृष्टिकोण क्लीनर और मेरे लिए अधिक तार्किक है।


3

मैं शायद दोनों होगा। बाहरी एपीआई के रूप में पहला, समय में स्थिरता की कुछ आशा के साथ। बाहरी एपीआई द्वारा एक निजी कार्यान्वयन के रूप में दूसरा।

अगर कुछ समय बाद मुझे चेकिंग नियम बदलना है, तो मैं सिर्फ एक नया निजी फ़ंक्शन लिखूंगा जिसमें एक बाहरी हस्ताक्षर होगा।

इससे आंतरिक कार्यान्वयन को बदलने में आसानी का लाभ मिलता है। यह भी वास्तव में सामान्य है कि कुछ समय में आपको एक ही समय में उपलब्ध दोनों फ़ंक्शन की आवश्यकता हो सकती है और कुछ बाहरी संदर्भ परिवर्तन के आधार पर एक या दूसरे को कॉल कर सकते हैं (उदाहरण के लिए आपके पास पुराने उपयोगकर्ता और नए उपयोगकर्ता अलग-अलग क्षेत्रों के साथ हो सकते हैं)।

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

दूसरे शब्दों में, यदि आप डेटाबेस के साथ काम कर रहे थे तो एक उपयोगकर्ता एक रिकॉर्ड होगा, जबकि आईडी, पासवर्ड और लॉगिन उस रिकॉर्ड में फ़ील्ड होंगे।


मैं निजी पद्धति का कारण नहीं देखता हूं। दोनों को क्यों बनाए रखा? यदि निजी पद्धति को विभिन्न तर्कों की आवश्यकता होती है, तो आपको अभी भी सार्वजनिक संशोधन करना होगा। और आप इसे जनता के माध्यम से परखेंगे। और नहीं, यह सामान्य नहीं है कि आपको कुछ समय बाद दोनों की आवश्यकता है। आप यहाँ अनुमान लगा रहे हैं - YAGNI।
पियोत्र पेरक

आप उदाहरण के लिए मान रहे हैं कि उपयोगकर्ता डेटा संरचना में शुरुआत से कोई अन्य फ़ील्ड नहीं है। यह आमतौर पर सच नहीं है। दूसरा फ़ंक्शन यह स्पष्ट करता है कि उपयोगकर्ता का कौन सा आंतरिक भाग यह देखने के लिए जाँचा जाता है कि क्या यह एक व्यवस्थापक है। विशिष्ट उपयोग के मामले इस प्रकार के हो सकते हैं: यदि उपयोगकर्ता के निर्माण का समय कुछ तारीख से पहले है, तो पुराने नियम को कॉल करें, यदि नया नियम नहीं कहते हैं (जो उपयोगकर्ता के अन्य भागों पर निर्भर हो सकता है, या उसी पर निर्भर करता है, लेकिन किसी अन्य नियम का उपयोग करके)। कोड को इस तरह विभाजित करने से आपको दो न्यूनतम कार्य मिलेंगे: एक न्यूनतम वैचारिक एपीआई और एक न्यूनतम कार्यान्वयन फ़ंक्शन।
kriss

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

एक और शब्द: मैं निश्चित रूप से बाहरी के माध्यम से आंतरिक विधि का परीक्षण नहीं करूंगा। यह बुरा परीक्षण अभ्यास है।
क्रि।

1
यह एक अच्छा अभ्यास है, और इसके लिए एक नाम है। इसे "एकल जिम्मेदारी सिद्धांत" कहा जाता है। इसे कक्षाओं और विधियों दोनों पर लागू किया जा सकता है। एक ही ज़िम्मेदारी के साथ तरीके होना अधिक मॉड्यूलर और मेंटेनेंस कोड बनाने का एक अच्छा तरीका है। इस स्थिति में, एक कार्य उपयोगकर्ता ऑब्जेक्ट से डेटा का मूल सेट चुन रहा है, और दूसरा कार्य यह जाँच रहा है कि डेटा का मूल सेट यह देखने के लिए है कि उपयोगकर्ता एक व्यवस्थापक है या नहीं। इस सिद्धांत का पालन करने से आपको तरीकों की रचना करने और कोड दोहराव से बचने में सक्षम होने का बोनस मिलता है। इसका मतलब यह भी है, जैसा कि @kriss द्वारा कहा गया है कि आपको बेहतर इकाई परीक्षण मिलते हैं।
diegoreymendez

3

वर्गों में (संदर्भ प्रकार) भेजने के लिए एक नकारात्मक बिंदु है, और वह है, मास-एसाइनमेंट वल्नरेबिलिटी । कल्पना कीजिए कि IsAdmin(User user)विधि के बजाय , मेरे पास UpdateUser(User user)विधि है।

यदि Userक्लास में बूलियन प्रॉपर्टी होती है IsAdmin, और अगर मैं इसे अपने तरीके के निष्पादन के दौरान जांच नहीं करता हूं, तो मैं बड़े पैमाने पर असाइनमेंट के लिए असुरक्षित हूं। 2012 में GitHub ने इसी हस्ताक्षर से हमला किया था।


2

मैं इस दृष्टिकोण के साथ जाऊँगा:

public bool IsAdmin(this IUser user) { /* ... */ }

public class User: IUser { /* ... */ }

public interface IUser
{
    string Username {get;}
    string Password {get;}
    IID Id {get;}
}
  • इस फ़ंक्शन के लिए एक पैरामीटर के रूप में इंटरफ़ेस प्रकार का उपयोग करना आपको उपयोगकर्ता ऑब्जेक्ट में परीक्षण करने के लिए नकली उपयोगकर्ता वस्तुओं को परिभाषित करने की अनुमति देता है, और आपको इस फ़ंक्शन के उपयोग और रखरखाव दोनों के बारे में अधिक लचीलापन देता है।

  • मैंने thisफ़ंक्शन को सभी IUser कक्षाओं की विस्तार विधि बनाने के लिए भी जोड़ा ; इस तरह आप कोड को अधिक OO फ्रेंडली तरीके से लिख सकते हैं और इस फ़ंक्शन का उपयोग Linq प्रश्नों में कर सकते हैं। सरल अभी भी IUser और उपयोगकर्ता में इस फ़ंक्शन को परिभाषित करना होगा, लेकिन मुझे लगता है कि कुछ कारण है कि आपने इस पद्धति को उस वर्ग के बाहर रखने का निर्णय क्यों लिया?

  • मैं IIDइसके बजाय कस्टम इंटरफ़ेस का उपयोग करता हूं, intइससे आप अपनी आईडी के गुणों को फिर से परिभाषित कर सकते हैं; जैसे आप कभी से बदलने की जरूरत है चाहिए intकरने के लिए long, Guid, या कुछ और। यह शायद ओवरकिल है, लेकिन हमेशा चीजों को लचीला बनाने की कोशिश करना अच्छा होता है ताकि आप शुरुआती फैसलों में बंद न हों।

  • नायब: आपकी IUser वस्तु एक अलग नामस्थान और / या असेंबली में उपयोगकर्ता वर्ग के लिए हो सकती है, इसलिए आपके पास अपना उपयोगकर्ता कोड अपने IsAdmin कोड से पूरी तरह से अलग रखने का विकल्प है, उनके साथ केवल एक संदर्भित पुस्तकालय साझा करना है। वास्तव में आप क्या करते हैं, इसके लिए एक कॉल है कि आप इन वस्तुओं का उपयोग करने के लिए कैसे संदेह करते हैं।


3
IUser यहां बेकार है और केवल जटिलता जोड़ता है। मैं यह नहीं देखता कि आप परीक्षणों में वास्तविक उपयोगकर्ता का उपयोग क्यों नहीं कर सकते।
पियोत्र पेरक

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

@Peri एक वास्तविक उपयोगकर्ता वर्ग बनाने के लिए जटिल हो सकता है, एक इंटरफ़ेस लेने से आप इसे नकली कर सकते हैं ताकि आप अपने परीक्षणों को सरल रख सकें
Userk।

@ जॉनलेन: यज्ञी !!!
पायोत्र पेरक

@jk: अगर उपयोगकर्ता को बनाना मुश्किल है तो कुछ गलत है
पेरक

1

अस्वीकरण:

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

मैं भी इसके user.isAdmin()समकक्ष मानता हूं IsAdmin(User user)। यह आपके लिए एक विकल्प है।

जवाब दे दो:

मेरी सिफारिश केवल उपयोगकर्ता के लिए है:

public bool IsAdmin(User user);

या दोनों का उपयोग करें:

public bool IsAdmin(User user); // calls the private method below
private bool IsAdmin(int id, string name, string password);

सार्वजनिक विधि के कारण:

सार्वजनिक तरीकों को लिखते समय आमतौर पर यह सोचना एक अच्छा विचार है कि उनका उपयोग कैसे किया जाएगा।

इस विशेष मामले के लिए, आमतौर पर इस विधि को कॉल करने का कारण यह पता लगाना है कि क्या एक निश्चित उपयोगकर्ता एक व्यवस्थापक है। यह एक ऐसी विधि है जिसकी आपको आवश्यकता है। आप वास्तव में नहीं चाहते हैं कि प्रत्येक कॉलर को भेजने के लिए सही मापदंडों को चुनना होगा (और कोड दोहराव के कारण गलतियों को जोखिम में डालना)।

निजी विधि के कारण:

आवश्यक मापदंडों का केवल न्यूनतम सेट प्राप्त करने वाला निजी तरीका कभी-कभी एक अच्छी बात हो सकती है। कभी-कभी इतना नहीं।

इन विधियों को विभाजित करने के बारे में एक अच्छी बात यह है कि आप एक ही कक्षा में कई सार्वजनिक तरीकों से निजी संस्करण को कॉल कर सकते हैं। उदाहरण के लिए, यदि आप चाहते थे (किसी भी कारण से) तो इसके लिए थोड़ा अलग तर्क होना चाहिए Localuserऔर RemoteUser(शायद दूरस्थ प्रवेश को चालू / बंद करने के लिए कोई सेटिंग है?):

public bool IsAdmin(Localuser user); // Just call private method
public bool IsAdmin(RemoteUser user); // Check if setting is on, then call private method
private bool IsAdmin(int id, string name, string password);

इसके अतिरिक्त, यदि किसी भी कारण से आपको निजी विधि को सार्वजनिक करने की आवश्यकता है ... तो आप कर सकते हैं। यह बस के रूप में बदलने के privateलिए आसान है public। यह इस मामले के लिए एक बड़ा लाभ की तरह प्रतीत नहीं हो सकता है, लेकिन कभी-कभी यह वास्तव में है।

इसके अलावा, जब यूनिट-परीक्षण आप अधिक परमाणु परीक्षण करने में सक्षम होंगे। इस पद्धति पर परीक्षण चलाने के लिए पूर्ण उपयोगकर्ता ऑब्जेक्ट बनाने के लिए आमतौर पर बहुत अच्छा नहीं है। और यदि आप पूर्ण कवरेज चाहते हैं, तो आप दोनों कॉल का परीक्षण कर सकते हैं।


0
public bool IsAdmin(int id, string name, string password);

सूचीबद्ध कारणों के लिए बुरा है। इसका मतलब यह नहीं

public bool IsAdmin(User user);

स्वचालित रूप से अच्छा है। विशेष रूप से यदि उपयोगकर्ता एक वस्तु की तरह तरीकों चल रहा है: getOrders(), getFriends(), getAdresses(), ...

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.