Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी में ठोस डिजाइन सिद्धांत

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

  • यह गतिहीनता का कारण बनता है।
  • कोड बदलना महंगा है।
  • सॉफ़्टवेयर को सरल बनाने की तुलना में अधिक जटिलता जोड़ना आसान है।
  • कोड अप्रबंधनीय है।
  • डेवलपर को यह पता लगाने में बहुत समय लगता है कि इसकी कार्यक्षमता कैसे काम करती है।
  • सॉफ़्टवेयर के एक हिस्से को बदलने से आमतौर पर दूसरा भाग टूट जाता है, और हम यह अनुमान नहीं लगा सकते कि कोई परिवर्तन किन समस्याओं को ला सकता है।

पेपर डिज़ाइन सिद्धांत और डिज़ाइन पैटर्न, सड़ने वाले सॉफ़्टवेयर के निम्नलिखित लक्षणों को सूचीबद्ध करता है:

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

सॉफ़्टवेयर को इस तरह डिज़ाइन करना आवश्यक है कि परिवर्तनों को नियंत्रित और अनुमानित किया जा सके।

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

सॉलिड डिजाइन सिद्धांत में ये पांच सिद्धांत शामिल हैं:

  • एस जिम्मेदारी का सिद्धांत
  • कलम/बंद सिद्धांत
  • एल iskov प्रतिस्थापन सिद्धांत
  • मैं इंटरफ़ेस अलगाव सिद्धांत
  • डी एपेंडेंसी उलटा सिद्धांत

हम उनमें से प्रत्येक को यह समझने के लिए खोजेंगे कि ये सिद्धांत रूबी में अच्छी तरह से डिज़ाइन किए गए सॉफ़्टवेयर के निर्माण में कैसे मदद कर सकते हैं।

एकल उत्तरदायित्व सिद्धांत - SRP

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

<ब्लॉकक्वॉट>

एक वर्ग के पास बदलने का एक और केवल एक कारण होना चाहिए - रॉबर्ट सी मार्टिन

यहां एक नमूना कोड है जहां सभी कार्यक्षमता एक ही वर्ग में है:

class User
  def initialize(employee, month)
    @employee = employee
    @month = month
  end

  def generate_payslip
    # Code to read from database,
    # generate payslip
    # and write it to a file
    self.send_email
  end

  def send_email
    # code to send email
    employee.email
    month
  end
end

एक पेस्लिप जेनरेट करने और उसे यूजर को भेजने के लिए, हम क्लास को इनिशियलाइज़ कर सकते हैं और जनरेट पेस्लिप मेथड को कॉल कर सकते हैं:

  month = 11
  user = User.new(employee, month)
  user.generate_payslip

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

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

यह सुनिश्चित करने के लिए कि हम चीजों को न तोड़ें, हमें इन तर्कों को अलग-अलग वर्गों में विभाजित करने की आवश्यकता है:

  class PayslipGenerator
    def initialize(employee, month)
      @employee = employee
      @month = month
    end

    def generate_payslip
      # Code to read from database,
      # generate payslip
      # and write it to a file
    end
  end
  class PayslipMailer
    def initialize(employee)
      @employee = employee
    end

    def send_mail
      # code to send email
      employee.email
      month
    end
  end

इसके बाद, हम इन दो वर्गों को इनिशियलाइज़ कर सकते हैं और उनके तरीकों को कॉल कर सकते हैं:

  month = 11
  # General Payslip
  generator = PayslipGenerator.new(employee, month)
  generator.generate_payslip
  # Send Email
  mailer = PayslipMailer.new(employee, month)
  mailer.send_mail

यह दृष्टिकोण जिम्मेदारियों को अलग करने में मदद करता है और एक पूर्वानुमेय परिवर्तन सुनिश्चित करता है। अगर हमें केवल मेलर कार्यक्षमता को बदलने की आवश्यकता है, तो हम रिपोर्ट पीढ़ी को बदले बिना ऐसा कर सकते हैं। यह कार्यक्षमता में किसी भी बदलाव की भविष्यवाणी करने में भी मदद करता है।

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

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

