यह कैसे निर्धारित किया जाए कि अपने संबंधित नियंत्रक को क्या मिलना चाहिए?


10

मैं PHP के साथ निर्मित अपने वेब एप्लिकेशन में एमवीसी पैटर्न का उपयोग कर रहा हूं।

मैं हमेशा यह निर्धारित करने के लिए संघर्ष कर रहा हूं कि क्या मुझे कार्यों के एक सेट के लिए एक नए समर्पित नियंत्रक की आवश्यकता है या यदि मुझे उन्हें पहले से मौजूद नियंत्रक के अंदर रखना चाहिए।

नियंत्रक बनाते समय क्या अंगूठे के कोई अच्छे नियम हैं?

उदाहरण के लिए मेरे पास हो सकता है:

AuthenticationController क्रियाओं के साथ:

  • index() प्रदर्शन फ़ॉर्म प्रदर्शित करने के लिए।
  • submit() फार्म जमा करने के लिए।
  • logout(), स्व-व्याख्यात्मक।

या

LoginController क्रियाओं के साथ:

  • index() प्रदर्शन फ़ॉर्म प्रदर्शित करने के लिए।
  • submit() फार्म जमा करने के लिए।

LogoutController कार्रवाई के साथ:

  • index() लॉगिंग से निपटने के लिए।

या

AccountController क्रियाओं के साथ:

  • loginGet() प्रदर्शन फ़ॉर्म प्रदर्शित करने के लिए।
  • loginPost() लॉगिन फ़ॉर्म सबमिट करने के लिए।
  • logoutGet() लॉगिंग से निपटने के लिए।
  • registerGet() पंजीकरण फार्म प्रदर्शित करने के लिए।
  • registerPost() फार्म जमा करने के लिए।

    और किसी भी अन्य कार्यों को एक खाते के साथ शामिल किया गया है।


शायद Restful डिजाइन पर एक नज़र है। यह इस तरह की हर समस्या को हल नहीं करता है, लेकिन आपको इस बारे में सोचने के लिए एक बहुत अच्छी दिशा देता है।
थरस्टेन मुलर

जवाबों:


3

नियंत्रकों के लिए सही समूह का पता लगाने के लिए, परीक्षण के बारे में सोचें

(यहां तक ​​कि अगर आप वास्तव में कोई परीक्षण नहीं करते हैं, तो यह सोचकर कि आप अपने नियंत्रकों के परीक्षण के बारे में कैसे जाएंगे, आपको उन्हें संरचना के बारे में कुछ बहुत अच्छी अंतर्दृष्टि प्रदान करेगा।)

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

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

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

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

और आम तौर पर, "परीक्षण के बारे में सोचें" दृष्टिकोण न केवल इस विशेष परिदृश्य में काम करेगा, बल्कि भविष्य में आपके सामने आने वाले किसी भी समान परिदृश्य में भी काम करेगा।


1

उत्तर स्पष्ट नहीं है

कृपया मुझे कुछ बातें स्पष्ट करने दें, इससे पहले कि मैं कोई जवाब देने वाला बयान दूं। सबसे पहले:

नियंत्रक क्या है?

नियंत्रक प्रणाली का एक हिस्सा है जो अनुरोध को भेजने के बाद - को नियंत्रित करता है । इस प्रकार, हम इसे ... से संबंधित कुछ क्रियाओं के रूप में परिभाषित कर सकते हैं ... क्या?

नियंत्रक की गुंजाइश क्या है?

और जब हम कोई जवाब देंगे तो कम या ज्यादा हिस्सा। तुम क्या सोचते हो? क्या यह चीजों का नियंत्रक है (उदाहरण के लिए खाता) या क्रियाओं का नियंत्रक? बेशक इसके कुछ मॉडल या कुछ और अमूर्त चीज के एक नियंत्रक है जो उस पर कार्रवाई प्रदान करता है।

उत्तर है...

कार्यों के साथ प्रमाणीकरणकंट्रोलर:

  • अनुक्रमणिका () लॉगिन फ़ॉर्म प्रदर्शित करने के लिए।
  • सबमिट करें () फ़ॉर्म सबमिट करने के लिए।
  • लॉगआउट (), स्व-व्याख्यात्मक।

नाह, प्रमाणीकरण एक प्रक्रिया है। इस तरह मत जाओ।

कार्यों के साथ LoginController:

  • अनुक्रमणिका () लॉगिन फ़ॉर्म प्रदर्शित करने के लिए।
  • सबमिट करें () फ़ॉर्म सबमिट करने के लिए।

मुझे भी। लॉगिन - क्रिया। बेहतर है कि एक्शन कंट्रोलर न बनाएं (आपके पास इसका सहसंबंधित मॉडल नहीं है)।

