2012-01-19 8 views
25

मैंने कुछ स्प्रिंग-हाइबरनेट वेब एप्लिकेशन प्रोजेक्ट्स को काम/देखा है क्योंकि कई इंटरफेस हैं क्योंकि वास्तविक सेवा और दाओ कक्षाएं हैं।सेवा और दाओ परतों में हमेशा एक कार्यान्वयन इंटरफेस क्यों है?

मुझे हमेशा यही लगता है कि इन एकल कार्यान्वयन इंटरफेस होने के लिए मुख्य कारणों के रूप में इन दो:

  1. स्प्रिंग किसी वर्ग (ढीला संयोजन) में निर्भरता के रूप में वास्तविक क्रियान्वयन तार कर सकते हैं

    public class Person { 
        @Autowired 
        private Address address; 
    
        @Autowired 
        private AccountDetail accountDetail; 
    
        public Person(Address address, AccountDetail accountDetail) 
        { // constructor 
    
  2. यूनिट परीक्षण करते समय, मैं नकली कक्षाएं बना सकता हूं और अलगाव में एक वर्ग का परीक्षण कर सकता हूं।

    Address mockedAddress = mock(Address); 
    AccountDetail mockedAccountDetail = mock(AccountDetail); 
    Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
    // unit test follows 
    

लेकिन, देर से की, मुझे एहसास हुआ कि:

स्प्रिंग निर्भरता के रूप में ठोस कार्यान्वयन कक्षाएं तार कर सकते हैं:

public class Person { 

@Autowired 
private AddressImpl address; 

@Autowired 
private AccountDetailImpl accountDetail; 

public Person(AddressImpl address, AccountDetailImpl accountDetail) { 
// constructor 

EasyMock की तरह नकली चौखटे ठोस वर्ग के साथ-साथ

नकली कर सकते हैं
AddressImpl mockedAddress = mock(AddressImpl); 
AccountDetailImpl mockedAccountDetail = mock(AccountDetailImpl); 
Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
// unit test follows 

इसके अलावा, this चर्चा के अनुसार, मुझे लगता है कि सारांश यह है कि एक ही ऐप के भीतर, इंटरफेस ज्यादातर सम्मेलन या आदत से बाहर हो जाते हैं। वे आम तौर पर उन मामलों में सबसे अच्छी समझ बनाते हैं जहां हम दूसरे एप्लिकेशन के साथ इंटरफेसिंग कर रहे हैं उदाहरण के लिए slf4j दुनिया भर के कई ऐप्स द्वारा उपयोग किया जाता है। एक ऐप के भीतर, एक वर्ग एक इंटरफ़ेस के रूप में लगभग एक अमूर्त है।

तो, मेरा सवाल यह है कि हमें अभी भी इंटरफेस की आवश्यकता क्यों है और उसके बाद * ServiceImpl और * DaoImpl कक्षाओं जैसे एकल कार्यान्वयन और अनावश्यक रूप से हमारे कोड आधार आकार को बढ़ाएं। कंक्रीट कक्षाओं का मज़ाक उड़ाते हुए कुछ मुद्दा है जो मुझे पता नहीं है।

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

+2

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

उत्तर

14

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

इस पर और अधिक के लिए here पढ़ें।

अधिक जानकारी के लिए what reasons are there to use interfaces (Java EE or Spring and JPA) पर एक और चर्चा पढ़ें।

14

यह एक बहुत ही विवादास्पद विषय है। संक्षेप में, कम से कम आपके लिए, डेवलपर नहीं है।

ईजेबी 2 दुनिया में, घर और रिमोट इंटरफेस एक जरूरी थे, और बिल्कुल एक कारण के लिए @ अरविंद उल्लेख है: प्रॉक्सी। सुरक्षा, रिमोटिंग, पूलिंग इत्यादि सभी को प्रॉक्सी में लपेटा जा सकता है, और मानक लाइब्रेरी के भीतर सख्ती से अनुरोध की गई सेवाएं प्रदान करें (जैसे DynamicProxy)।

अब हमारे पास javaassist और cglib है, स्प्रिंग (हाइबरनेट, ईजेबी 3 यदि आप पसंद करते हैं) पूरी तरह से फ्रेमवर्क डेवलपर पसंद के रूप में आपके वर्गों को वाद्ययंत्र करने में सक्षम हैं। समस्या यह है कि, वे क्या करते हैं एक बहुत ही परेशान चीज है: वे आमतौर पर आपको नो-पैरामीटर कन्स्ट्रक्टर जोड़ने का अनुरोध करते हैं.-रुको, मेरे पास पैरामीटर थे? -नहीं, बस कन्स्ट्रक्टर जोड़ें।

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

इसके अलावा, यदि आप अपनी कक्षा में एक इंटरफ़ेस को लागू करना चाहते हैं, (कम से कम कुछ संस्करण) वसंत अचानक निर्णय लेता है कि आप केवल इस इंटरफ़ेस को प्रॉक्सी करने जा रहे हैं, और एप्लिकेशन किसी स्पष्ट कारण के लिए काम नहीं करता है।

इस प्रकार, अब तक, सुरक्षा और स्वच्छता का कारण है। ऐसे कारण हैं कि यह एक अच्छा अभ्यास क्यों है- लेकिन आपकी पोस्ट से, मुझे लगता है कि आप पहले से ही उन सभी को पढ़ चुके हैं। आज मैं देख सकता हूं कि सबसे महत्वपूर्ण कारण WTH/मिनट मीट्रिक है, खासकर यदि हम आपके प्रोजेक्ट में नवागंतुकों के बारे में बात कर रहे हैं।