डिजाइन पैटर्न और ओओपी प्रथाओं पर सोच गतिशील और कमजोर टाइप की भाषाओं में कैसे बदलती है?


11

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

यह है: मान लें कि मैं कई वर्षों से C ++, C #, या Java में प्रोग्रामिंग कर रहा हूं, और GoF डिजाइन पैटर्न, Fowler के पैटर्न ऑफ एंटरप्राइज एप्लीकेशन आर्किटेक्चर , SOLID सिद्धांतों , आदि की तर्ज पर बहुत सारे ज्ञान को अवशोषित कर रहा हूं। रूबी, पायथन, जावास्क्रिप्ट, आदि में m dbbling, और सोच रहा था कि मेरा ज्ञान कैसे लागू होता है। संभवतः मैं कई मामलों में सीधे अनुवाद कर सकता था, लेकिन लगभग निश्चित रूप से यह मेरी नई सेटिंग का पूरा फायदा नहीं उठाएगा। अकेले डक टाइपिंग मेरे इंटरफ़ेस-आधारित सोच का एक बहुत कुछ बदल जाता है।

क्या वही रहता है? कौन सा शुल्क? क्या सॉलिड, या विहित पैटर्न (शायद पूरी तरह से नए) जैसे मार्गदर्शक सिद्धांत हैं जो एक गतिशील भाषा नौसिखिया जानना चाहिए?

जवाबों:


7

क्या वही रहता है? कौन सा शुल्क?

पैटर्न समान हैं। भाषा तकनीक बदल जाती है।

क्या सॉलिड जैसे मार्गदर्शक सिद्धांत हैं,

हाँ। दरअसल, वे मार्गदर्शक सिद्धांत बने हुए हैं। कुछ नहीं बदलता है।

या विहित पैटर्न (शायद पूरी तरह से नए) जो एक गतिशील भाषा नौसिखिया जानना चाहिए?

कुछ चीजें अनोखी हैं। अधिकतर प्रभाव यह है कि कार्यान्वयन तकनीकों में परिवर्तन होता है।

एक पैटर्न है - अच्छी तरह से - एक पैटर्न । कानून नहीं। सबरूटीन नहीं है। स्थूल नहीं। यह सिर्फ एक अच्छा विचार है जो दोहराया जाता है क्योंकि यह एक अच्छा विचार है।

अच्छे विचार शैली से बाहर नहीं जाते हैं या नाटकीय रूप से बदलते हैं।

अन्य नोट। अजगर "कमजोर टाइप" नहीं है। यह जावा या C ++ की तुलना में अधिक दृढ़ता से टाइप किया गया है क्योंकि कोई कास्ट ऑपरेशन नहीं है। [हाँ, एक वस्तु से जुड़े वर्ग को ठगने का एक तरीका है, लेकिन यह एक प्रकार की चीज नहीं है, जो एक उधम मचाते, कानूनी बिंदु को साबित करने के अलावा है।]

इसके अलावा। अधिकांश डिजाइन पैटर्न बहुरूपता का फायदा उठाने के विभिन्न तरीकों पर आधारित हैं।

उदाहरण के तौर पर स्टेट या कमांड या मेमेंटो को देखें। राज्य परिवर्तन के लिए एक बहुरूपी राज्य, कमांड या स्मृति चिन्ह बनाने के लिए उनके पास श्रेणी पदानुक्रम हैं। जब आप पायथन में ऐसा करते हैं तो कुछ भी नहीं बदलता है। मामूली बदलावों में सटीक वर्ग पदानुक्रम की छूट शामिल है क्योंकि पायथन में बहुरूपता आम तरीकों पर निर्भर करता है न कि सामान्य पूर्वजों।

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

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


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

@ मेसन व्हीलर। ओपन-क्लोज्ड मेरे अनुभव में स्वतंत्र भाषा है। आपको जावास्क्रिप्ट या गो के साथ खुले-बंद डिज़ाइन "अर्थहीन" होने के कुछ और ठोस उदाहरण प्रदान करने होंगे। Liskov प्रतिस्थापन, शायद, जावास्क्रिप्ट पर लागू नहीं होता है, लेकिन आवश्यक पैटर्न - बहुरूपता - अभी भी लागू होता है।
S.Lott

@ S.Lott: संपादन में अच्छा अपडेट; वे मूल उत्तर की तुलना में बहुत अधिक दिलचस्प थे: पी। मेरी पायथन गलती को सुधारने के लिए धन्यवाद। सामान्य तौर पर विशिष्ट पैटर्न के उदाहरण और वे कैसे गतिशील भाषाओं में बाँधते हैं, बहुरूपता, देर से बाध्यकारी, आदि परिपूर्ण हैं।
डोमनिक

@ एस.लॉट: क्योंकि ओपन / क्लोज इनहेरिटेंस के बारे में है, जो उन भाषाओं में नहीं है। (इसके अलावा, किसी वस्तु के "संशोधन के लिए बंद" होने का विचार रूबी कोडर्स के साथ अच्छी तरह से नहीं बैठेगा ...)
मेसन व्हीलर

