क्या इंटरफेस को एक अलग पैकेज में रखा जाना चाहिए? [बन्द है]


80

मैं एक बड़ी परियोजना पर काम कर रहा हूं, जिसमें बहुत सारे घटक और निर्भरताएं हैं। प्रत्येक घटक के लिए, एक interfacesपैकेज होता है जहाँ उस घटक के लिए उजागर इंटरफेस रखे जाते हैं। क्या यह अच्छा अभ्यास है?

मेरा सामान्य अभ्यास हमेशा इंटरफेस और कार्यान्वयन समान पैकेज में रहा है।


4
यह क्यों टैग किया गया है [भाषा-अज्ञेयवादी]
रात 11:45

एक और स्थिति जहां इसे पसंद किया जा सकता है यदि मॉड्यूल को सीधे मंगलाचरण के बजाय कुछ आरपीसी पर संचारित किया जाना है - तो इंटरफ़ेस क्लाइंट के लिए परदे के पीछे उत्पन्न करने के लिए काम में आता है ??
रेडजेड्डी

जवाबों:


101

इंटरफ़ेस और कार्यान्वयन दोनों को लागू करना आम जगह है, और यह एक समस्या नहीं लगती है।

उदाहरण के लिए जावा एपीआई लें - अधिकांश कक्षाओं में एक ही पैकेज में शामिल इंटरफेस और उनके कार्यान्वयन दोनों हैं।

उदाहरण के लिए java.utilपैकेज लें :

यह इस तरह के रूप इंटरफेस शामिल Set, Map, List, भी कार्यान्वयन करते हुए इस तरह के रूप HashSet, HashMapऔर ArrayList

इसके अलावा, Javadocs, अच्छी तरह से उन परिस्थितियों में काम करने के लिए तैयार कर रहे हैं के रूप में यह में प्रलेखन अलग करती है इंटरफेस और वर्गों बार देखा गया जब पैकेज की सामग्री प्रदर्शित।

केवल इंटरफेस के लिए पैकेज होने से वास्तव में थोड़ा अधिक हो सकता है, जब तक कि बड़ी संख्या में इंटरफेस न हों। लेकिन ऐसा करने के लिए इंटरफेस को अपने स्वयं के पैकेज में अलग करना, ताकि बुरा अभ्यास हो।

यदि कार्यान्वयन से एक इंटरफ़ेस के नाम को अलग करना आवश्यक है, तो इंटरफेस को पहचानने में आसान बनाने के लिए एक नामकरण सम्मेलन हो सकता है:

  • एक के साथ इंटरफेस नाम उपसर्ग Iयह दृष्टिकोण .NET फ्रेमवर्क में इंटरफेस के साथ लिया गया है। यह बताना काफी आसान होगा कि IListयह सूची के लिए एक इंटरफ़ेस है।

  • - ableप्रत्यय का प्रयोग करें । यह दृष्टिकोण जैसे, जावा एपीआई में अक्सर देखा जाता है Comparable, Iterableऔर Serializableकुछ नाम हैं।


43
+1 हालांकि मैं तब तक I * नामकरण सम्मेलन की सिफारिश नहीं करूंगा जब तक आप .NETverse में नहीं होते, और तब भी केवल स्थिरता के लिए
CurtainDog

7
मैंने इस कन्वेंशन का उपयोग जावा कोड में किया है और मैंने इसे उपयोगी पाया है .... YMMV
hhafez

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

1
मुझे लगता है कि यह दृष्टिकोण, भले ही यह सही लगे, वास्तु समस्याओं को लाता है। उदाहरण के लिए, पुस्तकालयों को परिभाषित करने का कोई तरीका नहीं है जो सिर्फ इंटरफेस का उपयोग करते हैं और फिर उन्हें एक सामान्य पुस्तकालय में लागू किया जाता है, जो कि बुनियादी ढांचे की परत है।
लुका मसेरा

1
मैं इस तरह से इंटरफेस के लिए "I" उपसर्ग का उपयोग नहीं करने के बारे में टिप्पणी से सहमत हूं, मैं कार्यान्वयन के लिए "प्रत्यय" प्रत्यय का उपयोग करने की सिफारिश नहीं करूंगा, यह उन मामलों पर प्रतिबिंबित करने वाला एक अच्छा लेख है: octoperf.com/blog/2016 / १० / २ 10 / प्रति-वर्ग-

19

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

आइए इस विशेष उदाहरण को देखें।

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

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

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


