যদি কোনও গেটের অবজেক্টের অবৈধ অবস্থা থাকে তবে কি তাকে ব্যতিক্রম করা উচিত?


55

আমি প্রায়শই এই সমস্যায় পড়ে যাই, বিশেষত জাভাতে, এমনকি যদি আমি মনে করি এটি একটি সাধারণ ওওপি সমস্যা। এটি: একটি ব্যতিক্রম উত্থাপন একটি ডিজাইনের সমস্যা প্রকাশ করে।

ধরুন আমার একটি ক্লাস আছে যার একটি String nameক্ষেত্র এবং String surnameক্ষেত্র রয়েছে।

তারপরে এটি কোনও ক্ষেত্রের ডকুমেন্টে প্রদর্শন করার জন্য কোনও ব্যক্তির পুরো নাম রচনা করতে এই ক্ষেত্রগুলি ব্যবহার করে, একটি চালান বলুন।

public void String name;
public void String surname;

public String getCompleteName() {return name + " " + surname;}

public void displayCompleteNameOnInvoice() {
    String completeName = getCompleteName();
    //do something with it....
}

displayCompleteNameOnInvoiceনাম নির্ধারিত হওয়ার আগে যদি ডাকা হয় তবে আমি এখন একটি ত্রুটি ছুঁড়ে দিয়ে আমার শ্রেণীর আচরণকে আরও শক্তিশালী করতে চাই । এটি একটি ভাল ধারণা বলে মনে হচ্ছে, তাই না?

আমি getCompleteNameপদ্ধতিতে একটি ব্যতিক্রম-উত্থাপন কোড যুক্ত করতে পারি । তবে এইভাবে আমি শ্রেণীর ব্যবহারকারীর সাথে একটি 'অন্তর্নিহিত' চুক্তি লঙ্ঘন করছি; সাধারণভাবে গ্রাহকরা যদি তাদের মানগুলি সেট না করে থাকে তবে তারা ব্যতিক্রম ছোঁড়ার কথা নয়। ঠিক আছে, এটি কোনও স্ট্যান্ডার্ড প্রাপ্তি নয় যেহেতু এটি কোনও একক ক্ষেত্র ফেরত না, তবে ব্যবহারকারীর দৃষ্টিকোণ থেকে পার্থক্যটি এটি সম্পর্কে ভাবতে খুব সূক্ষ্ম হতে পারে।

অথবা আমি ব্যতিক্রমটি ভিতরে থেকে ফেলে দিতে পারি displayCompleteNameOnInvoice। তবে এটি করার জন্য আমার সরাসরি nameবা surnameক্ষেত্রের পরীক্ষা করা উচিত এবং তা করা আমি প্রতিনিধিত্বমূলক বিমূর্তি লঙ্ঘন করব getCompleteName। পুরো নামটি পরীক্ষা করা এবং তৈরি করা এই পদ্ধতির দায়িত্ব responsibility এটি এমনকি সিদ্ধান্ত নেন পারে, অন্যান্য ডেটার উপর সিদ্ধান্ত ভিত্তিবিন্দু, যে কিছু কিছু ক্ষেত্রে এটা যথেষ্ট surname

সুতরাং শুধুমাত্র সম্ভাবনা পদ্ধতির শব্দার্থিক পরিবর্তন বলে মনে হয় getCompleteNameকরতে composeCompleteName, যে আরো একটি 'সক্রিয়' আচরণ এবং তার সাথে একটি ব্যতিক্রম নিক্ষেপ ক্ষমতা দাড়ায়।

এটি কি আরও ভাল ডিজাইনের সমাধান? আমি সর্বদা সরলতা এবং সঠিকতার মধ্যে সেরা ভারসাম্য খুঁজছি। এই সমস্যাটির জন্য কোনও নকশা রেফারেন্স আছে?


8
"সাধারণভাবে গ্রাহকরা যদি তাদের মান নির্ধারণ না করে তবে ব্যতিক্রম ছোঁড়ার কথা নয়।" - তখন তাদের কী করার কথা?
রোটেম

2
@ স্ক্রিপ্টিন তারপরে এই যুক্তি অনুসরণ করে displayCompleteNameOnInvoiceযদি কেবল getCompleteNameফেরত দেয় তবে ব্যতিক্রম nullকরতে পারেন, তাই না?
রোটেম

2
@ রোটেম এটি করতে পারেন প্রশ্নটি করা উচিত কিনা তা নিয়ে।
স্ক্রিপ্টিন

