2012-06-13 7 views
15

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

तो मैं इस QueryBuilder वर्ग

class QueryHelper(): 
    """ 
    Help abstract out the problem of querying over vastly 
    different dataschemas. 
    """ 

    def __init__(self, collection_name, field_name, params_dict): 
     self.query_dict = {} 
     self.params_dict = params_dict 
     db = connection.get_db() 
     self.collection = db[collection_name] 

    def _build_query(self): 
     # check params dict and build a mongo query 
     pass 

अब _build_query में मैं परम dict जाँच की जाएगी और query_dict तो पॉप्युलेट के रूप में यह के मोंगो को find() समारोह पारित करने के लिए की है। ऐसा करने में मैं बस सोच रहा था कि _build_query को एक शब्दकोश वापस करना चाहिए या फिर इसे self.query_dict संशोधित करना चाहिए या नहीं। चूंकि यह एक आंतरिक विधि है, इसलिए मुझे लगता है कि self.query_dict को संशोधित करना ठीक है। क्या इस पर पहुंचने का कोई सही तरीका (पायथनिक) तरीका है ?? क्या यह सिर्फ मूर्ख है और एक महत्वपूर्ण डिजाइन निर्णय नहीं है ?? किसी भी मदद की सराहना की है। धन्यवाद।

उत्तर

4

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

class QueryHelper(object): 
    def __init__(self, param, text): 
     self._param = param 
     self._query = self._build_query(text) 

    def _build_query(self, text): 
     return text + " and ham!" 

class RefinedQueryHelper(QueryHelper): 
    def _build_query(self, text): 
     # no need to know how the query object is going to be used 
     q = super(RefinedQueryHelper, self)._build_query() 
     return q.replace("ham", "spam") 

बनाम "सेटर संस्करण": यहाँ एक उदाहरण है

class QueryHelper(object): 
    def __init__(self, param, text): 
     self._param = param 
     self._build_query(text) 

    def _build_query(self, text): 
     self._query = text + " and ham!" 

class RefinedQueryHelper(QueryHelper): 
    def _build_query(self, text): 
     # what if we want to store the query in __query instead? 
     # then we need to modify two classes... 
     super(RefinedQueryHelper, self)._build_query() 
     self._query = self._query.replace("ham", "spam") 

आप एक विशेषता सेट करने के लिए चयन करते हैं, तो आप स्पष्टता के लिए विधि _set_query कॉल करने के लिए चाहते हो सकता है।

9

ऑब्जेक्ट उन्मुख प्रोग्रामिंग के पूरे विचार के रूप में self.query_dict को संशोधित करना बिल्कुल ठीक है, यह तरीका किसी ऑब्जेक्ट की स्थिति को संशोधित कर सकता है। एक विधि समाप्त होने के बाद जब तक एक वस्तु एक सतत स्थिति में है, तो आप ठीक हैं। तथ्य यह है कि _build_query एक आंतरिक विधि है इससे कोई फर्क नहीं पड़ता। ऑब्जेक्ट बनने पर पहले से ही क्वेरी बनाने के लिए आप __init__ में _build_query पर कॉल करना चुन सकते हैं।

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

6

यदि आप कुछ भी वापस लौटते हैं, तो मैं self का सुझाव दूंगा। उदाहरण के तरीकों से लौटते self, विधि श्रृंखलन के लिए सुविधाजनक है, क्योंकि प्रत्येक वापसी मान एक ही वस्तु पर एक और विधि कॉल की अनुमति देता है:

foo.add_thing(x).add_thing(y).set_goal(42).execute() 

यह कभी कभी एक "धाराप्रवाह" एपीआई के रूप में जाना जाता है।

हालांकि, अजगर ऐसे int और str के रूप में अपरिवर्तनीय प्रकार के लिए विधि श्रृंखलन की अनुमति देता है, जबकि, यह इस तरह के list और set के रूप में अस्थायी कंटेनरों के तरीकों के लिए प्रदान नहीं करता है -by डिजाइन तो यह यकीनन नहीं "pythonic" यह करने के लिए है अपने खुद के परिवर्तनीय प्रकार के लिए। फिर भी, पाइथन पुस्तकालयों के बहुत सारे "धाराप्रवाह" एपीआई हैं।

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

+1

'.execute()' अनावश्यक है। आप '.all()', '.irst() ',' .one() 'का उपयोग करके निष्पादन को ट्रिगर कर सकते हैं। – jfs

+0

निश्चित रूप से, यह अच्छा है यदि आपके पास एक से अधिक विधि हैं जो वास्तव में कुछ करती हैं। – kindall

2

हालांकि यह आम है एक वस्तु के तरीकों सीधे अपने राज्य को संशोधित करने के लिए, यह कभी कभी लाभप्रद एक वस्तु का अपना 'ग्राहक' होने के लिए, और (आमतौर पर) निजी उपयोग तरीकों के माध्यम से परोक्ष रूप से खुद को पहुँचने के लिए हो सकता है।

ऐसा बेहतर कैप्सूलीकरण और लाभ यह है कि से पालन करती है। हालांकि ऐसा करना अव्यवहारिक हो सकता है क्योंकि इसे बहुत अधिक अतिरिक्त कोड की आवश्यकता होती है, और अक्सर धीमी होती है जो प्रदर्शन को एक अस्वीकार्य राशि को प्रतिकूल रूप से प्रभावित कर सकती है - इसलिए व्यापार-बंद आदर्श के साथ किया जाना चाहिए।

संबंधित मुद्दे