एमवीपी पैटर्न में यूआई सामग्री के आधार पर एक मॉडल ऑब्जेक्ट को देखें, या इन सामग्रियों को प्रस्तुतकर्ता के मापदंडों के रूप में पारित करें?


9

मैं एक एंड्रॉइड ऐप में एमवीपी पैटर्न का उपयोग कर रहा हूं जो मैं विकसित कर रहा हूं।

मेरे पास मूल रूप से 4 तत्व हैं:

  1. AddUserView जहां एक नया उपयोगकर्ता जोड़ा जा सकता है:
  2. AddUserPresenter
  3. UserInfo (पूजो)
  4. UserInfoManager (व्यस्तता तर्क और भंडारण प्रबंधक)

मेरा सवाल यह है कि:

जब मैं AddUserView में "Add" बटन दबाता हूं, तो उसे टेक्स्टव्यूज़ की सामग्री मिलनी चाहिए, एक नया UserInfo तुरंत करना चाहिए और इसे प्रस्तुतकर्ता को पास करना होगा। या AddUserView को केवल TextViews सामग्री प्राप्त करनी चाहिए और उन्हें AddUserPresenter में पास करना चाहिए, जो वास्तव में UserInfo को तुरंत भेज देगा और UserInfoManager को पास कर देगा?

जवाबों:


8

एमवीपी के मार्टिन फॉलर के विवरण के अनुसार ( http://martinfowler.com/eaaDev/uiArchs.html )

MVC के व्यू भाग में, फाउलर कहते हैं:

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

(बोल्ड जोर मेरा)

फिर प्रस्तुतकर्ता:

उपयोगकर्ता के कार्यों के लिए सक्रिय प्रतिक्रिया एक अलग प्रस्तुतकर्ता वस्तु में रहती है। उपयोगकर्ता के इशारों के लिए मौलिक हैंडलर अभी भी विगेट्स में मौजूद हैं, लेकिन ये हैंडलर केवल प्रस्तुतकर्ता को नियंत्रण देते हैं

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

(फिर से, बोल्ड जोर मेरा)

इसलिए, फाउलर के दिशानिर्देशों के अनुसार, बटन इवेंट के जवाब में किसी भी व्यवहार के लिए आपका दृष्टिकोण जिम्मेदार नहीं होना चाहिए; जिसमें एक उदाहरण बनाना शामिल है UserInfo। ऑब्जेक्ट बनाने का निर्णय लेने की जिम्मेदारी प्रस्तुतकर्ता विधि की है, जिसके लिए UI ईवेंट को अग्रेषित किया गया है।

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

MVP के साथ, यह एक इंटरफ़ेस को लागू करने के लिए दृश्य के लिए आम है जिसे प्रस्तुतकर्ता सीधे दृश्य से डेटा लेने के लिए उपयोग कर सकता है (जबकि यह सुनिश्चित करना कि प्रस्तुतकर्ता अभी भी दृश्य के लिए अज्ञेय है)। चूंकि UserInfo एक सरल POJO है, यह देखने के लिए एक का पर्दाफाश करने के लिए मान्य हो सकता गेटर UserInfo के लिए जो प्रस्तुतकर्ता एक इंटरफेस के माध्यम से देखें fron ले सकते हैं।

// The view would implement IView
public interface IView {

    public UserInfo GetUserInfo();
}

// Presenter
public class AddUserPresenter {

    private IView addUserView;

    public void SetView(IView view) {
        addUserView = view
    }

    public void onSomethingClicked() {

        UserInfo userInfo = addUserView.GetUserInfo();
        // etc.
    }
}

UserInfoइवेंट हैंडलर का उपयोग करके सीधे दृश्य में पास करने के लिए यह कैसे अलग है ? मुख्य अंतर यह है कि प्रस्तुतकर्ता अभी भी तर्क के लिए ज़िम्मेदार है जो किसी UserInfoवस्तु को बनाने का कारण बनता है । यानी ईवेंट प्रेजेंटर के निर्माण से पहले पहुंच गया UserInfo, जिससे प्रेजेंटर को निर्णय लेने की अनुमति मिल गई।

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

    private boolean IsUsernameValid() {
        String username = addUserView.GetUsername();
        return (username != null && !username.isEmpty());
    }

    public void onSomethingClicked() {            

        if (IsUsernameValid()) {
            UserInfo userInfo = addUserView.GetUserInfo();
            // etc.
        }
    }

वह तर्क प्रस्तुतकर्ता के अंदर रहता है, और उसे दृश्य में जोड़ने की आवश्यकता नहीं है। यदि दृश्य कॉलिंग के लिए जिम्मेदार था, GetUserInfo()तो इसके उपयोग के आसपास के किसी भी तर्क के लिए भी जिम्मेदार होगा; जो कि MVP पैटर्न से बचने की कोशिश कर रहा है।

तो जबकि विधि जो बनाता है कि UserInfoशारीरिक रूप से दृश्य वर्ग में मौजूद हो सकता है, इसे व्यू वर्ग से कभी नहीं बुलाया जाता है, केवल प्रस्तुतकर्ता से।

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

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


1
शानदार जवाब @BenCottrell! लेकिन मेरे पास एक और है :) क्या प्रस्तोता विधियों का नामकरण एक अच्छा अभ्यास है onSomethingClicked(), इसलिए जब उपयोगकर्ता "कुछ" पर क्लिक करता है, तो दृश्य कॉल करता है presenter.onSomethingClicked()? या मेरे प्रस्तोता तरीकों का इरादा कार्रवाई, मेरे मामले में के रूप में नामित किया जाना चाहिए addUser()?
रौमूल.ईडु