खुला/बंद सिद्धांत - OCP

बर्ट्रेंड मेयर ने ऑब्जेक्ट-ओरिएंटेड सॉफ्टवेयर कंस्ट्रक्शन नामक अपनी पुस्तक में ओपन/क्लोज्ड सिद्धांत की उत्पत्ति की।

सिद्धांत कहता है, "सॉफ़्टवेयर इकाइयां (वर्ग, मॉड्यूल, फ़ंक्शन इत्यादि) विस्तार के लिए खुली होनी चाहिए लेकिन संशोधन के लिए बंद होनी चाहिए "। इसका मतलब यह है कि हमें इकाई को बदले बिना व्यवहार बदलने में सक्षम होना चाहिए।

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

class PayslipGenerator
  def initialize(employee, month)
    @employee = employee
    @month = month
  end

  def generate_payslip
    # Code to read from database,
    # generate payslip
    if employee.contractor?
        # generate payslip for contractor
    else
        # generate a normal payslip
    end
    # and write it to a file
  end
end

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

हम इस कोड को इस तरह से रिफैक्टर कर सकते हैं कि हम कार्यक्षमता को बढ़ाकर कार्यक्षमता जोड़ सकते हैं लेकिन इकाई को बदलने से बच सकते हैं। तो, आइए हम इनमें से प्रत्येक के लिए एक अलग वर्ग बनाएं और एक ही generate उनमें से प्रत्येक के लिए विधि:

class ContractorPayslipGenerator
  def initialize(employee, month)
    @employee = employee
    @month = month
  end

  def generate
    # Code to read from the database,
    # generate payslip
    # and write it to a file
  end
end
class FullTimePayslipGenerator
  def initialize(employee, month)
    @employee = employee
    @month = month
  end

  def generate
    # Code to read from the database,
    # generate payslip
    # and write it to a file
  end
end

सुनिश्चित करें कि इनका एक ही विधि नाम है। अब, इन वर्गों का उपयोग करने के लिए PayslipGenerator वर्ग बदलें:

GENERATORS = {
  'full_time' => FullTimePayslipGenerator,
  'contractor' => ContractorPayslipGenerator
}

class PayslipGenerator
  def initialize(employee, month)
    @employee = employee
    @month = month
  end

  def generate_payslip
    # Code to read from database,
    # generate payslip
    GENERATORS[employee.type].new(employee, month).generate()
    # and write it to a file
  end
end

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

लिस्कोव प्रतिस्थापन सिद्धांत - LSP

लिस्कोव प्रतिस्थापन सिद्धांत कहता है, "यदि S, T का उपप्रकार है, तो T प्रकार की वस्तुओं को S प्रकार की वस्तुओं से बदला जा सकता है"

इस सिद्धांत को समझने के लिए, आइए पहले समस्या को समझें। ओपन/क्लोज्ड सिद्धांत के तहत, हमने सॉफ्टवेयर को इस तरह से डिजाइन किया है कि इसे बढ़ाया जा सकता है। हमने एक उपवर्ग Payslip जनरेटर बनाया है जो एक विशिष्ट कार्य करता है। कॉल करने वाले के लिए, जिस वर्ग को वे कॉल कर रहे हैं वह अज्ञात है। इन वर्गों को समान व्यवहार करने की आवश्यकता है ताकि कॉलर अंतर बताने में असमर्थ हो। व्यवहार से हमारा तात्पर्य है कि कक्षा में विधियाँ सुसंगत होनी चाहिए। इन वर्गों की विधियों में निम्नलिखित विशेषताएं होनी चाहिए:

  • एक ही नाम है
  • समान डेटा प्रकार के साथ समान संख्या में तर्क लें
  • वही डेटा प्रकार लौटाएं

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

class User
  def generate
  end
end

खुले/बंद सिद्धांत के उदाहरण में हमने जो उपवर्ग बनाया है, उसका कोई आधार वर्ग नहीं है। हम इसे आधार वर्ग के लिए संशोधित करते हैं User :

