चूंकि रूबी एक वस्तु-उन्मुख भाषा है, इसलिए हम दुनिया को वस्तुओं के एक सेट के रूप में मॉडल करते हैं। हम कहते हैं कि दो पूर्णांक (x और y) एक बिंदु हैं, और एक रेखा में उनमें से दो होते हैं।
जबकि यह दृष्टिकोण अक्सर उपयोगी होता है, इसमें एक बड़ी समस्या होती है। यह अन्य सभी पर डेटा की एक व्याख्या का विशेषाधिकार देता है। यह मानता है कि x, और y हमेशा एक बिंदु होंगे और आपको कभी भी सेल या वेक्टर के रूप में कार्य करने के लिए उनकी आवश्यकता नहीं होगी।
क्या होता है जब आपको सेल की आवश्यकता होती है? खैर, प्वाइंट डेटा का मालिक है। तो आप प्वाइंट में अपनी सेल विधियों को जोड़ते हैं। समय के साथ आप एक पॉइंट क्लास के साथ समाप्त हो जाते हैं जो शिथिल-संबंधित विधियों का एक जंक ड्रॉअर है।
जंक-दराज वर्ग इतने आम हैं कि हम अक्सर उन्हें अपरिहार्य के रूप में स्वीकार करते हैं और विकास के लिए "रीफैक्टरिंग" कदम उठाते हैं। लेकिन क्या होगा अगर हम पहली बार में समस्या से बच सकें?
वेब विकास का पहला नियम यह है कि हम इसके बारे में बात नहीं करते हैं उपयोगकर्ता वर्ग
किसी भी युद्ध-कठिन उत्पादन के केंद्र में रेल ऐप User
नामक एक वर्ग की विशाल राक्षसी है ।
यह हमेशा काफी मासूमियत से शुरू होता है। आप लोगों को लॉग इन करने देना चाहते हैं। आपको उनका यूजरनेम और पासवर्ड स्टोर करने की जरूरत है, ताकि आप एक क्लास बना सकें:
class User
attr_accessor :username, :password, :email, :address
def authenticate!(password)
...
end
end
यह इतनी अच्छी तरह से काम करता है कि अंततः लोग आपको पैसा देना चाहते हैं। "ठीक है," हम कहते हैं "एक उपयोगकर्ता मूल रूप से एक सब्सक्राइबर जैसा ही होता है इसलिए हम केवल कुछ विशेषताओं और कुछ विधियों को जोड़ देंगे।"
class User
...
attr_accessor :payment_processor_token, :subscription_plan_id, ...etc
def charge_cc
...
end
end
महान! अब हम कुछ वास्तविक पैसा कमा रहे हैं! सीईओ ने फैसला किया है कि वे उपयोगकर्ताओं की संपर्क जानकारी के साथ वीकार्ड निर्यात करने में सक्षम होना चाहते हैं ताकि बिक्री टीम उन्हें आसानी से सेल्सफोर्स में आयात कर सके। विम को सक्रिय करने का समय:
class User
...
def export_vcard
...
end
end
हमने क्या किया है?
हमने एक उपयोगकर्ता वर्ग के साथ शुरुआत की, जिसका एकमात्र उद्देश्य प्रमाणीकरण को संभालना था। इसमें अतिरिक्त तरीके और विशेषताएं जोड़कर, हमने इसे उपयोगकर्ता/ग्राहक/संपर्क फ्रेंकस्टीन हाइब्रिड में बदल दिया।
हम ऐसा क्यों करेंगे? क्या हम खुद को डेवलपर्स के रूप में सम्मान नहीं करते हैं? क्या हमारे माता-पिता ने हमें पर्याप्त प्यार नहीं किया? या क्या हमने इस डेटा को वास्तव में है . मानकर विफलता के लिए खुद को स्थापित किया है एक वस्तु, एक वस्तु?
हम ऐसा क्यों कहते हैं कि उपयोगकर्ता नाम, पासवर्ड और ईमेल पते का संयोजन एक उपयोगकर्ता है? सब्सक्राइबर क्यों नहीं? या एक संपर्क? या एक सत्र धारक?
डेटा के बारे में सच्चाई यह है कि यह डेटा है
डेटा सिर्फ डेटा है। आज आपको प्रेमी की तरह व्यवहार करना पड़ सकता है। कल यह एक पूर्व प्रेमी हो सकता है।
यह वह दृष्टिकोण है जो अमृत जैसी कार्यात्मक भाषाएँ अपनाती हैं। डेटा को रूबी के हैश, एरेज़, स्ट्रिंग्स इत्यादि जैसी सरल संरचनाओं में संग्रहीत किया जाता है। जब आप डेटा के साथ कुछ करना चाहते हैं तो आप इसे किसी फ़ंक्शन में पास करते हैं। उस फ़ंक्शन से कोई भी परिणाम लौटाया जाता है।
यह आसान लगता है, लेकिन यह दृष्टिकोण विभिन्न मॉड्यूल में चिंताओं को अलग करना बहुत आसान बनाता है।
यहाँ एक कार्टून है कि कैसे हम अपने उपयोगकर्ता सिस्टम को इसे अमृत में बना सकते हैं:
my_user = %{username: "foo", password: ..., phone: ..., payment_token: ...}
my_user = Authentication.authenticate(my_user)
my_user = Subscription.charge(my_user)
my_user = Contact.export_vcard(my_user)
चूंकि डेटा कोड से अलग है, इसलिए किसी भी मॉड्यूल के पास उस डेटा की विशेषाधिकार प्राप्त व्याख्या नहीं है।
इसे रूबी में वापस लाना
चूंकि यह दृष्टिकोण अमृत में बहुत अच्छा काम करता है, इसलिए इसे रूबी में क्यों न अपनाएं? हमें User
. बनाने से कोई रोक नहीं सकता है अपने डेटा के लिए एक साधारण आवरण में, और सभी व्यावसायिक तर्क को मॉड्यूल में खींच रहा है।
class User
attr_accessor :username, :password, :email, :address
end
module Authentication
def self.authenticate!(user)
..
end
end
module Subscription
def self.charge(user)
..
end
end
module Contact
def self.export_vcard(user)
..
end
end
आप User
. भी बना सकते हैं एक संरचना में वर्ग, या इसे (तरह का) अपरिवर्तनीय बनाने के लिए कोड जोड़ें।
तो क्या?
क्या यह एक मामूली बदलाव की तरह लगता है? क्या बात है?
जैसा कि हमने देखा, विशिष्ट OO दृष्टिकोण में समस्याएँ होती हैं क्योंकि यह उम्र होती है। यह कहकर कि एक निश्चित वर्ग मालिक है डेटा, जब हमें उस डेटा को किसी अन्य तरीके से उपयोग करने की आवश्यकता होती है, तो हम समस्याओं में पड़ जाते हैं।
मॉड्यूलर दृष्टिकोण में, हालांकि, व्यवहार जोड़ने से कोई समस्या नहीं होती है। हम बस एक नया मॉड्यूल बनाते हैं जो डेटा की किसी भी तरह से व्याख्या करता है। ऐसा करना आसान है क्योंकि डेटा और कार्यक्षमता पूरी तरह से अलग हैं।
अन्य दृष्टिकोण
जंक-दराज की समस्या को रोकने के लिए अन्य दृष्टिकोण भी हैं। परंपरागत रूप से, ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में आप इनहेरिटेंस और सावधानीपूर्वक रिफैक्टरिंग के माध्यम से ऐसा करने का प्रयास करेंगे। 2012 में सैंडी मेट्ज़ ने रूबी में प्रैक्टिकल ऑब्जेक्ट ओरिएंटेड डिज़ाइन प्रकाशित किया जिसने कई लोगों को डिपेंडेंसी इंजेक्शन का उपयोग करके वस्तुओं की रचना शुरू करने के लिए मना लिया। हाल ही में, कार्यात्मक प्रोग्रामिंग की लोकप्रियता ने रूबीवादियों को अपरिवर्तनीय "डेटा ऑब्जेक्ट्स" के साथ प्रयोग करने के लिए प्रेरित किया है।
इन सभी दृष्टिकोणों का उपयोग स्वच्छ, सुंदर कोड बनाने के लिए किया जा सकता है। हालांकि तथ्य यह है कि कक्षाएं आमतौर पर डेटा का मालिक होती हैं, इसका मतलब है कि वर्ग है . के बीच हमेशा तनाव रहेगा और कक्षा डेटा के साथ क्या करती है।
मुझे संदेह है कि जंक-दराज की समस्या से बचने में इन दृष्टिकोणों को जो भी सफलता मिली है, वह कोड से उनके डेटा को अलग करने के परिणामस्वरूप है।