22
বিষয়টিতে , 'প্রথম নাম' এবং 'উপাধি' খুব সংকীর্ণ ধারণা কেন ফালতুহডস প্রোগ্রামার্স বিশ্বাস সম্পর্কে নামগুলি খুব ভাল পঠিত।
লার্স ভিক্লুন্ড

9
যদি আপনার অবজেক্টের একটি অবৈধ অবস্থা থাকতে পারে তবে আপনি ইতিমধ্যে খারাপ হয়ে গেছেন।
ব্যবহারকারী 253751

উত্তর:


151

কোনও নাম বরাদ্দ না করে আপনার ক্লাসটি নির্মাণের অনুমতি দেবেন না।


9
এটি আকর্ষণীয় তবে বেশ মৌলিক সমাধান। অনেক সময় আপনার ক্লাসগুলিকে আরও তরল হতে হবে, এমন রাজ্যের জন্য অনুমতি দেয় যা কেবল তখনই সমস্যা হয়ে দাঁড়ায় যখন নির্দিষ্ট পদ্ধতিগুলি বলা হয় অন্যথায় আপনি ছোট ক্লাসের প্রলাইফেরাইটন সহ শেষ করবেন যার জন্য খুব বেশি ব্যাখ্যা প্রয়োজন।
AgostinoX

71
এটি কোনও মন্তব্য নয়। যদি তিনি উত্তরে পরামর্শটি প্রয়োগ করেন তবে তার আর সমস্যা বর্ণিত হবে না। এটি একটি উত্তর।
ডেডএমজি

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

25
@ গ্যাनेट: আপনি পিএসইতে প্রতিটি প্রশ্নের মান এবং প্রতিটি উত্তরের প্রশ্ন নিয়ে এখানে দুর্দান্ত কাজ করেছেন তবে কখনও কখনও আপনি সামান্য কিছুটা ছোটও হন।
ডক ব্রাউন

9
যদি সেগুলি বৈধভাবে optionচ্ছিক হতে পারে তবে তার প্রথম স্থানে ফেলে দেওয়ার কোনও কারণ নেই।
ডেড এমএমজি

75

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

সুতরাং আপনি যদি তরলতা চান তবে বিল্ডার প্যাটার্নের মতো কিছু ব্যবহার করুন । বা অন্য যে কোনও কিছুই "আসল জিনিস" এর বিপরীতে নির্মাণে কোনও বস্তুর পৃথক সংস্কার, যেখানে পরেরটির বৈধ রাষ্ট্রের গ্যারান্টিযুক্ত এবং এটিই সেই রাজ্যে সংজ্ঞায়িত ক্রিয়াকলাপগুলি প্রকটভাবে প্রকাশ করে (যেমন getCompleteName)।


7
So if you want fluidity, use something like the builder pattern- তরলতা বা অপরিবর্তনীয়তা (যদি না আপনি কোনওভাবে বোঝাতে চান তবে)। যদি কেউ অপরিবর্তনীয় বস্তু তৈরি করতে চায় তবে কিছু মান স্থগিত করা প্রয়োজন, তবে অনুসরণ করার প্যাটার্নটি হ'ল বিল্ডার অবজেক্টে একে একে সেট করা এবং কেবলমাত্র যখন আমরা সঠিকর জন্য প্রয়োজনীয় সমস্ত মান সংগ্রহ করি তখনই কেবল অপরিবর্তনীয় একটি তৈরি করা যায় follow রাষ্ট্র ...
কনরাড মোরাউস্কি

1
@ কনরাডমোরওস্কি: আমি বিভ্রান্ত আপনি কি আমার বক্তব্যকে স্পষ্ট করছেন বা বিরোধ করছেন? ;)
back2dos

3
আমি এটির পরিপূরক দেওয়ার চেষ্টা করেছি ...
কনরাড মোরাউস্কি

40

একটি অবৈধ অবস্থা সহ কোনও বস্তু নেই।

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