class ContractorPayslipGenerator < User
  def generate
    # Code to generate payslip
  end
end
class FullTimePayslipGenerator < User
  def generate
    # Code to generate payslip
  end
end

इसके बाद, हम उन विधियों के एक सेट को परिभाषित करते हैं जो किसी भी उपवर्ग के लिए आवश्यक हैं जो User . को इनहेरिट करता है कक्षा। हम इन विधियों को बेस क्लास में परिभाषित करते हैं। हमारे मामले में, हमें केवल एक ही विधि की आवश्यकता है, जिसे जनरेट कहा जाता है।

class User
  def generate
    raise "NotImplemented"
  end
end

यहां, हमने जनरेट विधि को परिभाषित किया है, जिसमें एक raise . है बयान। इसलिए, बेस क्लास को इनहेरिट करने वाले किसी भी उपवर्ग को जनरेट करने की विधि की आवश्यकता होती है। यदि यह मौजूद नहीं है, तो यह एक त्रुटि उत्पन्न करेगा कि विधि लागू नहीं की गई है। इस तरह, हम यह सुनिश्चित कर सकते हैं कि उपवर्ग सुसंगत है। इसके साथ, कॉलर हमेशा यह सुनिश्चित कर सकता है कि generate विधि मौजूद है।

यह सिद्धांत चीजों को तोड़े बिना और बहुत सारे बदलाव किए बिना किसी भी उपवर्ग को आसानी से बदलने में मदद करता है।

इंटरफ़ेस अलगाव सिद्धांत - ISP

इंटरफ़ेस अलगाव सिद्धांत स्थिर भाषाओं पर लागू होता है, और चूंकि रूबी एक गतिशील भाषा है, इसलिए इंटरफेस की कोई अवधारणा नहीं है। इंटरफेस कक्षाओं के बीच अमूर्त नियमों को परिभाषित करते हैं।

सिद्धांत कहता है,

<ब्लॉकक्वॉट>

ग्राहकों को उन इंटरफेस पर निर्भर होने के लिए मजबूर नहीं किया जाना चाहिए जिनका वे उपयोग नहीं करते हैं। - रॉबर्ट सी. मार्टिन

इसका मतलब यह है कि किसी भी वर्ग द्वारा उपयोग किए जा सकने वाले सामान्यीकृत इंटरफ़ेस की तुलना में कई इंटरफेस होना बेहतर है। यदि हम एक सामान्यीकृत इंटरफ़ेस को परिभाषित करते हैं, तो वर्ग को उस परिभाषा पर निर्भर रहना पड़ता है जिसका वह उपयोग नहीं करता है।

रूबी में इंटरफेस नहीं है, लेकिन आइए हम कुछ इसी तरह के निर्माण के लिए वर्ग और उपवर्ग की अवधारणा को देखें।

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

class Generator
  def generate
    raise "NotImplemented"
  end
end
class ContractorPayslipGenerator < Generator
  def generate
    # Code to generate payslip
  end
end
class FullTimePayslipGenerator < Generator
  def generate
    # Code to generate payslip
  end
end

यह जनरेटर पेस्लिप पीढ़ी के लिए विशिष्ट है, और उपवर्ग को सामान्य User पर निर्भर होने की आवश्यकता नहीं है कक्षा।

निर्भरता उलटा सिद्धांत - डीआईपी

डिपेंडेंसी इनवर्जन एक सिद्धांत है जो सॉफ्टवेयर मॉड्यूल को अलग करने के लिए लागू होता है।

<ब्लॉकक्वॉट>

एक उच्च-स्तरीय मॉड्यूल को निम्न-स्तरीय मॉड्यूल पर निर्भर नहीं होना चाहिए; दोनों को अमूर्तता पर निर्भर होना चाहिए।

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

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

रूबी में ठोस डिजाइन सिद्धांत

