क्या गेटर्स का उपयोग करके स्थिरांक से बचने के लिए यह एक अच्छा अभ्यास है?


25

क्या गेटर्स द्वारा कक्षाओं के बाहर उपयोग किए जाने वाले स्थिरांक को बदलना एक अच्छा अभ्यास है?

एक उदाहरण के रूप में, क्या इसका उपयोग करना बेहतर है if User.getRole().getCode() == Role.CODE_ADMINया if User.getRole().isCodeAdmin()?

इस वर्ग के लिए नेतृत्व करेंगे:

class Role {
    constant CODE_ADMIN = "admin"
    constant CODE_USER = "user"

    private code

    getRoleCode() {
       return Role.code
    }

    isCodeAdmin () {
       return Role.code == Role.CODE_ADMIN
    }

    isCodeUser () {
       return Role.code == Role.CODE_USER
    }
}

15
मैं बल्कि कुछ का उपयोग करना चाहते हैं User.HasRole(Role.Admin)
कोडइन्चोस


4
सिद्धांत मत पूछो सिद्धांत की जाँच करें ।
एंडी

मैं आधार पर सवाल करता हूं: User.getRole().getCode()पहले से ही एक अप्रिय रीड है, एक कोड की भूमिका की तुलना करने से यह अभी तक अधिक अस्पष्ट है।
msw

जवाबों:


47

सबसे पहले, कृपया ध्यान दें कि कुछ ऐसा करना कानून के कानून केentity.underlyingEntity.underlyingEntity.method() अनुसार कोड गंध माना जाता है । इस तरह, आप उपभोक्ता को बहुत सारे कार्यान्वयन विवरण दिखा रहे हैं। और ऐसी प्रणाली के विस्तार या संशोधन की प्रत्येक आवश्यकता को बहुत नुकसान होगा।

तो यह देखते हुए, मैं आपको CodeInChaos की टिप्पणी के अनुसार एक विधि HasRoleया IsAdminविधि रखने की Userसलाह दूंगा। इस तरह, जिस तरह से उपयोगकर्ता पर भूमिकाओं को लागू किया जाता है, वह उपभोक्ता के लिए कार्यान्वयन विवरण रहता है। और उपयोगकर्ता को यह पूछना और भी स्वाभाविक लगता है कि उसकी भूमिका के बारे में उससे पूछने और उसके आधार पर निर्णय लेने के बजाय उसकी भूमिका क्या है।


stringजब तक आवश्यक न हो, कृपया एस का उपयोग करने से भी बचें । चर nameका एक अच्छा उदाहरण है stringक्योंकि सामग्री पहले से अज्ञात है। दूसरी ओर, ऐसा कुछ roleजहां आपके पास दो अलग-अलग मूल्य हैं जो संकलन समय पर अच्छी तरह से ज्ञात हैं, आप बेहतर टाइपिंग का उपयोग करेंगे। यहीं पर एन्यूमरेशन टाइप चलता है ...

तुलना

public bool HasRole(string role)

साथ में

public enum Role { Admin, User }

public bool HasRole(Role role)

दूसरा मामला मुझे बहुत अधिक विचार देता है कि मुझे क्या करना चाहिए। यह मुझे गलत तरीके से अवैध रूप से गुजरने से रोकता है, जब मुझे stringआपकी भूमिका स्थिरांक के बारे में कोई पता नहीं था।


इसके बाद फैसला होता है कि भूमिका कैसी होगी। आप या तो enum का उपयोग सीधे उपयोगकर्ता पर संग्रहीत कर सकते हैं:

public enum Role
{
    Admin,
    User
}

public class User
{
    private Role _role;

    public bool HasRole(Role role)
    {
        return _role == role;
    }

    // or
    public bool IsAdmin()
    {
        return _role == Role.Admin;
    }
}

दूसरी ओर, यदि आप चाहते हैं कि आपकी भूमिका स्वयं एक व्यवहार की हो, तो यह निश्चित रूप से फिर से विवरण को छिपाना चाहिए कि इसका प्रकार कैसे तय किया जा रहा है:

