क्या हम स्थैतिक तरीकों का दुरुपयोग कर रहे हैं?


13

कुछ महीने पहले मैंने एक नई परियोजना में काम करना शुरू किया था, और कोड के माध्यम से जाने पर यह मेरे द्वारा उपयोग किए जाने वाले स्थिर तरीकों की मात्रा को स्ट्रोक करता था। न केवल उपयोगिता विधियों के रूप में collectionToCsvString(Collection<E> elements), बल्कि उनमें बहुत सारे व्यावसायिक तर्क भी रखे गए हैं।

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

@Service
public class CustomerReceiptCreationService {

    public CustomerReceipt createReceipt(Object... args) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        return receipt;
    }
}

अब, उस व्यक्ति ने कहा कि वह अनावश्यक रूप से स्प्रिंग द्वारा प्रबंधित कक्षाओं को नापसंद करता है, मूल रूप से क्योंकि यह प्रतिबंध लगाता है कि ग्राहक वर्ग को स्वयं स्प्रिंग बीन्स होना चाहिए। हम अंत में स्प्रिंग द्वारा प्रबंधित सब कुछ करते हैं, जो हमें एक प्रक्रियात्मक तरीके से स्टेटलेस वस्तुओं के साथ काम करने के लिए मजबूर करता है। कमोबेश यहाँ क्या बताया गया है https://www.javacodegeeks.com/2011/02/domain-driven-design-spring-aspectj.html

इसलिए उपरोक्त कोड के बजाय उसके पास है

public class CustomerReceiptCreator {

    public static CustomerReceipt createReceipt(Object... args) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        return receipt;
    }
}

जब संभव हो तो हम अपनी कक्षाओं को प्रबंधित करने से बचने के मुद्दे पर बहस कर सकते हैं, लेकिन जो मैं नहीं देखता वह सब कुछ स्थिर होने का लाभ है। ये स्थैतिक विधियां भी स्टेटलेस हैं, इसलिए बहुत अधिक ओओ नहीं हैं। मैं कुछ के साथ अधिक सहज महसूस करूंगा

new CustomerReceiptCreator().createReceipt()

उनका दावा है कि स्थैतिक तरीकों से कुछ अतिरिक्त लाभ होते हैं। अर्थात्:

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

लेकिन मुझे लगता है कि इसके साथ कुछ पूरी तरह से सही नहीं है, इसलिए मैं इस पर कुछ और अनुभवी डेवलपर्स के विचार सुनना चाहूंगा।

तो मेरा सवाल यह है कि प्रोग्रामिंग के इस तरीके के संभावित नुकसान क्या हैं?




4
जिस staticविधि के बारे में आप ऊपर बता रहे हैं, वह सिर्फ एक सामान्य फैक्टरी विधि है। फैक्ट्री के तरीकों को स्थिर बनाना आम तौर पर स्वीकृत सम्मलेन है, कई सम्मोहक कारणों से। क्या कारखाने की विधि यहां उपयुक्त है या नहीं यह अलग बात है।
रॉबर्ट हार्वे

जवाबों:


23

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

जहां चीजें अलग होती हैं, जब आप इसे आईएनजी के CustomerReceiptCreatorबजाय इंजेक्ट करते newहैं। आइए एक उदाहरण पर विचार करें:

class OrderProcessor {
    @Inject CustomerReceiptCreator customerReceiptCreator;

    void processOrder(Order order) {
        ...
        CustomerReceipt receipt = customerReceiptCreator.createReceipt(order);
        ...
    }
}

आइए इस स्थैतिक विधि संस्करण की तुलना करें:

void processOrder(Order order) {
    ...
    CustomerReceipt receipt = CustomerReceiptCreator.createReceipt(order);
    ...
}

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

अगर मैं इंजेक्शन लगाता हूं तो मैं वही गारंटी नहीं दे सकता CustomerReceiptCreator। इसमें आंतरिक स्थिति हो सकती है जिसे कॉल द्वारा बदल दिया जाता है, मैं दूसरे राज्य से प्रभावित या बदल सकता हूं। मेरे कार्य में बयानों के बीच अप्रत्याशित संबंध हो सकते हैं जैसे कि आदेश को बदलना आश्चर्यजनक बगों को पेश करेगा।

दूसरी ओर, क्या होता है अगर CustomerReceiptCreatorअचानक एक नई निर्भरता की आवश्यकता होती है? मान लें कि इसे एक सुविधा ध्वज की जांच करने की आवश्यकता है। यदि हम इंजेक्शन लगा रहे थे, तो हम कुछ ऐसा कर सकते थे:

public class CustomerReceiptCreator {
    @Injected FeatureFlags featureFlags;

    public CustomerReceipt createReceipt(Order order) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        if (featureFlags.isFlagSet(Flags::FOOBAR)) {
           ...
        }
        return receipt;
    }
}

फिर हम कर रहे हैं, क्योंकि कॉलिंग कोड इंजेक्ट किया CustomerReceiptCreatorजाएगा जो एक स्वचालित रूप से इंजेक्ट हो जाएगा FeatureFlags

क्या होगा यदि हम एक स्थिर विधि का उपयोग कर रहे थे?

public class CustomerReceiptCreator {
    public static CustomerReceipt createReceipt(Order order, FeatureFlags featureFlags) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        if (featureFlags.isFlagSet(Flags::FOOBAR)) {
           ...
        }
        return receipt;
    }
}

लेकिन रुकें! कॉलिंग कोड को भी अपडेट करना होगा:

void processOrder(Order order) {
    ...
    CustomerReceipt receipt = CustomerReceiptCreator.createReceipt(order, featureFlags);
    ...
}

बेशक, यह अभी भी इस सवाल को छोड़ देता है कि इसे कहां से processOrderमिलता FeatureFlagsहै। यदि हम भाग्यशाली हैं, तो निशान यहाँ समाप्त हो जाता है, यदि नहीं, तो FeatureFlags के माध्यम से गुजरने की आवश्यकता को स्टैक को और धक्का दिया जाता है।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.