clojure - क्लोज़र परिपत्र निर्भरता को हल करना




circular-dependency (4)

मैं कुछ क्लोज़र कोड पर काम कर रहा हूं जिसमें विभिन्न नेमस्पेस के बीच कुछ परिपत्र निर्भरताएं हैं और मैं उन्हें हल करने का सबसे अच्छा तरीका तैयार करने की कोशिश कर रहा हूं।

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

कोई विचार? Clozure में इस तरह की परिपत्र निर्भरता को संभाल करने का सबसे अच्छा तरीका क्या है?


मुझे कुछ गुई कोड के साथ एक ऐसी ही समस्या थी, जो मैंने समाप्त कर दिया है,

(defn- frame [args]
  ((resolve 'project.gui/frame) args))

यह मुझे रनटाइम के दौरान कॉल को हल करने की इजाजत देता था, इसे फ्रेम में मेनू आइटम से फोन किया जाता था, इसलिए मुझे 100% यकीन था कि फ्रेम को परिभाषित किया गया था क्योंकि इसे फ़्रेम से ही बुलाया जा रहा था, ध्यान रखें कि संकल्प शून्य हो सकता है


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

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

संक्षेप करने के लिए, मेरा वोट रिफैक्टोरिंग को जाता है


मुझे लगातार यही समस्या है जितने ज्यादा डेवलपर्स इसे स्वीकार नहीं करना चाहते, उतना ही यह भाषा में एक गंभीर डिजाइन दोष है। परिपत्र निर्भरता वास्तविक वस्तुओं की एक सामान्य स्थिति है। एक शरीर हृदय के बिना जीवित नहीं रह सकता है, और हृदय शरीर के बिना जीवित नहीं रह सकता है।

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

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

यदि एए (BA) पर निर्भर करता है और बीबी () एबी () पर निर्भर होता है तो एकमात्र समाधान बा () को सीए () और / या एबी () को सीबी () में ले जाना है, हालांकि सी तकनीकी रूप से मौजूद नहीं है वास्तविक दुनिया।


डिजाइन के बारे में ध्यान से सोचना अच्छा है परिपत्र निर्भरता हमें बता रही है कि हम कुछ महत्वपूर्ण बातों के बारे में भ्रमित हैं।

यहाँ एक ऐसी चाल है जो मैंने एक या दो मामलों में परिपत्र निर्भरता के आसपास काम करने के लिए उपयोग किया है।

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; example/a.cljc

(ns example.a
  (:require [example.b :as b]))

(defn foo []
  (println "foo"))

#?(

   :clj
   (alter-var-root #'b/foo (constantly foo))                ; <- in clojure do this

   :cljs
   (set! b/foo foo)                                         ; <- in clojurescript do this

   )

(defn barfoo []
  (b/bar)
  (foo))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; example/b.cljc

(ns example.b)

;; Avoid circular dependency.  This gets set by example.a
(defonce foo nil)

(defn bar []
  (println "bar"))

(defn foobar []
  (foo)
  (bar))

मैंने इस चाल से रेगेंट में दान होल्म्सैंड के कोड से सीखा है





circular-dependency