if
. की वह विशाल गड़बड़ी बयान आपको चेहरे पर घूरते रहते हैं। आपको ऐसा लगता है कि आपको चाहिए इसे सरल बनाने में सक्षम हो, सिवाय उस व्यावसायिक तर्क के जो बीच में आता रहता है।
उदाहरण के लिए, मान लें कि आपके पास एक बिक्री मंच है जहां आप Quote
बनाते हैं s, जिसमें कई LineItem
हैं एस। इसके अलावा, आपके पास डुप्लीकेट लाइन आइटम के साथ एक कोट हो सकता है यदि वे विज्ञापन . हैं , लेकिन यदि आपके पास एकाधिक वेबसाइट हैं , आपको कीमतों को एक साथ जोड़ना होगा और इसे एक पंक्ति वस्तु के रूप में दिखाना होगा। ओह और साथ ही, यदि आप एक वेबसाइट खरीदते हैं और आपके उद्धरण में पहले से ही पांच विज्ञापन हैं, तो आपको उन्हें वेबसाइट पर 20% की छूट देनी होगी।
मैं आपको यहां से खिड़की से अपना लैपटॉप फेंकते हुए सुन सकता हूं।
आप कर सकते थे if
. का एक गुच्छा लिखें इन नियमों को संभालने के लिए बयान:
class Quote
attr_accessor :line_items
...
def add_line_item(line_item)
if line_item.kind_of?(Ad)
self.line_items << line_item
elsif line_item.kind_of?(Website)
if @line_items.select {|item| item.kind_of?(Ad) }.length >= 5
# TODO: Put the fractions of a cent into a bank account
# I have set up
line_item.price *= 0.8
end
existing_website = self.line_items.detect { |item| item.kind_of?(Website) }
if existing_website
existing_website.price += line_item.price
else
self.line_items << line_item
end
end
end
end
लेकिन मुझे लगता है कि हम सहमत हो सकते हैं कि यह बहुत ही भयानक है। आप किसी ऐसी चीज को कैसे सुलझा सकते हैं?
आप इस विधि को छोटे-छोटे तरीकों के एक समूह में विघटित कर सकते हैं, लेकिन यह आपके सभी खिलौनों को अपनी अलमारी में रखने जैसा है, ताकि आपकी माँ को लगे कि आपने अपना कमरा साफ कर लिया है। और वो kind_of?
s अभी भी मुझे बहुत परेशान करेंगे।
लेकिन क्या होगा यदि आपको पंक्ति वस्तु . से चीज़ें दिखाई देने लगे परिप्रेक्ष्य, उद्धरण के बजाय? अगर पूछने के बजाय आप किस प्रकार के लाइन आइटम के साथ काम कर रहे हैं और उसे कोट में जोड़ रहे हैं, आपने अभी बताया जोड़ने के लिए पंक्ति वस्तु स्वयं बोली के लिए?
अपनी विधियों को उलट दें!
कोड को रिफैक्टर करने के मेरे पसंदीदा तरीकों में से एक है कॉल करने वाले और कॉल करने वाले को उलटने का प्रयास करना। ऊपर दिए गए कोड का उपयोग करके यहां एक उदाहरण दिया गया है:
class Quote
...
def add_line_item(line_item)
line_item.add_to_quote(self)
end
end
class Ad < LineItem
...
def add_to_quote(quote)
quote.line_items << self
end
end
class Website < LineItem
def add_to_quote(quote)
if quote.line_items.select {|item| item.kind_of?(Ad) }.length >= 5
# TODO: Put the fractions of a cent into a bank account
# I have set up
self.price *= 0.8
end
existing_website = quote.line_items.detect { |item| item.kind_of?(Website) }
if existing_website
existing_website.price += self.price
else
quote.line_items << self
end
end
end
यह संपूर्ण नहीं है। website.rb
अभी भी एक बहुत कुछ की आवश्यकता है रिफैक्टरिंग मदद की, और मैं इस बात से खुश नहीं हूं कि कैसे उलटने के तरीकों ने line_items
के एनकैप्सुलेशन को तोड़ दिया ।
लेकिन आपने जटिलता की पहली परत हटा दी है। अब आप LineItem
. पर कोड डाल सकते हैं या Quote
, इस पर निर्भर करता है कि यह सबसे अधिक कहां समझ में आता है। LineItem
ऑब्जेक्ट प्रत्येक LineItem
. के बीच समानता और अंतर को संभालने के लिए इनहेरिटेंस और मिक्सिन का उपयोग कर सकते हैं उपवर्ग साथ ही, अब नया LineItem
add जोड़ना वाकई आसान हो गया है अपने add_line_item
. को ब्लो किए बिना उपवर्ग विधि।
आपका कोड थोड़ा साफ है, और बहुत अधिक लचीला है। तो आम तौर पर, मैं इसे जीत कहूंगा।
जहां आप शायद इस पैटर्न का उपयोग नहीं करना चाहें
उलटने का तरीका जितना उपयोगी है है, ऐसे कुछ कारण हैं जिनकी वजह से आप इस पैटर्न का उपयोग नहीं करना चाहेंगे:
-
यह इनकैप्सुलेशन को तोड़ सकता है। आपको
Quote
. पर विशेषताओं को उजागर करना पड़ सकता है जिसे आप सार्वजनिक रूप से उजागर नहीं करना चाहते थे। -
यह युग्मन बढ़ा सकता है। दोनों
Quote
औरAd
अब एक दूसरे के बारे में जानने की जरूरत है। और कितना कितना . पर निर्भर करता है उन्हें एक दूसरे के बारे में जानने की जरूरत है, यह आपके कोड को अधिक बना सकता है जटिल। -
यह
Ad
पर एकल उत्तरदायित्व सिद्धांत का उल्लंघन कर सकता है , क्योंकि अबAd
यह जानने की जिम्मेदारी है कि खुद कोQuote
. में कैसे जोड़ा जाए ।
आप आमतौर पर इन समस्याओं के आसपास काम कर सकते हैं। लेकिन आपको उनके बारे में पता होना चाहिए, क्योंकि आप अपने कोड को बदतर! बनाने के लिए रिफैक्टरिंग नहीं चाहते हैं!
यह मेरे पसंदीदा में से एक क्यों है
उन समस्याओं के साथ भी, यह मेरी पसंदीदा रिफैक्टरिंग में से एक है। इस पैटर्न का उपयोग करने के बाद मैं जो कोड लिखता हूं वह स्पष्ट और अधिक आत्मविश्वासी होता है।
लेकिन ऐसा न होने पर भी, इस पैटर्न का उपयोग करने से मैं अपनी वस्तुओं के बीच संबंधों के बारे में अलग तरीके से सोचता हूं। जब मैं "यह सुविधा भयानक है, मुझे विश्वास नहीं हो रहा है कि मुझे इसे संभालने के लिए यह भयानक कोड लिखना होगा" रट, यह मेरे दिमाग को नए तरीकों को देखने के लिए प्रेरित करता है जिससे मैं उन समस्याओं को हल कर सकता हूं। यह मुझे सोचने पर मजबूर करता है कि मैं अपने कोड को अलग तरीके से कैसे बना सकता हूं, और यह अविश्वसनीय रूप से उपयोगी है।
इसे अपने कोड में आज़माएं
मेरे कई पसंदीदा पैटर्न की तरह, मैं पहली बार रिवर्सिंग मेथड . में आया था स्मॉलटाक बेस्ट प्रैक्टिस पैटर्न में, और तब से यह एक मूल्यवान टूल रहा है।
अगली बार जब आपको समान वस्तुओं से निपटने में कठिनाई होती है, जिनका व्यवहार थोड़ा भिन्न होता है, तो इसे आज़माएं! यदि आपको नया कोड बेहतर लगता है, तो इसे रखें। हालांकि, अगर आप ऐसा नहीं भी करते हैं, तो यह आपके दिमाग को एक ऐसे रास्ते पर ले जाएगा जो आपको बेहतर कोड की ओर ले जाएगा।