मुझे JavaBeans के बजाय अपरिवर्तनीय POJOs का उपयोग क्यों नहीं करना चाहिए?


79

मैंने अभी कुछ जावा अनुप्रयोगों को लागू किया है, अब तक केवल डेस्कटॉप अनुप्रयोग। मैं म्यूटेटर (सेटर्स और गेटर्स ), जिसे JavaBeans भी कहा जाता है, का उपयोग करने के बजाय एप्लिकेशन में डेटा पास करने के लिए अपरिवर्तनीय वस्तुओं का उपयोग करना पसंद करता हूं ।

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

आइटम 15 में अपरिवर्तनीय वस्तुओं की भी सिफारिश की जाती है : उत्परिवर्तन को कम करें , प्रभावी जावा 2ed

यदि मेरे पास जावाबीन केPerson रूप में लागू की गई कोई वस्तु है, तो ऐसा लगेगा:

public class Person {
    private String name;
    private Place birthPlace;

    public Person() {}

    public setName(String name) {
        this.name = name;
    }

    public setBirthPlace(Place birthPlace) {
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

और Personएक अपरिवर्तनीय वस्तु के रूप में लागू किया गया :

public class Person {
    private final String name;
    private final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

या structC में करीब :

public class Person {
    public final String name;
    public final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }
}

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

बस, मुझे समझ में नहीं आता है कि जावाबीन का उपयोग करना बेहतर क्यों है, या यदि मैं अपने अपरिवर्तनीय पीओजेओ के साथ जा सकता हूं या नहीं रखूं?

जावा पुस्तकालयों में से कई के लिए JavaBeans का बेहतर समर्थन प्रतीत होता है, लेकिन हो सकता है कि अपरिवर्तनीय POJOs के लिए अधिक समर्थन समय के साथ अधिक लोकप्रिय हो जाए?


1
मुझे लगता है कि आपका मतलब है आइटम 15: उत्परिवर्तन को कम करें , न कि * कम से कम अपरिवर्तनीयता "
मैट बी

@matt: धन्यवाद =) मैंने इसे अभी अपडेट किया है।
जोनास

7
आपका अपरिवर्तनीय दृष्टिकोण बहुत अच्छा है, आपको बहुत सारे थ्रेड मुद्दों को बचाता है। +1
व्हिस्की सिएरा

1
यदि आपको JPA
नील मैकगिगॉन

जवाबों:


78

JavaBeans को प्राथमिकता दें

  • आपको उन परिवेशों के साथ बातचीत करनी होगी जो उनसे उम्मीद करते हैं
  • आपके पास बहुत से गुण हैं जिनके लिए तात्कालिकता पर सभी आरंभीकरण करना असुविधाजनक होगा
  • आपके पास वह राज्य है जो किसी कारण से महंगा या असंभव है लेकिन म्यूटेशन की आवश्यकता है
  • आपको लगता है कि कुछ बिंदु पर आपको यह बदलना पड़ सकता है कि गुणों तक कैसे पहुँचा जा सकता है (जैसे संग्रहीत से परिकलित मानों तक पहुँचना, प्राधिकार तक पहुँचना, आदि)
  • आप कोडिंग मानकों के अनुरूप होना चाहते हैं, जो नासमझी से यह जोर देते हैं कि यह जावाबीन का उपयोग करने के लिए किसी तरह अधिक "वस्तु-उन्मुख" है

जब अपरिवर्तनीय POJOs को प्राथमिकता दें

  • आपके पास सरल गुणों की एक छोटी संख्या है
  • आपको JavaBean सम्मेलनों को मानते हुए पर्यावरण के साथ बातचीत करने की आवश्यकता नहीं है
  • यह आसान है (या बहुत कम से कम संभव है) अपनी वस्तु की क्लोनिंग करते समय राज्य की नकल करना
  • आप कभी भी ऑब्जेक्ट को क्लोन करने की योजना नहीं बनाते हैं
  • आपको पूरा यकीन है कि आपको कभी भी संशोधित नहीं करना होगा कि ऊपर की तरह कैसे संपत्तियों तक पहुँचा जा सकता है
  • आप अपने कोड को पर्याप्त रूप से "ऑब्जेक्ट-ओरिएंटेड" नहीं होने के बारे में सुनकर (या व्यंग्य) सुनकर बुरा नहीं मानते हैं

लिस्टिंग के लिए +1, और आपके नाम के लिए लगभग -1 :) आखिरकार, हर कोई जानता है कि यह मेरी राय है जो सही है। प्रत्येक व्यक्ति को निश्चित रूप से एक डिस्कवर्ल्ड अर्थ में परिभाषित किया जा रहा है।
एक्सट्रैनन