@ मेसन व्हीलर: ओपन / बंद पर स्पष्टीकरण के लिए धन्यवाद। मुझे लगता है कि जावास्क्रिप्ट अपवाद महत्वपूर्ण है, लेकिन चूंकि प्रश्न इतना खुला है (जावास्क्रिप्ट, पायथन और रूबी को सूचीबद्ध करना, साथ ही साथ ईटीसी नामक भाषा) मुझे यकीन नहीं है कि विशेष मामले को कैसे संबोधित किया जाए।
एस.लॉट

8

पीटर Norvig के 1998 में यह बहुत ही सवाल पर ले लिया है, पढ़ा http://norvig.com/design-patterns/ppframe.htm विस्तृत बातें उसने देखा का एक सेट के लिए, और http://c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatures के लिए बिंदु के आसपास आगे की चर्चा।

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


8

एक गतिशील वस्तु उन्मुख भाषा में प्रोग्रामिंग कई समान पैटर्न और सिद्धांतों का उपयोग करता है, लेकिन पर्यावरण के कारण कुछ निश्चित मोड़ और अंतर हैं:

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

कार्य वस्तुएं भी हैं - बहुत सारे पैटर्न हैं जो कार्रवाई से निर्णय को अलग करने के बारे में हैं; कमान, रणनीति, जिम्मेदारी की श्रृंखला, आदि प्रथम श्रेणी के कार्यों के साथ एक भाषा में, अक्सर .doIt()तरीकों से ऑब्जेक्ट बनाने के बजाय केवल एक फ़ंक्शन पास करना उचित होता है । ये पैटर्न "उच्च क्रम फ़ंक्शन का उपयोग करते हैं" में बदल जाते हैं।

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

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


3

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

एक सृजनात्मक प्रतिमान स्थापित करने के बजाय यह अक्सर एक कॉल करने योग्य पास करने के लिए पर्याप्त है जो ऑब्जेक्ट बनाता है। यह एक कार्य हो सकता है, एक __call__विधि या एक वर्ग के साथ एक वस्तु , क्योंकि new()पायथन में कोई भी नहीं है, केवल कक्षा का एक आह्वान:

def make_da_thing(maker, other, stuff):
    da_thing = maker(other + 1, stuff + 2)
    # ... do sth
    return da_thing

def maker_func(x, y):
     return x * y

class MakerClass(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
...
a = make_da_thing(maker_func, 5, 8)
b = make_da_thing(MakerClass, 6, 7)

राज्य और रणनीति पैटर्न सी ++ और जावा जैसी भाषाओं में एक समान संरचना साझा करते हैं। पायथन में इतना कम। रणनीति पैटर्न कमोबेश एक जैसा रहता है, लेकिन स्टेट पैटर्न ज्यादातर अनावश्यक हो जाता है। स्टेटिक भाषाओं में स्टेट पैटर्न, रनटाइम पर क्लास के बदलाव का अनुकरण करता है। पायथन में, आप बस इतना कर सकते हैं: रनटाइम पर किसी ऑब्जेक्ट की क्लास बदलें। जब तक आप इसे नियंत्रित, संक्षिप्त तरीके से करते हैं, तब तक आपको ठीक होना चाहिए:

class On(object):
    is_on = True
    def switch(self):
        self.__class__ = Off

class Off(object):
    is_on = False
    def switch(self):
        self.__class__ = On
...

my_switch = On()
assert my_switch.is_on
my_switch.switch()
assert not my_switch.is_on

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

class Visitable(object):
    def accept(self, visitor):
        visit = getattr(visitor, 'visit' + self.__class__.__name__)
        return visit(self)
...

class On(Visitable):
    ''' exactly like above '''

class Off(Visitable):
    ''' exactly like above '''

class SwitchStatePrinter(object): # Visitor
    def visitOn(self, switch):
         print 'the switch is on'
    def visitOff(self, switch):
         print 'the switch is off'

class SwitchAllOff(object): # Visitor
    def visitOn(self, switch):
         switch.switch()
    def visitOff(self, switch):
         pass
...
print_state = SwitchStatePrinter()
turn_em_off = SwitchAllOff()
for each in my_switches:
    each.accept(print_state)
    each.accept(turn_em_off)

कई स्थितियाँ जो स्टैटिक लैंग्वेज में एक पैटर्न के आवेदन के लिए कहती हैं, वे पायथन में उतनी नहीं हैं। कई चीज़ों को अन्य आदेशों के साथ हल किया जा सकता है, जैसे कि उच्च ऑर्डर फ़ंक्शंस (सज्जाकार, फ़ंक्शन फ़ैक्टरी) या मेटा क्लास।


मुझे अब पता चला है कि आपके उत्तर में मेरे द्वारा पूछे गए प्रश्न को शामिल किया गया है: क्या पायथन में कारखाने को लागू करने के लिए ओवरराइटिंग__class__ एक अच्छा विचार है?
आरडीएस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.