इस सवाल पर 'जावा' टैग को देखते हुए - जावा में ' सार्वजनिक रूप से उजागर पैकेज' का क्या अर्थ है ? या आपका उत्तर जावा-विशिष्ट नहीं है? मैंने केवल पैकेज सदस्यों (जैसे कि कक्षाएं, इंटरफेस और उनके सदस्य) के बारे में सोचा, न कि स्वयं पैकेज, 'पब्लिक', 'प्राइवेट' आदि जैसे एक्सेस कंट्रोल स्पेसर्स थे (यह आगे चर्चा की है @ सवाल stackoverflow.com/questions/4388715/… )
बेकर

मैंने सिर्फ शब्दों को स्पष्ट किया है; "सार्वजनिक रूप से उजागर पैकेज" द्वारा मेरा वास्तव में मतलब था, "सार्वजनिक रूप से उजागर चीजों के साथ पैकेज।"
cjs

निश्चित रूप से सभी पैकेजों में सार्वजनिक चीजें होनी चाहिए; यदि नहीं, तो आप पैकेज का उपयोग कैसे कर सकते हैं?
बेकर

इस विशेष मामले में, कुछ भी नहीं के साथ पैकेज सार्वजनिक थे, लेकिन जिन पैकेजों का उपयोग किया गया था, वे सार्वजनिक थे। तो पूर्व को सीधे इस्तेमाल नहीं किया जा सकता है, लेकिन केवल परोक्ष रूप से उत्तरार्द्ध के माध्यम से।
cjs

