গেটার্স ব্যবহার করে ধ্রুবকগুলি এড়ানো ভাল অভ্যাস?


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()ইতিমধ্যে একটি অপ্রীতিকর পড়া, কোনও কোডকে একটি ভূমিকার সাথে তুলনা করা এটি আরও বেশি দুর্দশাগ্রস্ত করে তোলে।
এমএসডব্লিউ

উত্তর:


47

প্রথমে, দয়া করে নোট করুন যে এর মতো কিছু করা লেনদেনের আইনentity.underlyingEntity.underlyingEntity.method() অনুযায়ী কোড গন্ধ হিসাবে বিবেচিত হয় । এইভাবে, আপনি গ্রাহকের কাছে প্রচুর বাস্তবায়ন বিবরণ প্রকাশ করছেন। এবং এই জাতীয় ব্যবস্থার প্রতিটি সম্প্রসারণ বা সংশোধন করার প্রয়োজনীয়তা অনেক ক্ষতি করবে।

সুতরাং এটি দেওয়া, আমি আপনাকে কোডসইনচায়োসের মতামত অনুসারে একটি HasRoleবা IsAdminপদ্ধতি থাকার পরামর্শ Userদিচ্ছি। এইভাবে, ব্যবহারকারীর উপর কীভাবে ভূমিকাগুলি প্রয়োগ করা হয় তা ভোক্তার জন্য বাস্তবায়নের বিশদটি থেকে যায়। এবং ব্যবহারকারীকে তার ভূমিকার বিবরণ সম্পর্কে জিজ্ঞাসা করার পরিবর্তে তার ভূমিকা কী তা জিজ্ঞাসা করা এবং তার ভিত্তিতে সিদ্ধান্ত নেওয়া আরও স্বাভাবিক মনে হয়।


প্রয়োজন না হলে দয়া করে stringএর ব্যবহার এড়াতে দয়া করে । nameপরিবর্তনশীল একটি ভাল উদাহরণ stringকারণ বিষয়বস্তু আগে অজানা। অন্যদিকে, roleআপনার দুটি স্বতন্ত্র মান রয়েছে যা সংকলনের সময়ে সুপরিচিত, আপনি আরও শক্তিশালী টাইপিং ব্যবহার করতে চাইবেন। এখানেই গণনার ধরণ আসে ...

তুলনা করা

public bool HasRole(string role)

সঙ্গে

public enum Role { Admin, User }

public bool HasRole(Role role)

দ্বিতীয় কেসটি আমাকে আরও অনেক ধারণা দেয় যে আমার চারপাশে কী ঘটবে। stringআপনার ভূমিকার ধ্রুবক সম্পর্কে যদি আমার কোনও ধারণা না থাকে তবে এটি ভুলভাবে আমাকে একটি অবৈধ পাস করতে বাধা দেয় ।


এরপরে ভূমিকাটি কীভাবে প্রদর্শিত হবে তার সিদ্ধান্ত। আপনি হয় ব্যবহারকারীর উপর সরাসরি সঞ্চিত এনাম ব্যবহার করতে পারেন:

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
পুনরায় "উদাহরণ.property.property.method () ..." তরল জিনিস কি তাই না ?
পিটার মর্টেনসেন

2
@ পিটারমোরটেনসেন এটি সাবলীল ইন্টারফেসের চেয়ে আলাদা। প্রকারভেদে একটি সাবলীল ইন্টারফেস Xআপনাকে অবশ্যই ফাংশন কলগুলির মতো স্ট্রিং তৈরি করতে দেয় X.foo().bar().fee()...। এই সাশ্রয়ী ইন্টারফেসে, ফু, বার এবং ফি সবই শ্রেণীর অভ্যন্তরে ফাংশন হবে Xকোনও ধরণের কোনও বস্তু ফেরত X। তবে এই উদাহরণে উল্লিখিত 'উদাহরণ.property.property.method () এর জন্য দুটি propertyকল আসলে পৃথক শ্রেণিতে থাকবে। সেখানে সমস্যাটি হ'ল নিম্ন স্তরের বিশদটি ধরে রাখতে আপনি বিমূর্ততার কয়েকটি স্তর পেরিয়ে যাচ্ছেন।
শাজ

10
উত্তম উত্তর, তবে ল অফ ডিমিটার কোনও বিন্দু গণনা অনুশীলন নয়। instance.property.property.method()অগত্যা লঙ্ঘন বা এমনকি কোডের গন্ধ নয়; আপনি অবজেক্টস বা ডেটা স্ট্রাকচারের সাথে কাজ করছেন কিনা তা নির্ভর করে। Node.Parent.RightChild.Remove()সম্ভবত এলওডির লঙ্ঘন নয় (যদিও অন্যান্য কারণে দুর্গন্ধযুক্ত)। var role = User.Role; var roleCode = role.Code; var isAdmin = roleCode == ADMIN;আমি অবশ্যই "শুধুমাত্র একটি বিন্দু ব্যবহার করি" এই সত্ত্বেও প্রায় অবশ্যই লঙ্ঘন।
কার্ল লেথ

1
আমি বুঝতে পারি যে instance.property.property.method()এটি এলওডির লঙ্ঘন, তবে ওপিতে রয়েছে instance.method().method()যা ভাল হওয়া উচিত। আপনার শেষ উদাহরণে, এত বেশি বয়লারপ্লেট কোড রয়েছে Userযা কেবলমাত্র এর জন্য একটি মুখের কাজ করে Role
বার্গি

9