ऊपर हमारे उदाहरण में, ContractorPayslipGenerator मॉड्यूल निर्भरता को नियंत्रित करता है, यह निर्धारित करने के लिए कि डेटा को कहां पढ़ा जाए और आउटपुट को कैसे स्टोर किया जाए, यह वर्ग द्वारा नियंत्रित किया जाता है। इसे वापस करने के लिए, आइए एक UserReader बनाएं वह वर्ग जो उपयोगकर्ता डेटा पढ़ता है:

class UserReader
  def get
    raise "NotImplemented"
  end
end

अब, मान लीजिए कि हम चाहते हैं कि यह Postgres के डेटा को पढ़े। हम इस उद्देश्य के लिए UserReader का एक उपवर्ग बनाते हैं:

class PostgresUserReader < UserReader
  def get
    # Code to read data from Postgres
  end
end

इसी तरह, हमारे पास FileUserReader . से एक रीडर हो सकता है , InMemoryUserReader , या किसी अन्य प्रकार का पाठक जो हम चाहते हैं। अब हमें FullTimePayslipGenerator . को संशोधित करने की आवश्यकता है वर्ग ताकि वह PostgresUserReader . का उपयोग करे एक निर्भरता के रूप में।

class FullTimePayslipGenerator < Generator
  def initialize(datasource)
    @datasource = datasource
  end

  def generate
    # Code to generate payslip
    data = datasource.get()
  end
end

कॉलर अब PostgresUserReader . पास कर सकता है एक निर्भरता के रूप में:

datasource = PostgresUserReader.new()
FullTimePayslipGenerator.new(datasource)

कॉलर का निर्भरता पर नियंत्रण होता है और जरूरत पड़ने पर वह आसानी से स्रोत को बदल सकता है।

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

class PostgresUserReader < UserReader
  def initialize(config)
    config = config
  end

  def get
    # initialize DB with the config
    self.config
    # Code to read data from Postgres
  end
end

कॉलर द्वारा कॉन्फिगरेशन प्रदान करें:

  config = { url: "url", user: "user" }
  datasource = PostgresUserReader.new(config)
  FullTimePayslipGenerator.new(datasource)

कॉलर का अब निर्भरता पर पूर्ण नियंत्रण है, और परिवर्तन प्रबंधन आसान और कम दर्दनाक है।

समापन

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

यह समझना वास्तव में महत्वपूर्ण है कि सॉलिड किस प्रकार की समस्याओं का समाधान करता है और हम ऐसा क्यों कर रहे हैं। समस्या को समझने से आपको डिज़ाइन सिद्धांतों को अपनाने और बेहतर सॉफ़्टवेयर डिज़ाइन करने में मदद मिलती है।


  1. 5 पेशेवर आर्किटेक्ट के लिए आवश्यक सॉफ्टवेयर

    ‘अगर कोई इमारत वास्तुकला बन जाती है, तो वह कला है’- अर्ने जैकबसन! डेनिश वास्तुकार के ये शब्द दुनिया भर के उन सभी भावुक वास्तुकारों के लिए बिल्कुल सही हैं जो एक ईंट को एक उत्कृष्ट कृति में बदल सकते हैं। और उभरती हुई तकनीक के साथ, कुछ आर्किटेक्चर डिज़ाइन सॉफ़्टवेयर एक वास्तुकार के प्रयास को सकारात्म

  1. सर्वश्रेष्ठ मुफ्त गेम डिजाइन सॉफ्टवेयर

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

  1. 2022 के 10 सर्वश्रेष्ठ पुस्तक डिजाइन सॉफ्टवेयर

    पुस्तक डिज़ाइन सॉफ़्टवेयर का उपयोग लेखकों और लेखकों द्वारा ऑनलाइन पुस्तक बनाने के लिए किया जा सकता है। ऐसे कई एप्लिकेशन नौसिखियों और विशेषज्ञों द्वारा समान रूप से उपयोग किए जा सकते हैं। यह लेख पुस्तक कवर और आंतरिक डिज़ाइन बनाने और आपकी पुस्तक को डिजिटल स्वरूप में सहेजने के लिए सशुल्क और निःशुल्क पुस