1
लेकिन वही प्रश्न लागू होता है। जिन पैकेजों ने चीजों को सार्वजनिक किया है वे उन पैकेजों का उपयोग कैसे कर सकते हैं जिन्होंने कुछ भी सार्वजनिक नहीं किया? मैं जावा में "पूर्व को सीधे इस्तेमाल नहीं किया जा सकता है, लेकिन इसे बाद के माध्यम से अप्रत्यक्ष रूप से लागू करने का कोई तरीका नहीं जानता।" यदि आपके कार्यान्वयन पैकेज में केवल निजी सदस्य हैं, तो यह आपके इंटरफ़ेस पैकेज द्वारा उतना ही दुर्गम है जितना ग्राहक द्वारा। और इसी तरह अन्य एक्सेस स्कोप के लिए। जावा में friend(C ++) या internal(C #) के बराबर नहीं है ।
बैकर

10

कई रूपरेखाओं में, जैसे कि ओएसजीआई, आपको लगभग करना होगा। मुझे लगता है कि यह जार स्तर के बजाय पैकेज पर शिथिल युग्मन को बढ़ावा देता है।


7

विभिन्न पैकेजों में इंटरफेस रखने का एक तर्क यह है कि 'एपी' जार बनाना आसान है जो आपके उत्पाद या सेवा के उपभोक्ताओं को वितरित किया जा सकता है। यह पूरी तरह से एक साथ इंटरफेस और कार्यान्वयन के साथ करना संभव है, लेकिन अलग-अलग पैकेजों में होने पर स्क्रिप्ट को सरल करना।


7
आपके पास एपीआई प्रोजेक्ट अलग (एक अलग वितरण योग्य) हो सकता है और यह अभी भी एक ही पैकेज में इंटरफेस और कार्यान्वयन को रोक नहीं सकता है। आप की तरह एक बिट परीक्षण की कक्षाओं के रूप में एक ही पैकेज में इकाई परीक्षण है, लेकिन अभी भी एक अलग निर्माण विरूपण साक्ष्य में है। जावा में जार और पैकेज बहुत ओर्थोगोनल हैं।
जॉर्ज

7

पुस्तक प्रैक्टिकल सॉफ्टवेयर इंजीनियरिंग: ए केस-स्टडी दृष्टिकोण अलग परियोजनाओं / पैकेजों में इंटरफेस लगाने की वकालत करता है।

PCMEF + आर्किटेक्चर जिस पुस्तक के बारे में बात करता है उसके निम्न सिद्धांत हैं:

  1. डाउनवर्ड डिपेंडेंसी प्रिंसिपल (DDP)
  2. अपवर्ड नोटिफिकेशन सिद्धांत (UNP)
  3. पड़ोसी संचार सिद्धांत (NCP)
  4. स्पष्ट एसोसिएशन सिद्धांत (EAP)
  5. साइकिल उन्मूलन सिद्धांत (सीईपी)
  6. क्लास नामकरण सिद्धांत (CNP)
  7. परिचित पैकेज सिद्धांत (एपीपी)

सिद्धांत # 3 और # 7 का वर्णन क्यों यह एक अच्छा विचार है:

पड़ोसी संचार सिद्धांत मांग करता है कि एक पैकेज केवल अपने पड़ोसी पैकेज के साथ सीधे संवाद कर सकता है। यह सिद्धांत सुनिश्चित करता है कि सिस्टम इंटरकम्प्युटिंग ऑब्जेक्ट्स के एक अचूक नेटवर्क के लिए विघटित नहीं होता है। इस सिद्धांत को लागू करने के लिए, गैर-पड़ोसी वस्तुओं के बीच गुजरने वाला संदेश प्रतिनिधिमंडल का उपयोग करता है (धारा 9.1.5.1)। अधिक जटिल परिदृश्यों में, परिचित पैकेज (धारा 9.1.8.2) का उपयोग समूह इंटरफेस को सहयोग के लिए किया जा सकता है जो दूर के पैकेजों को संलग्न करता है।

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

इस लिंक को देखें: http://comp.mq.edu.au/books/pse/about_book/Ch9.pdf


5

हां, यह एक बहुत अच्छा अभ्यास है, क्योंकि यह आपको अपने विशिष्ट कार्यान्वयन को प्रकाशित किए बिना इंटरफ़ेस प्रकाशित करने की अनुमति देता है। कहा कि, यदि आपको बाहरी इंटरफेस प्रकाशित करने की कोई आवश्यकता नहीं है, तो कार्यान्वयन के समान इंटरफ़ेस परिभाषाओं को एक ही पैकेज में रखने में कोई समस्या नहीं है।


2
हो सकता है कि अगर आप जेसीपी या कुछ के लिए इंटरफेस को परिभाषित कर रहे हैं, तो यह अच्छी समझ में आता है, लेकिन यदि आप अपनी परियोजना के लिए इन इंटरफेस के कई ठोस कार्यान्वयन का उत्पादन कर रहे हैं तो यह अलग से इंटरफेस को पैकेज करने के लिए एक अनावश्यक बोझ की तरह लगता है।
ब्रायन रीटर

2
यह किसी भी घटना में बहुत बोझ नहीं है ...
पॉल सोनियर

4
-1 हाँ, यह है। यह कार्यान्वयन को खोजने के लिए अनावश्यक रूप से कठिन बनाता है और एक साथ संबंधित चीजों को अलग करता है।
माइकल बोर्गवर्ड

5
और कार्यान्वयन को प्रकाशित नहीं करना एक पूरी तरह से अलग मामला है जो उन्हें पैकेज-निजी बनाकर किया जा सकता है - और उन्हें एक अलग पैकेज में रखकर नहीं किया जा सकता है। गैर-सार्वजनिक पैकेज जैसी कोई चीज नहीं है।
माइकल बोर्गवर्ड

1
इसके अलावा, यह सभी इंटरफेस को अनावश्यक रूप से सार्वजनिक करने जैसा लगता है।
अदील अंसारी

4

हम ऐसा करते हैं जहां मैं काम करता हूं (यानी: एक पैकेज में इंटरफ़ेस डालें और दूसरे में कार्यान्वयन) और इससे निकलने वाला मुख्य लाभ यह है कि हम कार्यान्वयन के बीच आसानी से स्वैप कर सकते हैं।


7
यह कैसे लागू करने में आपकी मदद करता है?
जानुस १

कैमरन पोप का जवाब देखें, यह बिल्कुल वैसा ही है जैसा हम यहां कर रहे हैं
hhafez

3

मुझे बहुत अधिक जावा अनुभव नहीं है, लेकिन मैं इसे C # /। NET में एक अच्छे अभ्यास के रूप में करना पसंद करता हूं क्योंकि यह भविष्य के विस्तार के लिए अनुमति देता है जहां कंक्रीट वर्गों के साथ असेंबली जो इंटरफेस को लागू करते हैं उन्हें नीचे सभी तरह से वितरित नहीं किया जा सकता है। ग्राहक क्योंकि वे एक बिचौलिया कारखाने या एक वेब सेवा परिदृश्य में तार के पार होते हैं।


2

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


2

मैं एक परियोजना पर कर रहा हूँ और यह इन कारणों से मेरे लिए अच्छा काम कर रहा है:

  • अलग-अलग पैक किए गए इंटरफेस और कार्यान्वयन विभिन्न प्रकार के मानचित्र या सेट के बजाय एक अलग उपयोग के मामले के लिए हैं। केवल पेड़ों (java.util.tree.Map, java.util.tree.Set) के लिए पैकेज होने का कोई कारण नहीं है। यह सिर्फ एक मानक डेटास्ट्रक्चर है, इसलिए इसे अन्य डेटास्ट्रक्चर के साथ जोड़ दें। हालाँकि, यदि आप एक पहेली गेम के साथ काम कर रहे हैं, जिसमें वास्तव में सरल डिबग इंटरफ़ेस और एक सुंदर उत्पादन इंटरफ़ेस है, तो इसके फ्रंट-एंड के हिस्से के रूप में आपके पास एक com.your.app.skin.debug और एक com.your.app हो सकता है। .skin.pretty मैं इन्हें एक ही पैकेज में नहीं डालूंगा, क्योंकि वे अलग-अलग काम करते हैं और मुझे पता है कि मैं एक ही पैकेज में दोनों के लिए कुछ अनौपचारिक नाम स्थान बनाने के लिए कुछ SmurfNamingConvention (DebugAttackSurface, DebugDefenceSurface, PrettyAttackSurack आदि) का सहारा लूंगा।

  • अलग-अलग पैकेजों में संबंधित इंटरफेस और कार्यान्वयन खोजने की समस्या के लिए मेरा वर्कअराउंड मेरे पैकेज के लिए एक नामकरण कॉन्फ़िगरेशन को अपनाना है। उदाहरण के लिए, मैं com.your.app.skin.framework में अपने सभी इंटरफेस रख सकता हूं, और यह जान सकता हूं कि पैकेज ट्री के समान स्तर पर अन्य पैकेज कार्यान्वयन हैं। नुकसान यह है कि यह एक अपरंपरागत सम्मेलन है। ईमानदारी से, मैं देखूंगा कि 6 महीने के समय में यह सम्मेलन कितना अच्छा है :)

  • मैं इस तकनीक का धार्मिक रूप से उपयोग नहीं करता हूं। ऐसे इंटरफेस हैं जो केवल एक विशेष कार्यान्वयन में समझ में आते हैं। मैं उन्हें फ्रेमवर्क पैकेज में नहीं रखता। कुछ पैकेज हैं जहां ऐसा नहीं लगता है कि मैं 40 अलग कार्यान्वयन कक्षाएं बनाने जा रहा हूं, इसलिए मैं परेशान नहीं हूं।

  • मेरे आवेदन में गिटार का उपयोग किया गया है और इसमें बहुत सारे इंटरफेस हैं।