public enum RoleType
{
    User,
    Admin
}

public class Role
{
    private RoleType _roleType;

    public bool IsAdmin()
    {
        return _roleType == RoleType.Admin;
    }

    public bool IsUser()
    {
        return _roleType == RoleType.User;
    }

    // more role-specific logic...
}

public class User
{
    private Role _role;

    public bool IsAdmin()
    {
        return _role.IsAdmin();
    }

    public bool IsUser()
    {
        return _role.IsUser();
    }
}

यह हालांकि काफी क्रियात्मक है और प्रत्येक भूमिका के साथ जटिलता बढ़ेगी - आमतौर पर यह है कि जब आप पूरी तरह से डेमेटर के कानून का पालन करने का प्रयास करते हैं तो कोड कैसे समाप्त होता है। आपको सिस्टम की ठोस आवश्यकताओं के आधार पर डिज़ाइन में सुधार करना चाहिए।

आपके प्रश्न के अनुसार, मुझे लगता है कि आप बेहतर विकल्प के साथ सीधे एनम के साथ पहले विकल्प पर जाएंगे User। क्या आपको अधिक तर्क की आवश्यकता है Role, दूसरे विकल्प को एक प्रारंभिक बिंदु माना जाना चाहिए।


10
काश यह वह तरीका होता, जिस तरह से लोग हर जगह करते हैं। केवल जाँच के लिए एक निजीकरण विशेषता पर एक गेट्टर होने के कारण कि क्या यह किसी और चीज़ के बराबर है, इस तरह की एक भयानक प्रथा है।
एंडी

2
पुन: "Inst.property.property.method () ..." यह तरल पदार्थ नहीं है ?
पीटर मोर्टेनसेन

2
@PeterMortensen यह एक धाराप्रवाह इंटरफ़ेस से अलग है। प्रकार पर एक धाराप्रवाह इंटरफ़ेस Xनिश्चित रूप से आपको फ़ंक्शन कॉल के तार बनाने की अनुमति देगा X.foo().bar().fee()...। इस धाराप्रवाह इंटरफ़ेस में, फू, बार, और शुल्क सभी Xप्रकार के ऑब्जेक्ट लौटाने वाले वर्ग के अंदर कार्य होंगे X। लेकिन इस उदाहरण में उल्लिखित 'उदाहरण.प्रोपर्टी.प्रोपरेटीमेथोड () के लिए, दो propertyकॉल वास्तव में अलग-अलग कक्षाओं में होंगे। समस्या यह है कि आप निम्न स्तर के विवरण को प्राप्त करने के लिए अमूर्तता की कई परतों से गुजर रहे हैं।
शाज़

10
अच्छा जवाब है, लेकिन लॉ ऑफ डेमेटर एक डॉट-काउंटिंग अभ्यास नहीं है। instance.property.property.method()जरूरी नहीं कि एक उल्लंघन या एक कोड गंध भी हो; यह इस बात पर निर्भर करता है कि आप वस्तुओं या डेटा संरचनाओं के साथ काम कर रहे हैं या नहीं। Node.Parent.RightChild.Remove()शायद LoD का उल्लंघन नहीं है (हालांकि अन्य कारणों से बदबूदार)। var role = User.Role; var roleCode = role.Code; var isAdmin = roleCode == ADMIN;लगभग निश्चित रूप से एक उल्लंघन है, इस तथ्य के बावजूद कि मैंने हमेशा "केवल एक डॉट का उपयोग किया"।
कार्ल लेथ

1
मैं समझता हूं कि instance.property.property.method()यह LoD का उल्लंघन है, लेकिन ओपी के पास instance.method().method()ठीक होना चाहिए। आपके अंतिम उदाहरण में, बहुत अधिक बॉयलरप्लेट कोड है Userजो केवल के लिए एक मुखौटा के रूप में कार्य करता है Role
बर्गी