সুতরাং, এই অংশটির জন্য প্রশ্নটি হল "আপনি নাম বা ছদ্মনামটি কেন বাতিল করতে দিচ্ছেন?" এটি যদি সঠিকভাবে কাজ করার জন্য ক্লাসে বৈধ যে কোনও জিনিস না হয় তবে এটির অনুমতি দিন না। এমন কোনও কনস্ট্রাক্টর বা নির্মাতা থাকুন যা সঠিকভাবে অবজেক্টের তৈরিকে বৈধতা দেয় এবং যদি এটি সঠিক না হয় তবে বিষয়টি সেই পর্যায়ে উত্থাপন করুন। "এটি নাল হতে পারে না" এবং কোডিং এবং বিশ্লেষণে এটিকে প্রয়োগ করতে যোগাযোগ করতে সহায়তা করতে বিদ্যমান @NotNullটীকাগুলির মধ্যে একটিও ব্যবহার করতে পারেন।

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

আরও বেশি কিছু করা

এই বিষয়টিতে বেশ কিছুটা আছে। গেটার্সে আপনি কতটা লজিক পেয়েছেন এবং গেটার্স এবং সিটারগুলির ভিতরে কী অনুমোদিত হতে হবে? এখান থেকে এবং গেটার্স এবং সেটটাররা স্ট্যাক ওভারফ্লোতে অতিরিক্ত যুক্তি সম্পাদন করে। এটি এমন একটি সমস্যা যা ক্লাস ডিজাইনে বারবার আসে।

এর মূলটি এসেছে:

সাধারণভাবে গ্রাহকরা যদি তাদের মানগুলি সেট না করে থাকে তবে তারা ব্যতিক্রম ছোঁড়ার কথা নয়

এবং আপনি ঠিক বলেছেন। তাদের করা উচিত নয়। তাদের বাকী বিশ্বের 'বোবা' হওয়া উচিত এবং যা প্রত্যাশিত তা করা উচিত। সেখানে অত্যধিক যুক্তি স্থাপন করা এমন সমস্যাগুলির দিকে নিয়ে যায় যেখানে সর্বনিম্ন বিস্ময়ের আইন লঙ্ঘিত হয়। এবং এটির মুখোমুখি হতে দেয়, আপনি সত্যিই একটি দিয়ে প্রহসনকারীদের মোড়ানো করতে চান না try catchকারণ আমরা জানি যে সাধারণভাবে এটি করা আমাদের কতটা পছন্দ।

এমন পরিস্থিতিতেও রয়েছে যেখানে আপনার জাভাবীনের কাঠামোর মতো কোনও পদ্ধতি ব্যবহার করতে হবেgetFoo এবং যখন শিমটি পাওয়ার প্রত্যাশার সাথে আপনার কাছে এল কল থেকে কিছু আসবে (যাতে <% bar.foo %>প্রকৃতপক্ষে getFoo()ক্লাসে কল করা যায় - 'সিমটি রচনাটি করা উচিত বা হওয়া উচিত) এটিকে দেখার জন্য রেখে দেওয়া যায়? 'কারণ একজন সহজেই এমন পরিস্থিতি নিয়ে আসতে পারে যেখানে একজন বা অন্য পরিষ্কারভাবে সঠিক উত্তর হতে পারে)

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

দিনের শেষে...

যে বিষয়টি সম্পর্কে তর্ক করা সহজ Do আপনি এই কোডটি ডিজাইনিং করার জন্য ব্যয় করার চেয়ে বেশি সময় ব্যয় করবেন (যদিও আপনি ডিজাইনিং করতে যত কম সময় ব্যয় করবেন তত বেশি সময় আপনি বজায় রাখতে ব্যয় করবেন)। আদর্শ পছন্দ এমনভাবে এটি যতটা সময় বজায় রাখার জন্য নেবে না এটা ডিজাইন করতে, কিন্তু দিনের জন্য এটা সম্পর্কে চিন্তা বসতে না পারেন - যদি না এই সত্যিই একটি নকশা পছন্দ করে হবে প্রভাব দিন পরে আছে ।

প্রতীকী সত্তার অর্থগত বিশুদ্ধতার সাথে আঁকড়ে থাকার চেষ্টা করা আপনাকে এক private T foo; T getFoo() { return foo; }পর্যায়ে সমস্যার মধ্যে ফেলবে। কখনও কখনও কোডটি কেবল সেই মডেলটির সাথে খাপ খায় না এবং এটি যেভাবে চালিয়ে যাওয়ার চেষ্টা করে সেগুলি বোঝায় না ... এবং শেষ পর্যন্ত এটির নকশা করা আরও শক্ত করে তোলে।

কখনও কখনও গ্রহণ করুন যে কোডটিতে আপনি যেভাবে চান ডিজাইনের আদর্শগুলি অনুধাবন করা যায় না। নির্দেশিকাগুলি হ'ল গাইডলাইন - শেকল নয়।