সঞ্চিত কোডটি অ্যাডমিন কোড কিনা তা যাচাই করার জন্য এটি কোনও ফাংশন বোধ করার মতো মনে হচ্ছে। আপনি যা জানতে চান তা হ'ল সেই ব্যক্তি প্রশাসক কিনা। সুতরাং আপনি যদি ধ্রুবকগুলি প্রকাশ করতে চান না, তবে আপনার একটি কোডও প্রকাশ করা উচিত নয় এবং পদ্ধতিগুলিকে অ্যাডমিন () এবং ইসুজার () বলা হয়।

এটি বলেছিল, "যদি ইউজার.জেটরোল ()। গেটকোড () == ভূমিকা.CODE_ADMIN" কেবল একজন ব্যবহারকারী একজন প্রশাসক কিনা তা যাচাই করার জন্য সত্যই মুষ্টিমেয়। কোনও বিকাশকারীকে সেই লাইনটি লেখার জন্য কতটি জিনিস মনে রাখতে হবে? তার বা তার মনে রাখতে হবে যে ব্যবহারকারীর ভূমিকা আছে, একটি ভূমিকার একটি কোড রয়েছে, এবং ভূমিকা শ্রেণীর কোডগুলির জন্য ধ্রুবক রয়েছে। এটি প্রচুর তথ্য যা সম্পূর্ণরূপে বাস্তবায়ন সম্পর্কে।


3
এটি আরও খারাপ: একজন ব্যবহারকারীর সর্বদা একটি ভূমিকা থাকে, কম বা কমও নয়।
অনুচ্ছেদে

5

অন্যরা ইতিমধ্যে যা পোস্ট করেছে সেগুলি ছাড়াও, আপনার মনে রাখা উচিত যে ধ্রুবকটি ব্যবহারের ক্ষেত্রে সরাসরি অন্য একটি অসুবিধা থাকে: যদি আপনি ব্যবহারকারীর অধিকারগুলি কীভাবে পরিচালনা করেন কিছু পরিবর্তন হয়, সেই সমস্ত জায়গাগুলিকেও পরিবর্তন করা দরকার ।

এবং এটি বাড়ানোর জন্য এটি ভয়ঙ্কর করে তোলে। সম্ভবত আপনি একটি পর্যায়ে একটি সুপার ব্যবহারকারী টাইপ করতে চান, সম্ভবত অ্যাডমিন অধিকার আছে। এনক্যাপসুলেশন সহ এটি যুক্ত করার জন্য মূলত একটি ওয়ান-লাইনার।

এটি কেবল সংক্ষিপ্ত এবং পরিষ্কার নয়, এটি ব্যবহার করা এবং বোঝাও সহজ। এবং - সম্ভবত বেশিরভাগ ক্ষেত্রে - ভুল হওয়া শক্ত।


2

যদিও আমি ধ্রুবকগুলি এড়াতে এবং কোনও পদ্ধতি isFoo()ইত্যাদি রাখার জন্য পরামর্শগুলির সাথে বেশিরভাগভাবে একমত আছি , তবে একটি সম্ভাব্য প্রতিদ্বন্দ্বিতা।

যদি এখানে কয়েকশো ধ্রুবক থাকে এবং কলগুলি খুব কম ব্যবহৃত হয় তবে এটি শত শত কনস্ট্যান্ট 1, আইস কনস্ট্যান্ট 2, পদ্ধতিগুলি লেখার প্রচেষ্টাটির পক্ষে কার্যকর হবে না। এই বিশেষত, অস্বাভাবিক ক্ষেত্রে, ধ্রুবকগুলি ব্যবহার করা যুক্তিসঙ্গত।

নোট করুন যে এনামগুলি ব্যবহার করে বা hasRole()শত শত পদ্ধতিতে লেখার প্রয়োজনীয়তা এড়ানো যায়, তাই এটি বিশ্বের সম্ভাব্য সেরা।


2

আমি মনে করি না যে আপনি উপস্থাপন করেছেন যে কোনও একটিই মূলত ভুল।

আমি দেখতে পাচ্ছি যে আপনি যে একটি জিনিসকে আমি পুরোপুরি ভুল বলব সেটিকে আপনি প্রস্তাব করেননি: ভূমিকা শ্রেণীর বাইরে ফাংশনগুলিতে রোল কোডগুলিকে কঠোর কোডিং od এটাই:

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

আমি অবশ্যই বলতে চাই ভুল। আমি এমন প্রোগ্রামগুলি দেখেছি যা এটি করে এবং তারপরে রহস্যজনক ত্রুটি পাওয়া যায় কারণ কেউ স্ট্রিংটি ভুল বানান করে। আমি একটি সময় স্মরণ করি যে কোনও প্রোগ্রামার "স্টক" লিখেছিলেন যখন ফাংশনটি "স্টক" এর জন্য যাচ্ছিল।

যদি 100 টি বিভিন্ন ভূমিকা থাকে তবে আমি প্রতিটি সম্ভাব্যতার জন্য যাচাই করার জন্য 100 ফাংশন লিখতে খুব অনীহা করব। আপনি সম্ভবত প্রথম ফাংশনটি লিখে এবং তারপরে এটি 99 বার অনুলিপি করে এবং এটিকে তৈরি করে দিতেন এবং আপনি কতটা বাজি রাখতে চান যে সেই 99 টি অনুলির মধ্যে আপনি পরীক্ষাটি আপডেট করতে ভুলে গেছেন বা আপনি যখন একসাথে বন্ধ হয়ে যাবেন তখন আপনি তালিকা দিয়ে দৌড়েছিলেন, সুতরাং আপনার এখন আছে

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))

তারপরে ব্যবহারকারী শ্রেণিকে কীভাবে কোনও ভূমিকা পরীক্ষা করতে হয় তা জানতে দিন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.