9

ऐसा लगता है कि जो कोड संचित है उसे जांचने के लिए एक फ़ंक्शन है जो कि व्यवस्थापक कोड है। क्या आप वास्तव में जानना चाहते हैं कि क्या वह व्यक्ति एक व्यवस्थापक है। इसलिए यदि आप स्थिरांक को उजागर नहीं करना चाहते हैं, तो आपको यह भी उजागर नहीं करना चाहिए कि एक कोड है, और तरीकों को कॉल करें Admin () और isUser ()।

उस ने कहा, "अगर User.getRole ()। GetCode () == Role.CODE_ADMIN" वास्तव में केवल यह जांचने के लिए एक मुट्ठी भर है कि एक उपयोगकर्ता एक व्यवस्थापक है। एक डेवलपर को उस लाइन को लिखने के लिए कितनी चीजें याद रखनी पड़ती हैं? उसे या उसे यह याद रखना होगा कि एक उपयोगकर्ता की एक भूमिका है, एक भूमिका में एक कोड है, और भूमिका वर्ग में कोड के लिए स्थिरांक हैं। यह बहुत सारी जानकारी है जो विशुद्ध रूप से कार्यान्वयन के बारे में है।


3
यह बदतर है: कि एक उपयोगकर्ता की हमेशा एक भूमिका होती है, न अधिक और न ही कम।
डेडुप्लिकेटर

5

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

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

यह न केवल छोटा और साफ है, इसका उपयोग करना और समझना भी आसान है। और - शायद सबसे अधिक - यह गलत होना मुश्किल है।


2

जबकि मैं मोटे तौर पर स्थिरांक से बचने और एक विधि isFoo()आदि के सुझावों से सहमत हूं , एक संभव प्रतिधारण।

यदि इनमें से सैकड़ों स्थिरांक हैं, और कॉल बहुत कम उपयोग की जाती हैं, तो यह सैकड़ों isCstst1, isConstant2, विधियों को लिखने के प्रयास के लायक नहीं हो सकता है। इस विशेष, असामान्य मामले में, स्थिरांक का उपयोग उचित है।

ध्यान दें कि एनमों का उपयोग करना या hasRole()सैकड़ों तरीकों को लिखने की आवश्यकता से बचा जाता है, इसलिए यह दुनिया भर में संभव है।


2

मुझे नहीं लगता कि आपके द्वारा प्रस्तुत विकल्पों में से कोई भी मौलिक रूप से गलत है।

मुझे लगता है कि आपने एक बात का सुझाव नहीं दिया है कि मैं सपाट रूप से गलत कहूंगा: भूमिका वर्ग के बाहर के कार्यों में भूमिका कोड को हार्ड-कोड करना। अर्थात्:

if (user.getRole().equals("Administrator")) ...

मैं कहता हूँ निश्चित रूप से गलत है। मैंने ऐसे कार्यक्रम देखे हैं जो ऐसा करते हैं और फिर रहस्यमय त्रुटियां प्राप्त करते हैं क्योंकि किसी ने स्ट्रिंग को गलत तरीके से लिखा था। मुझे याद है एक बार जब एक प्रोग्रामर ने "स्टॉक" लिखा था जब फ़ंक्शन "स्टॉक" के लिए जाँच कर रहा था।

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

public bool isActuary() { return code==Role.ACTUARY; }
public bool isAccountant() { return code==Role.ACTUARY; }
... etc ...

व्यक्तिगत रूप से, मैं कॉल की श्रृंखला से भी बचूंगा। मैं बल्कि लिखूंगा

if (user.getRole().equals(Role.FOOBATER))

फिर

if (user.getRole().getRoleCode()==Role.FOOBATER_CODE)

और उस बिंदु पर क्यों नोट लिखें:

if (user.hasRole(Role.FOOBATER))

फिर उपयोगकर्ता वर्ग को एक भूमिका की जांच करने का तरीका बताएं।

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