1
@regmoraes अच्छा सवाल; और मुझे लगता है कि आपने मेरे उदाहरण कोड में एक मामूली गंध को उजागर किया है । Presenterडोमेन तर्क यूआई तर्क के बजाय के लिए पाठ्यक्रम जिम्मेदार है, और विशेष रूप से अनुरूप Viewहै, इसलिए अवधारणाओं जो मौजूद होना चाहिए, यूआई अवधारणाएं हैं, तो एक विधि नामित onSomethingClicked()वास्तव में उचित है। दृष्टिहीनता के साथ, ऊपर मैंने अपने उदाहरण में जो नामकरण चुना है, वह बिल्कुल सही गंध नहीं है :-)।
बेन कॉटरेल

@BenCottrell सबसे पहले महान जवाब के लिए बहुत धन्यवाद। मैं समझता हूं, यह GetUserInfoविधि इस दृष्टि से मान्य है जैसा आपने उल्लेख किया है (प्रस्तुतकर्ता से ट्रिगर किया जाएगा) विधि के ifअंदर की संभावित स्थितियों के बारे में क्या GetUserInfo? हो सकता है कि UserInfo के कुछ क्षेत्र उपयोगकर्ता प्रतिक्रिया के माध्यम से सेट किए जाएंगे? एक परिदृश्य: शायद उपयोगकर्ता एक चेक बॉक्स का चयन करता है तो कुछ नए घटक (एक नया EditText शायद) उपयोगकर्ता को दिखाई देंगे। तो उस स्थिति में, GetUserInfoविधि की स्थिति होगी। इस परिदृश्य GetUserInfoमें अभी भी मान्य है?
कालाकार

1
@ ब्लेककारा UserInfoएक मॉडल-ऑफ-द-व्यू (उर्फ "मॉडल देखें") के रूप में व्यवहार करने पर विचार करें - उस परिदृश्य में मैं booleanचेक बॉक्स की Stringस्थिति और टेक्स्ट बॉक्स की खाली / अशक्त स्थिति को जोड़ दूंगा UserInfo। आप इसका नाम बदलने पर भी विचार कर सकते हैं UserInfoViewModelयदि POJO के वर्ग के रूप में सोचने में मदद मिलती है, जिसका एकमात्र वास्तविक उद्देश्य UserInfoPresenterव्यू स्टेट के बारे में जानकारी प्राप्त करना है।
बेन कॉटरेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.