12
कंस्ट्रक्टर में सीमा की जाँच और इनपुट सत्यापन किया जा सकता है। यदि इनपुट अमान्य है या बाध्य है, तो मैं ऑब्जेक्ट नहीं बनाना चाहता।
जोनास

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

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

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

39

मुझे आश्चर्य हुआ कि थ्रेड शब्द इस चर्चा में कहीं दिखाई नहीं दिया।

अपरिवर्तनीय वर्गों के मुख्य लाभों में से एक यह है कि वे बिना किसी उत्परिवर्तित, साझा स्थिति के कारण स्वाभाविक रूप से अधिक थ्रेड सुरक्षित हैं।

न केवल यह आपके कोडिंग को आसान बनाता है, यह आपको साइड इफेक्ट के रूप में दो प्रदर्शन लाभ भी देगा:

  • सिंक्रनाइज़ेशन की कम आवश्यकता।

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

मैं वास्तव में JavaBean शैली कक्षाओं के बजाय अपरिवर्तनीय वस्तुओं की ओर बढ़ने की कोशिश कर रहा हूं। गेटर्स और सेटर के माध्यम से वस्तुओं की हिम्मत को उजागर करना संभवतः डिफ़ॉल्ट विकल्प नहीं होना चाहिए।


18

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

विचार करें कि आपके व्यक्ति के पास बहुत सारे क्षेत्र हैं जैसे, पहला, मध्य, अंतिम नाम, जन्म तिथि, परिवार के सदस्य, शिक्षा, नौकरी, वेतन आदि।

और वह व्यक्ति एक महिला होने के लिए होता है, जिसने अभी-अभी शादी की है और अपना अंतिम नाम बदलना स्वीकार कर लिया है, और आपको डेटाबेस को अपडेट करने की आवश्यकता है।

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

यदि यह एक जावा बीन था तो आप केवल सेटलैमनाम () कर सकते हैं और इसे बचा सकते हैं।

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


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

इसके अलावा, एक "वास्तविक" एप्लिकेशन में संभवतः कुछ प्रकार की मेमोरी या वितरित कैश (EHCache, आदि) होंगे जो आपके डोमेन ऑब्जेक्ट होते हैं। यदि आप जानते हैं कि आपकी वस्तुएँ अपरिवर्तनीय हैं, तो आपको कॉपी-ऑन-रीड के ओवरहेड को लाइक करने की आवश्यकता नहीं है। आप कैश अखंडता के बारे में चिंता किए बिना इन-मेमोरी ऑब्जेक्ट को सुरक्षित रूप से पुनर्प्राप्त और उपयोग कर सकते हैं। IMHO, इस प्रकार के व्यावसायिक डोमेन ऑब्जेक्ट के लिए, आप हमेशा अपरिवर्तनीय ऑब्जेक्ट चाहते हैं। स्थानीय वस्तुओं और कुछ अन्य विशेष मामलों के लिए म्यूट करने योग्य वस्तुएं ठीक हैं, जो कि मेरे पास यहां आने के लिए वर्ण नहीं हैं।
२०:१६

7