2
স্পষ্টতই আমার উদাহরণটি কোডিং শৈলীর উপর যুক্তি দিয়ে উন্নত করার একটি অজুহাত ছিল, কোনও ব্লকিং ইস্যু নয়। তবে আপনি এবং অন্যরা নির্মাতাদের যে গুরুত্ব দিয়েছেন বলে আমি যথেষ্ট বিচলিত theory তত্ত্বের মধ্যে তারা তাদের প্রতিশ্রুতি রাখে। অনুশীলনে, উত্তরাধিকারের সাথে মান্তেনের কাছে তারা জটিল হয়ে ওঠে, যখন আপনি কোনও ক্লাস থেকে কোনও ইন্টারফেস বের করেন, জাভাবেন এবং বসন্তের মতো অন্যান্য ফ্রেমওয়ার্কগুলি গ্রহণ না করে, যদি আমি ভুল না করি। একটি 'শ্রেণি' ধারণার ছত্রছায়ায় বিভিন্ন ধরণের অবজেক্টের লাইভ। একটি মান অবজেক্টের সাথে একটি বৈধকরণকারী কনস্ট্রাক্টর থাকতে পারে তবে এটি কেবল এক ধরণের।
AgostinoX

2
কোড সম্পর্কে যুক্তি অর্জনে সক্ষম হওয়া কোনও এপিআই ব্যবহার করে কোড লিখতে সক্ষম হওয়া বা কোড বজায় রাখতে সক্ষম হওয়া কী key যদি কোনও শ্রেণীর এমন কোনও নির্মাণকারী থাকে যা এটি একটি অবৈধ অবস্থায় থাকতে দেয় তবে "ভাল, এটি কী করে?" এর মাধ্যমে চিন্তা করা আরও কঠিন করে তোলে ? কারণ এখন আপনাকে শ্রেণীর ডিজাইনার বিবেচিত বা উদ্দেশ্যযুক্তের চেয়ে আরও পরিস্থিতি বিবেচনা করতে হবে। এই অতিরিক্ত ধারণাগত লোডটি আরও বাগের জরিমানা এবং কোড লেখার জন্য আরও দীর্ঘ সময় নিয়ে আসে। অন্যদিকে, আপনি যদি কোডটি দেখতে এবং "নাম এবং উপাধি কখনই বাতিল হবে না" বলতে পারেন তবে তাদের ব্যবহার করে কোড লেখা খুব সহজ হয়ে যায়।

2
অসম্পূর্ণ অগত্যা অবৈধ মানে না। প্রাপ্তি ব্যতীত একটি চালানটি অগ্রগতিতে হতে পারে এবং এটি যে সর্বজনীন API উপস্থাপন করে তা প্রতিবিম্বিত হবে যে এটি একটি বৈধ রাষ্ট্র state যদি surnameবা nameশূন্য হওয়া অবজেক্টের জন্য একটি বৈধ রাষ্ট্র, তবে সেই অনুযায়ী এটি পরিচালনা করুন। তবে যদি এটি কোনও বৈধ রাষ্ট্র না হয় - শ্রেণির মধ্যে পদ্ধতিগুলি ব্যতিক্রম ছুঁড়ে ফেলার কারণ হয়ে থাকে, তবে এটি সূচনা হওয়ার দিক থেকে সেই অবস্থায় থাকতে দেওয়া উচিত। আপনি অসম্পূর্ণ বস্তুর কাছাকাছি যেতে পারেন, তবে অবৈধ বিষয়গুলির কাছাকাছি যাওয়া সমস্যাযুক্ত। যদি নাল ছদ্মনাম ব্যতিক্রমী হয়, তবে এটির চেয়ে আগে রোধ করার চেষ্টা করুন।

2
পড়তে সম্পর্কিত একটি ব্লগ পোস্ট: অবজেক্ট ইনিশিয়ালাইজেশন ডিজাইন করা এবং একটি উদাহরণ পরিবর্তনশীল সূচনা করার জন্য চারটি পদ্ধতির নোট। এর মধ্যে একটি হ'ল এটিকে একটি অবৈধ অবস্থায় থাকতে দেওয়া, যদিও নোট করুন এটি একটি ব্যতিক্রম ছুঁড়ে। যদি আপনি এটি এড়াতে চাইছেন তবে সেই পদ্ধতির কোনও বৈধতা নেই এবং আপনাকে অন্যান্য পদ্ধতির সাথে কাজ করতে হবে - যা সর্বদা একটি বৈধ অবজেক্টকে নিশ্চিতকরণের সাথে জড়িত। ব্লগ থেকে: "অবজেক্টের যে বিষয়গুলিতে অবৈধ অবস্থা থাকতে পারে সেগুলির ব্যবহার সর্বদা বৈধ যেগুলির চেয়ে বেশি কঠিন এবং বোঝা শক্ত।" এবং এটি কী।