क्रियाओं के साथ खाता नियंत्रक:

  • loginGet () लॉगिन फॉर्म प्रदर्शित करने के लिए।
  • loginPost () लॉगिन फॉर्म सबमिशन को संभालने के लिए।
  • logoutGet () लॉगिंग आउट को संभालने के लिए।
  • पंजीकरण फॉर्म प्रदर्शित करने के लिए registerGet ()।
  • फार्म जमा करने के लिए रजिस्टरपोस्ट ()।

काफी अच्छा है, लेकिन मुझे यकीन नहीं है कि निम्न-स्तरीय नियंत्रक (नियंत्रक अपने आप में अमूर्त है) का निर्माण करने लायक है। वैसे भी, * Get या * Post के साथ तरीके बनाना अस्पष्ट हैं।

कोई उपाय?

हाँ, इस पर विचार करें:

AccountController:

  • लॉगिन (AccountModel)
  • लॉगआउट (AccountModel)
  • रजिस्टर (AccountModel)
  • इंडेक्स ()

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


1

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

class SecurityController
{
    // can handle both the login page display and
    // the login page submission
    login(); 

    logout();

    register();

    // optional: confirm account after registration
    confirm();

    // displays the forgot password page
    forgotPassword();

    // displays the reset password page
    // and handle the form submission
    resetPassword();
}

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

संसाधनों के लिए बनाए गए नियंत्रकों के साथ (मान लें Task), आपके पास सामान्य CRUD क्रियाएं होंगी :

class TasksController
{
    // usually displays a paginated list of tasks
    index();

    // displays a certain task, based on an identifier
    show(id);

    // displays page with form and
    // handles form submission for creating
    // new tasks
    create();

    // same as create(), but for changing records
    update(id);     

    // displays confirmation message
    // and handles submissions in case of confirmation
    delete()
}

बेशक, आपके पास संबंधित संसाधनों को एक ही नियंत्रक में जोड़ने की संभावना है। उदाहरण के लिए कहें कि आपके पास इकाई है Business, और प्रत्येक के पास कई BusinessServiceसंस्थाएं हैं। इसके लिए एक नियंत्रक इस तरह दिख सकता है:

class BusinessController
{
    index();

    show(id);

    create();

    update(id);

    delete();

    // display the business services for a certain business
    listBusinessServices(businessId);

    // displays a certain business service
    showBusinessService(id);

    // create a new business service for a certain business
    createBusinessService(businessId);

    // updates a certain business service
    updateBusinessService(id);

    // deletes a certain business service
    deleteBusinessService(id);
}

यह दृष्टिकोण समझ में आता है जब संबंधित बच्चे संस्थाएं मूल संस्था के बिना मौजूद नहीं हो सकती हैं।

ये मेरी सिफारिशें हैं:

  • संबंधित ऑपरेशनों के एक समूह (सुरक्षा, या संसाधनों पर सीआरयूडी संचालन जैसे कुछ जिम्मेदारियों को संभालना) के आधार पर नियंत्रक बनाएं;
  • संसाधन-आधारित नियंत्रकों के लिए, अनावश्यक क्रियाओं को न जोड़ें (यदि आप संसाधन को अद्यतन नहीं करने वाले हैं, तो अद्यतन क्रिया को न जोड़ें);
  • आप चीजों को सरल बनाने के लिए "कस्टम" क्रियाएं जोड़ सकते हैं (जैसे Subscriptionकि आपके पास एक इकाई है जिसमें सीमित संख्या में प्रविष्टियों के आधार पर उपलब्धता है, आप नियंत्रक के लिए एक नई कार्रवाई जोड़ सकते हैं जिसका नाम use()है एक प्रविष्टि को घटाने का एक ही उद्देश्य है Subscription)
  • चीजों को सरल रखें - बड़ी संख्या में कार्यों और जटिल तर्क के साथ अपने नियंत्रक को अव्यवस्थित न करें, कार्यों की संख्या कम करके या दो नियंत्रक बनाकर चीजों को सरल बनाने का प्रयास करें;
  • यदि आप MVC केंद्रित ढांचे का उपयोग कर रहे हैं, तो उनके सर्वोत्तम-अभ्यास दिशानिर्देशों का पालन करें (यदि उनके पास है)।

आगे पढ़ने के लिए कुछ संसाधनों यहाँ


0

मैं दो विरोधी डिज़ाइन "बलों" को देखता हूं (जो नियंत्रकों के लिए अनन्य नहीं हैं):

  • सामंजस्य - नियंत्रकों को समूह से संबंधित कार्रवाई करनी चाहिए
  • सादगी - नियंत्रकों को उनकी जटिलता को प्रबंधित करने के लिए जितना संभव हो उतना छोटा होना चाहिए

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

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

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