अन्य उत्तरों का संक्षेप में मुझे लगता है कि:

  • अयोग्यता सुगमता को सुगम बनाती है ( संरचना को संदर्भ द्वारा पारित किया जा सकता है और आप जानते हैं कि कुछ भी दोषपूर्ण / दुर्भावनापूर्ण ग्राहक द्वारा नष्ट नहीं किया जाएगा) और कोड सादगी
  • उत्परिवर्तन से एकरूपता की सुविधा मिलती है : वसंत और अन्य रूपरेखाएँ बिना तर्क के एक वस्तु का निर्माण करती हैं, वस्तु के गुण निर्धारित करती हैं, और वोई là । डेटा और बचत संशोधनों को देने के लिए एक ही वर्ग का उपयोग करके इंटरफेस को आसान बनाते हैं (आपको इसकी आवश्यकता नहीं है get(id): Clientऔर save(MutableClient)MutableClient ग्राहक के कुछ वंशज हैं।

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

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


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

3

जावा 7 से आपके पास अपरिवर्तनीय फलियां हो सकती हैं, दोनों दुनिया के सर्वश्रेष्ठ। अपने निर्माता पर एनोटेशन @ConstructorProperties का उपयोग करें।

public class Person {
    private final String name;
    private final Place birthPlace;

    @ConstructorProperties({"name", "birthPlace"})
    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}


1

मुझे नहीं लगता कि अपरिवर्तनीय वस्तुओं को ईमानदार होने के लिए सभी लोकप्रिय मिलेंगे।

मुझे इसके फायदे दिखाई देते हैं, लेकिन हाइबरनेट और स्प्रिंग जैसी रूपरेखा वर्तमान में बहुत प्रचलन में है (और अच्छे कारण के लिए भी), और वे वास्तव में बीन्स के साथ सबसे अच्छा काम करते हैं।

इसलिए मुझे नहीं लगता कि अपरिवर्तनीयता खराब है, लेकिन यह निश्चित रूप से वर्तमान रूपरेखा के साथ आपके एकीकरण विकल्पों को सीमित करेगा।

संपादित करें टिप्पणी मुझे अपना जवाब थोड़ा स्पष्ट करने के लिए प्रेरित करती है।

निश्चित रूप से समस्या वाले क्षेत्र हैं जहां अपरिवर्तनीयता बहुत उपयोगी है, और वास्तव में इसका उपयोग किया जाता है। लेकिन मुझे लगता है कि मौजूदा डिफॉल्ट ही ऐसा प्रतीत होता है कि जैसा कि अपेक्षित है वैसा ही है, और केवल अपरिवर्तनीय है अगर इसका स्पष्ट लाभ है।

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


2
IoC / DI का विचार राज्य की स्थापना / इंजेक्शन लगाने पर आधारित है, यही कारण है कि वसंत में अपरिवर्तनीयता इतनी लोकप्रिय नहीं है। हालांकि जोडा-टाइम सही से किए गए अपरिवर्तनीयता का एक अच्छा उदाहरण है।
lunohodov

आप वसंत के साथ निर्भरता को इंजेक्ट करने के लिए कंस्ट्रक्टर आर्ग्स का उपयोग कर सकते हैं, ऐसा लगता है कि बहुत से लोग ऐसा नहीं करते हैं (संभवतः क्योंकि जब आपके पास बहुत अधिक निर्भरता होती है, तो 10+ पैरामीटर का निर्माण करने वाला डरावना होता है)।
आंद्रेई फियरबंटेनु

6
@lunohodov: मैंने DI / IoC के लिए Google Guice का उपयोग किया है और कंस्ट्रक्टर को निर्भरता इंजेक्शन करने के लिए कोई समस्या नहीं है।
जोनास

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

जो लोग अपरिवर्तनीय वस्तुओं का उपयोग करते हैं वे कभी-कभी ऑब्जेक्ट पहचान के महत्व को पहचानने में विफल होते हैं, और यह तथ्य कि उत्परिवर्तित वस्तुओं की अपरिवर्तनीय पहचान हो सकती है जो अपरिवर्तनीय वस्तुओं को नहीं कर सकती है।
सुपरकैट

0

जावा में प्रोग्रामिंग के मामले में अपरिवर्तनीय: कुछ ऐसा जो एक बार बनाया गया हो उसे कभी भी राज्य में परिवर्तन नहीं करना चाहिए, दोनों अपेक्षित या अप्रत्याशित!

यह तकनीक रक्षात्मक प्रोग्रामिंग में उपयोगी है जहां एक और इकाई राज्य में परिवर्तन को प्रेरित नहीं कर सकती है।

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

उदाहरण जहां आप बदलाव की उम्मीद करते हैं: वास्तव में अपरिवर्तनीयता की आवश्यकता नहीं है क्योंकि यह सही प्रोग्रामिंग प्रक्रियाओं में बाधा होगी।

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