5
"যে বিষয়টি সম্পর্কে তর্ক করা সহজ is" এটি করুন " যে
বেন

5

আমি জাভা লোক নই, তবে এটি আপনার উপস্থাপিত উভয় প্রতিবন্ধকতা মেনে চলেছে বলে মনে হচ্ছে।

getCompleteNameনামগুলি অবিচ্ছিন্ন করা হলে এবং ব্যতিক্রম হয় না displayCompleteNameOnInvoice

public String getCompleteName()
{
    if (name == null || surname == null)
    {
        return null;
    }
    return name + " " + surname;
}

public void displayCompleteNameOnInvoice() 
{
    String completeName = getCompleteName();
    if (completeName == null)
    {
        //throw an exception.
    }
    //do something with it....
}

কেন এটি সঠিক সমাধান তা প্রসারিত করার জন্য: এই ধরণের কলকারীকে getCompleteName()সম্পত্তি প্রকৃতপক্ষে সঞ্চিত আছে বা এটি উড়তে গণনা করা হচ্ছে কিনা সেদিকে খেয়াল রাখতে হবে না।
বার্ট ভ্যান ইনজেন শেেনা

18
কেন এই সমাধানটি ব্যাশিত পাগল তা প্রসারিত করতে আপনাকে প্রতিটি কলটিতে নালিশতা পরীক্ষা করতে হবে getCompleteName, যা ঘৃণ্য।
ডেডএমজি

না, @ ডিড এমএমজি, আপনি কেবল তখনই এটি পরীক্ষা করতে পারেন যেখানে getCompleteName বাতিল হয়ে যায় যদি ব্যতিক্রম ছুঁড়ে ফেলা উচিত। এটি হওয়া উচিত যা উপায়। এই সমাধানটি সঠিক।
দাউদ ইবনে কেরেম

1
@ ডিড এমজি হ্যাঁ, তবে আমরা জানি না getCompleteName()যে ক্লাসের বাকী অংশে বা প্রোগ্রামের অন্যান্য অংশে অন্যরা কী ব্যবহার করে। কিছু ক্ষেত্রে, ফিরে আসা nullঠিক যা প্রয়োজন তা হতে পারে। তবে এমন একটি পদ্ধতি আছে যার বৈশিষ্টটি "এই ক্ষেত্রে একটি ব্যতিক্রম ছুঁড়ে ফেলা", এটি আমাদের কোড করা উচিত ঠিক EX
দাউদ ইবনে করিম

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

4

দেখে মনে হচ্ছে কেউ আপনার প্রশ্নের উত্তর দিচ্ছে না।
লোকেরা যা বিশ্বাস করতে পছন্দ করে তার বিপরীতে, "অবৈধ বিষয়গুলি এড়ানো" প্রায়শই ব্যবহারিক সমাধান নয়।

উত্তর হচ্ছে:

হ্যাঁ এটা করা উচিত।

সহজ উদাহরণ: FileStream.Lengthসি # /। নেট এ , NotSupportedExceptionফাইলটি সন্ধানযোগ্য না হলে এটি ছুড়ে দেয় ।


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
ম্যাপেল_শ্যাফ্ট

1

আপনার সম্পূর্ণ চেকিং নামের জিনিসটি উল্টো দিকে আছে।

getCompleteName()কোন ফাংশন এটি ব্যবহার করবে তা জানতে হবে না। সুতরাং, একটি হচ্ছে না nameযখন কলিং displayCompleteNameOnInvoice()নয় getCompleteName()দায়িত্ব সে।

তবে nameএটির জন্য একটি পরিষ্কার পূর্বশর্ত displayCompleteNameOnInvoice()। সুতরাং, এটি রাষ্ট্র পরীক্ষা করার দায়িত্ব গ্রহণ করা উচিত (বা যদি আপনি চান তবে এটি অন্য কোনও পদ্ধতিতে পরীক্ষা করার দায়িত্ব অর্পণ করা উচিত )।

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