प्रोग्राम डिज़ाइन के प्रश्नों में आम तौर पर लाभ और कमियां शामिल होती हैं और सभी उत्तर में एक-आकार-फिट नहीं होता है। जैसे आप कभी भी 200-लाइन प्रोग्राम में इस तकनीक का उपयोग क्यों करेंगे? यह मेरे लिए समझ में आता है, मेरी विशिष्ट समस्या के लिए, मेरे अन्य वास्तुशिल्प विकल्पों को देखते हुए। :)


1

मैं उन्हें एक ही पैकेज में पसंद करता हूं। विशेष रूप से इंटरफेस के लिए एक पैकेज बनाने के लिए व्यर्थ लगता है। यह उन टीमों के लिए विशेष रूप से बेमानी है जो बस अपने इंटरफ़ेस प्रीफ़िक्स और प्रत्यय (जैसे "I", और जावा के लिए "Impl") से प्यार करते हैं।

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


0

उन्हें उन पैकेजों में रखें जो आपकी परियोजनाओं को दर्शाते हैं। यदि वे एक ही परियोजना का हिस्सा हैं, तो इंटरफेस और कार्यान्वयन को एक साथ रखना ठीक और सामान्य है, लेकिन यदि आप एक एपीआई लिख रहे हैं, तो संभवतः कोई और अपने प्रोजेक्ट के लिए प्रासंगिक पैकेज नाम का चयन करेगा।

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


0

मुझे लगता है कि यह ध्यान रखना महत्वपूर्ण है कि OSGi ढांचे के लिए, यह अच्छा है कि वे अलग-अलग पैकेजों में हैं ताकि आप कार्यान्वयन पैकेजों को छिपाते हुए एक पूरे पैकेज को आसानी से निर्यात कर सकें।


-1

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


आपको जिन चीजों को सूचीबद्ध किया गया है, उन्हें लागू करने के लिए आपको एक अलग पैकेज में कार्यान्वयन करने की आवश्यकता नहीं है
क्रॉउल जूल

यह उचित है, लेकिन मुझे अभी भी लगता है कि आवश्यकताओं के "बिल्ड टाइम बनाम रन टाइम में मौजूद" अंतर अलग से पैकेजिंग के लिए एक सम्मोहक मामला है। मैंने उस स्पष्ट रूप से प्रतिबिंबित करने के लिए पाठ को अद्यतन किया।
टायसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.