BTW, आपका कोड बताता है कि आप GET अनुरोध के साथ उपयोगकर्ता को लॉग आउट कर रहे हैं। यह एक बुरा विचार है क्योंकि HTTP GET को अशक्त होना चाहिए (इसे एप्लिकेशन की स्थिति को संशोधित नहीं करना चाहिए)।


0

यहाँ अंगूठे के कुछ नियम दिए गए हैं:

  • विषय या विषय द्वारा व्यवस्थित करें, नियंत्रक नाम विषय का नाम है।

  • याद रखें कि URL में नियंत्रक का नाम आपके उपयोगकर्ताओं को दिखाई देगा, इसलिए अधिमानतः यह उनके लिए समझ में आना चाहिए।

जिस स्थिति का आप उल्लेख करते हैं (प्रमाणीकरण) एमवीसी टीम ने पहले ही आपके लिए नियंत्रक लिखा है। विजुअल स्टूडियो 2013 खोलें और फिर क्लिक करें

File / New / Project... 
Search installed templates for "ASP.NET MVC4 Web Application"
Choose "Internet Application" / OK.

AccountController.cs में उपयोगकर्ता खातों के प्रबंधन के लिए सभी तरीके हैं:

Login()
Logoff()
Register()
Disassociate()
Manage()
ExternalLogin()

इसलिए उन्होंने विषय "उपयोगकर्ता खाते और प्रमाणीकरण", दृश्यमान विषय नाम "खाता" के साथ आयोजित किया है।


0

शब्दावली

मेरा मानना ​​है कि कुछ HTTP से संबंधित विधियों को "नियंत्रक" कहे जाने वाले वर्ग को कॉल करना एक बड़ी गलत धारणा है।

नियंत्रक एक ऐसी विधि है जो अनुरोध को संभालती है, लेकिन इस तरह के तरीकों से युक्त वर्ग नहीं । तो, index(), submit(), logout()नियंत्रकों हैं।

उस तरह के तरीकों से युक्त क्लास को "नियंत्रक" नाम दिया गया है, क्योंकि यह नियंत्रकों के एक समूह का गठन करता है, और "नीचे-स्तर" नाम स्थान की भूमिका निभा रहा है। एफपी भाषा में (हास्केल की तरह) यह सिर्फ एक मॉड्यूल होगा। सेवाओं और अन्य प्रोग्राम-व्यापी सामान के संदर्भ को छोड़कर, उन "कंट्रोलर" वर्गों को ओओपी भाषाओं में जितना संभव हो सके, स्टेटलेस रखना संभव है।

उत्तर

शब्दावली के आधार पर, सवाल यह है कि "हमें नियंत्रकों को नामस्थान / मॉड्यूल में कैसे अलग करना चाहिए?" मुझे लगता है कि इसका उत्तर है: एकल नाम स्थान / मॉड्यूल के अंदर नियंत्रकों को एक ही तरह के डेटा से निपटना चाहिए । उदाहरण के लिए, मुख्य रूप से वर्ग के उदाहरणों के साथ UserControllerव्यवहार करता है , लेकिन कभी-कभी आवश्यकता होने पर अन्य संबंधित चीजों को छूता है।User

चूंकि login, logoutऔर इस तरह की अन्य क्रियाएं ज्यादातर सत्र के साथ काम कर रही हैं, इसलिए संभवत: उन्हें अंदर रखना सबसे अच्छा है SessionController, और indexनियंत्रक, जो सिर्फ एक फॉर्म प्रिंट करता है, को रखा जाना चाहिए LoginPageController, क्योंकि यह स्पष्ट रूप से लॉगिन पेज के साथ काम करता है। HTML रेंडरिंग और सेशन मैनेजमेंट को एक ही क्लास में रखना थोड़ा समझ में आता है, और वह SRP और शायद अन्य अच्छे व्यवहारों का एक गुच्छा होगा।

सामान्य सिद्धांत

जब आपको यह तय करने में परेशानी हो रही है कि कोड का एक टुकड़ा कहां रखा जाए, तो डेटा (और प्रकार) से शुरू करें, जिनसे आप निपटते हैं।


2
क्षमा करें, वे क्रियाएँ हैं, न कि नियंत्रक :)
JK01

@ JK01 वे हैं जिन्हें आप उन्हें कहते हैं। यह शब्दावली है, आप जानते हैं। और ऐसे फ्रेमवर्क हैं जो उन फ़ंक्शन को "नियंत्रक" (या "हैंडलर") कहते हैं, क्योंकि कई फ्रेमवर्क हैं जो उन वर्गों में व्यवस्थित नहीं करते हैं, क्योंकि नामस्थान / मॉड्यूल पहले से ही पर्याप्त हैं। आप अपनी पसंद के किसी भी शब्द का उपयोग कर सकते हैं, यह सिर्फ शब्द हैं, लेकिन मुझे लगता है कि कम शब्द होना बेहतर है।
पटकथा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.