অন্যথায় যদি হ্যান্ডেল করার মার্জিত উপায়


161

এটি একটি গৌণ নিগল, তবে প্রতিবারই আমাকে এই জাতীয় কিছু কোড করতে হবে, পুনরাবৃত্তি আমাকে বিরক্ত করে, তবে আমি নিশ্চিত নই যে সমাধানগুলির কোনওটি আরও খারাপ নয়।

if(FileExists(file))
{
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(SomeTest(contents))
    {
        DoSomething(contents);
    }
    else
    {
        DefaultAction();
    }
}
else
{
    DefaultAction();
}
  • এই জাতীয় যুক্তির নাম আছে কি?
  • আমি কি খুব ওসিডি বাচ্চা?

আমি কৌতূহলের জন্য যদি অশুভ কোড পরামর্শের জন্য উন্মুক্ত ...


8
@ ইমাদ কেরিম: দুটি DefaultActionকল DRY নীতি লঙ্ঘন করেছে
অ্যাবিক্স

আপনার জবাবের জন্য ধন্যবাদ, তবে আমি মনে করি যে এটি ঠিক আছে, চেষ্টা / ধরা ব্যবহার না করা ব্যতীত এমন ত্রুটি থাকতে পারে যা ফলাফল দেয় না এবং ফলস্বরূপ হতে পারে (আপনার প্রোগ্রামিং ভাষার উপর নির্ভর করে)।
NoChance

20
আমি মনে করি এখানে মূল বিষয়টি হ'ল আপনি বিমূর্ততার অসঙ্গত স্তরে কাজ করছেন । উচ্চতর বিমূর্ততা স্তর হল: make sure I have valid data for DoSomething(), and then DoSomething() with it. Otherwise, take DefaultAction()। ডসোমিংথিং () এর জন্য আপনার কাছে ডেটা রয়েছে তা নিশ্চিত করার কৌতূহলপূর্ণ বিশদ বিবরণগুলি নিম্ন বিমূর্ত স্তরে রয়েছে এবং তাই অন্য কোনও ফাংশনে থাকা উচিত। এই ফাংশনটির উচ্চতর বিমূর্তকরণ স্তরে একটি নাম থাকবে এবং এর বাস্তবায়ন হবে নিম্ন-স্তরের। নীচের ভাল উত্তরগুলি এই সমস্যাটিকে সম্বোধন করে।
গিলাদ নাওর

6
দয়া করে একটি ভাষা নির্দিষ্ট করুন। সম্ভাব্য সমাধান, মানক বাগধারার এবং দীর্ঘদিনের সাংস্কৃতিক নিয়ম বিভিন্ন ভাষার জন্য আলাদা এবং আপনার প্র: বিভিন্ন উত্তর হতে হবে
কালেব

1
আপনি এই বইটি "রিফ্যাক্টরিং: বিদ্যমান কোডের ডিজাইনের উন্নতি" উল্লেখ করতে পারেন the যদি-অন্য কাঠামো, সত্যই দরকারী অনুশীলন সম্পর্কে বিভিন্ন বিভাগ রয়েছে।
ভ্যাকার

উত্তর:


96

এটি পৃথক ফাংশন (পদ্ধতি) এবং returnস্টেটমেন্ট ব্যবহার করতে এক্সট্র্যাক্ট করুন :

if(FileExists(file))
{
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(SomeTest(contents))
    {
        DoSomething(contents);
        return;
    }
}

DefaultAction();

অথবা, আরও ভাল, পৃথকভাবে প্রাপ্ত সামগ্রী এবং এর প্রক্রিয়াজাতকরণ:

contents_t get_contents(name_t file)
{
    if(!FileExists(file))
        return null;

    contents = OpenFile(file);
    if(!SomeTest(contents)) // like IsContentsValid
        return null;

    return contents;
}

...

contents = get_contents(file)
contents ? DoSomething(contents) : DefaultAction();

Upd:

ব্যতিক্রম কেন নয়, কেন OpenFileআইও ব্যতিক্রম নিক্ষেপ করবে না:
আমি মনে করি এটি ফাইল আইও সম্পর্কে প্রশ্ন না করে সত্যই সাধারণ প্রশ্ন। এর মতো নামগুলি FileExists, OpenFileবিভ্রান্তিকর হতে পারে, কিন্তু যদি তাদের সাথে প্রতিস্থাপন করতে Foo, Barইত্যাদি - এটা পরিষ্কার যে হবে DefaultActionহিসাবে প্রায়ই হিসাবে বলা যেতে পারে DoSomething, তাই এটি অ ব্যতিক্রমী ক্ষেত্রে হতে পারে। পেটার তারেক তার উত্তরের শেষে এ সম্পর্কে লিখেছিলেন

২ য় বৈকল্পে কেন সেখানে চৌকস শর্তসাপেক্ষ অপারেটর রয়েছে:
যদি [সি ++] ট্যাগ থাকত তবে আমি তার শর্তের অংশে ifডিকোমলেশন সহ বিবৃতি লিখতাম contents:

if(contents_t contents = get_contents(file))
    DoSomething(contents);
else
    DefaultAction();

তবে অন্যান্য (সি-জাতীয়) ভাষার ক্ষেত্রে, if(contents) ...; else ...;টের্নারি শর্তসাপেক্ষ অপারেটরের সাথে অভিব্যক্তি বিবরণের মতো ঠিক তবে লম্বা। কোডটির মূল অংশটি ছিল কারণ get_contents, আমি কেবল সংক্ষিপ্ত সংস্করণটি ব্যবহার করেছি (এবং বাদ দেওয়া contentsপ্রকারও)। যাইহোক, এটি এই প্রশ্নের বাইরে।


93
একাধিক আয় জন্য +1 - যখন পদ্ধতি যথেষ্ট প্রণীত , এই পদ্ধতির সেরা আমার জন্য কাজ
মশা

একাধিক রিটার্নের কোনও বড় ফ্যান নয়, যদিও আমি এটি মাঝে মাঝে ব্যবহার করি। এটি কোনও সাধারণ বিষয়ে যথেষ্ট যুক্তিসঙ্গত, তবে কেবল ভাল স্কেল করে না। আমাদের স্ট্যান্ডার্ড হ'ল পাগল সহজ পদ্ধতির সকলের জন্য এড়াতে কারণ পদ্ধতিগুলি সঙ্কুচিত হওয়ার চেয়ে আকারে আরও বেড়ে যায়।
ব্রায়ান নোব্লাচ

3
একাধিক রিটার্ন পাথের সি ++ প্রোগ্রামগুলিতে নেতিবাচক কর্মক্ষমতা জড়িত থাকতে পারে, আরভিও নিয়োগের জন্য অপ্টিমাইজারের প্রচেষ্টা (এছাড়াও এনআরভিও, যদি না প্রতিটি পাথ একই বস্তুকে ফেরত দেয়)।
চমত্কার

আমি দ্বিতীয় সমাধানটিতে যুক্তিটির বিপরীতকরণের পরামর্শ দেব: {যদি (ফাইল উপস্থিত থাকে) contents বিষয়বস্তু সেট করে; যদি (একরকম) {রিটার্ন সামগ্রী; }} রিটার্ন নাল; Flow এটি প্রবাহকে সহজতর করে এবং লাইনের সংখ্যা হ্রাস করে।
ওয়েজ

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

56

আপনি যদি প্রোগ্রামিংয়ের ভাষাটি ব্যবহার করেন (0) শর্ট সার্কিট বাইনারি তুলনা (যেমন মিথ্যা প্রত্যাখ্যান SomeTestকরলে কল না করে FileExists) এবং (1) অ্যাসাইনমেন্ট একটি মান দেয় (এর ফলাফল OpenFileনির্ধারিত হয় contentsএবং তারপরে সেই মানটি আর্গুমেন্ট হিসাবে পাস করা হয়) থেকে SomeTest), আপনি নীচের মতো কিছু ব্যবহার করতে পারেন, তবে এটি এখনও আপনাকে পরামর্শ দেওয়া হবে যে একক =উদ্দেশ্যমূলক ing

if( FileExists(file) && SomeTest(contents = OpenFile(file)) )
{
    DoSomething(contents);
}
else
{
    DefaultAction();
}

এটিটি কীভাবে সংশ্লেষিত হয়েছে তার উপর নির্ভর করে একটি পতাকা পরিবর্তনশীল (যা DefaultActionএই ক্ষেত্রে ত্রুটি পরিচালনা করে এমন কোডের সাথে সাফল্য / ব্যর্থতার শর্তগুলির টেস্টিংকে পৃথক করে) ভাল হওয়া ভাল )


এইভাবে আমি এটি করব।
অ্যান্টনি

13
ifআমার মতে, একটি বিবৃতিতে এতগুলি কোড লাগাতে বেশ স্থূল ।
মোটেসচ

15
আমি বিপরীতে, এই জাতীয় "যদি কিছু উপস্থিত থাকে এবং এই শর্তটি পূরণ করে" বিবৃতি পছন্দ করি। +1
গর্পিক

আমিও করি! লোকেরা একাধিক রিটার্ন ব্যবহার করে কিছু প্রাঙ্গণ পূরণ হয় না তা আমি ব্যক্তিগতভাবে অপছন্দ করি। আপনি যদি এই আইএফগুলি উল্টান না এবং আপনার কোডটি পূরণ হয় তবে তা কার্যকর করবেন না কেন ?
klaar

"যদি কিছু বিদ্যমান থাকে এবং এই শর্তটি পূরণ করে" ঠিক আছে। "যদি কিছু বিদ্যমান থাকে এবং এখানে স্পর্শকাতরভাবে সম্পর্কিত কিছু করে এবং এই শর্তটি পূরণ করে", ওটিওএইচ বিভ্রান্তিকর। অন্য কথায়, আমি একটি অবস্থায় পার্শ্ব প্রতিক্রিয়া অপছন্দ করি।
পিসকভোর

26

ডিফল্ট অ্যাকশনে কলটির পুনরাবৃত্তির চেয়ে আরও গুরুত্ব সহকারে শৈলী নিজেই কারণ কোডটি অ অर्थোগোনাল লেখা ( অরথোগোনালি লেখার ভাল কারণগুলির জন্য এই উত্তরটি দেখুন )।

কেন অরર્થোগোনাল কোডটি খারাপ তা দেখানোর জন্য মূল উদাহরণটি বিবেচনা করুন, যখন কোনও নতুন প্রয়োজন যখন ফাইলটি নেটওয়ার্ক ডিস্কে সঞ্চিত থাকে তবে তা খোলার দরকার নেই। ঠিক আছে, তাহলে আমরা কেবল নিম্নলিখিতটি কোডটি আপডেট করতে পারি:

if(FileExists(file))
{
    if(! OnNetworkDisk(file))
    {
        contents = OpenFile(file); // <-- prevents inclusion in if
        if(SomeTest(contents))
        {
            DoSomething(contents);
        }
        else
        {
            DefaultAction();
        }
    }
    else
    {
        DefaultAction();
    }
}
else
{
    DefaultAction();
}

তবে তারপরে একটি প্রয়োজনীয়তাও আসে যে আমাদের 2 জিবি-র মাধ্যমে বড় ফাইলগুলি না খোলার উচিত। ঠিক আছে, আমরা কেবল আবার আপডেট করেছি:

if(FileExists(file))
{
    if(LessThan2Gb(file))
    {
        if(! OnNetworkDisk(file))
        {
            contents = OpenFile(file); // <-- prevents inclusion in if
            if(SomeTest(contents))
            {
                DoSomething(contents);
            }
            else
            {
                DefaultAction();
            }
        }
        else
        {
            DefaultAction();
        }
    else
    {
        DefaultAction();
    }
}
else
{
    DefaultAction();
}

এটি খুব স্পষ্ট হওয়া উচিত যে এই জাতীয় কোড শৈলী একটি রক্ষণাবেক্ষণের বিশাল ব্যথা হবে।

এখানে উত্তরগুলির মধ্যে যা সঠিকভাবে অরথোগোনালি লেখা হয় তা হলেন অ্যাবিক্সের দ্বিতীয় উদাহরণ এবং জ্যান হুডেকের উত্তর , তাই আমি এটিকে পুনরাবৃত্তি করব না, কেবল উল্লেখ করব যে এই উত্তরগুলিতে দুটি প্রয়োজনীয়তা যুক্ত করা ঠিক হবে

if(! LessThan2Gb(file))
    return null;

if(OnNetworkDisk(file))
    return null;

(বা এর goto notexists;পরিবর্তে return null;), যুক্ত লাইনগুলির চেয়ে অন্য কোনও কোডকে প্রভাবিত করছে না । যেমন অরথোগোনাল।

পরীক্ষা করার সময়, সাধারণ নিয়মটি ব্যতিক্রমগুলি পরীক্ষা করা উচিত , সাধারণ ক্ষেত্রে নয়


8
আমার জন্য +1 প্রথম দিকের রিটার্নগুলি তীরের এন্টি নিদর্শন এড়াতে সহায়তা করে। কোডিংহরর.com / blog/ 2006 / 01/ flattening - arrow- code.html এবং lostechies.com/chrismissal/2009/05/27/… দেখুন এই প্যাটার্নটি পড়ার আগে, আমি সর্বদা ফাংশন অনুযায়ী 1 টি প্রবেশ / প্রস্থানের সদস্যতা নিয়েছিলাম তত্ত্বের কারণে যা আমাকে 15 বছর বা তার আগে পড়ানো হয়েছিল। আমি মনে করি এটি পড়ার জন্য কোডটিকে এত সহজ করে তোলে এবং আপনি আরও রক্ষণাবেক্ষণের কথা উল্লেখ করেছেন।
মিঃ মোজ

3
@ মিঃমূজ: আপনার তীরচিহ্ন বিরোধী প্যাটার্নের উল্লেখ বেনজলের স্পষ্ট প্রশ্নটির উত্তর দেয়: "এই জাতীয় যুক্তির কোনও নাম আছে কি?" উত্তর হিসাবে পোস্ট করুন এবং আপনি আমার ভোট পেয়েছেন।
outis

এটি একটি দুর্দান্ত উত্তর, ধন্যবাদ। এবং @ মিঃমূজ: "অ্যারোহেড অ্যান্টি প্যাটার্ন" সম্ভবত আমার প্রথম বুলেটটির উত্তর দেয়, তাই হ্যাঁ, এটি পোস্ট করুন। আমি প্রতিজ্ঞা করতে পারি না আমি তা গ্রহণ করব, তবে এটি ভোটের দাবিদার!
বেনজল

@outis। ধন্যবাদ। আমি উত্তর যুক্ত করেছি। তীরক্ষেত্র বিরোধী নিদর্শন অবশ্যই হলভডালের পোস্টে প্রাসঙ্গিক এবং তার রক্ষাকারী ধারাগুলি তাদের চারপাশে পেতে ভালভাবে কাজ করে। আমি জানি না আপনি কীভাবে দ্বিতীয় বুলেট পয়েন্টটির উত্তর দিতে পারেন। আমি এটি নির্ণয়ের যোগ্য নই :)
মিঃ মোস

4
"পরীক্ষার ব্যতিক্রমগুলি, সাধারণ ক্ষেত্রে নয়" এর জন্য +1।
রায় টিঙ্কার

25

একথাও ঠিক যে:

Whatever(Arguments)
{
    if(!FileExists(file))
        goto notexists;
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(!SomeTest(contents))
        goto notexists;
    DoSomething(contents);
    return;
notexists:
    DefaultAction();
}

আপনি বলেছিলেন যে আপনি দুষ্ট সমাধানের জন্যও উন্মুক্ত, তাই মন্দ গোটের গণনা ব্যবহার করে, না?

প্রকৃতপক্ষে প্রসঙ্গের উপর নির্ভর করে এই সমাধানটি দুষ্ট ক্রিয়া দু'বার করা বা মন্দ অতিরিক্ত ভেরিয়েবলের চেয়ে কম খারাপ হতে পারে। আমি এটি একটি ফাংশনে আবৃত করেছি, কারণ এটি দীর্ঘ ফাংশনের মাঝামাঝি সময়ে অবশ্যই ঠিক থাকবে না (অন্তত মাঝখানে ফিরে আসার কারণে নয়)। কিন্তু দীর্ঘ ফাংশন চেয়ে সময়, ঠিক আছে না।

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


"দুষ্টু" তে দ্রষ্টব্য: সি ++ এফএকিউ 6.15 "অশুভ" সংজ্ঞায়িত করে:

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

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


11
আমার কার্সারটি গ্রহনযোগ্য বোতামের উপর ঘুরে বেড়াচ্ছে ... কেবল সমস্ত শুদ্ধবাদী থাকা সত্ত্বেও। ওহোহ প্রলোভন: ডি
বেনজল

2
হ্যা হ্যা! কোডটি লেখার এটি একেবারে "সঠিক" উপায়। কোডটির কাঠামোটি এখন "যদি ত্রুটি হয়, ত্রুটিটি পরিচালনা করে Nor সাধারণ ক্রিয়া error যদি ত্রুটি হয়, ত্রুটিটি হ্যান্ডেল করে Nor সমস্ত "নরমাল" কোডটি কেবল একটি একক স্তরের ইন্ডেন্টেশন দিয়ে লেখা হয় যখন সমস্ত ত্রুটি সম্পর্কিত কোডটিতে দুটি স্তরের ইন্ডেন্টেশন থাকে। সুতরাং স্বাভাবিক এবং সর্বাধিক গুরুত্বপূর্ণ কোডটি সর্বাধিক বিশিষ্ট ভিজ্যুয়াল স্থান পায় এবং খুব তাত্ক্ষণিকভাবে এবং সহজেই প্রবাহটি ক্রমানুসারে নীচের দিকে পড়া সম্ভব। যাই হোক না কেন এই উত্তর গ্রহণ করুন।
hlovdal

2
এবং অন্য দিকটি হ'ল এইভাবে লিখিত কোডটি অরথোগোনাল। উদাহরণস্বরূপ দুটি লাইন "যদি (! ফাইলএক্সিস্টগুলি (ফাইল)) \ n \ tgoto নোটেক্সিস্ট;" এখন কেবলমাত্র এই একক ত্রুটি দিকটি (কেআইএসএস) পরিচালনা করার সাথে সম্পর্কিত এবং সবচেয়ে গুরুত্বপূর্ণ বিষয় এটি অন্যান্য লাইনের কোনওটিকে প্রভাবিত করে না । এই উত্তর stackoverflow.com/a/3272062/23118 কোড অরথোগোনাল রাখতে বেশ কয়েকটি ভাল কারণ তালিকাভুক্ত করে।
hlovdal

5
দুষ্ট সমাধানগুলির কথা বলছি: আমি আপনার সমাধানটি for(;;) { if(!FileExists(file)) break; contents = OpenFile(file); if(!SomeTest(contents)) break; DoSomething(contents); return; } /* broken out */ DefaultAction();
গোটো

4
@ হার্বি: আপনার সমাধানটি এর চেয়েও খারাপ goto, কারণ আপনি এমনভাবে গালি দিচ্ছেন breakযে কেউ এটির অপব্যবহারের প্রত্যাশা করে না, তাই কোডটি পড়ার লোকেরা গোটো যা স্পষ্টভাবে বলেছে তার চেয়ে বিরতি তাদের কোথায় নিয়ে যায় তা দেখতে আরও সমস্যা হবে। আপনি একটি অসীম লুপ ব্যবহার করছেন যা কেবল একবার চলবে যা বরং বিভ্রান্তিকর হবে। দুর্ভাগ্যক্রমে do { ... } while(0)হুবহু পঠনযোগ্য নয়, কারণ আপনি কেবল দেখতে পান এটি কেবল একটি মজার ব্লক এবং যখন আপনি শেষ হয় এবং সি অন্য ব্লকগুলি (পার্লের বিপরীতে) থেকে বিরতি সমর্থন করে না।
জানু হুডেক

12
function FileContentsExists(file) {
    return FileExists(file) ? OpenFile(file) : null;
}

...

contents = FileContentExists(file);
if(contents && SomeTest(contents))
{
    DoSomething(contents);
}
else
{
    DefaultAction();
}

বা অতিরিক্ত পুরুষ যান এবং একটি অতিরিক্ত ফাইলএক্সিস্টসএন্ডকন্ডিশনমেট (ফাইল) পদ্ধতি তৈরি করুন ...
আনকালজাইভ

@ হরবি SomeTestফাইলের অস্তিত্বের মতো একই শব্দার্থক থাকতে পারে যদি SomeTestফাইল টাইপ পরীক্ষা করে থাকে, উদাহরণস্বরূপ পরীক্ষা করে দেখুন যে .gif সত্যই জিআইএফ ফাইল।
অ্যাবিক্স

1
হ্যাঁ. নির্ভর করে। @ বেঞ্জল আরও ভাল জানেন।
হার্বি

3
... অবশ্যই আমার অর্থ ছিল "অতিরিক্ত মাইল যাও" ... :)
আঙ্কেলজিভ

2
যে পা থেকে রাভিওলি নিচ্ছে এমনকি আমি যেতে না (এবং আমি আছি এই চরম) ... আমার মনে হয় এখন এটা চমত্কারভাবে পাঠযোগ্য বিবেচনা করা হয় contents && f(contents)। অন্য একটি সংরক্ষণ করতে দুটি ফাংশন ?!
হার্বি

12

একটি সম্ভাবনা:

boolean handled = false;

if(FileExists(file))
{
    contents = OpenFile(file); // <-- prevents inclusion in if
    if(SomeTest(contents))
    {
        DoSomething(contents);
        handled = true;
    }
}
if (!handled)
{
    DefaultAction();
}

অবশ্যই, এটি কোডটিকে অন্যভাবে কিছুটা জটিল করে তোলে। সুতরাং এটি মূলত একটি শৈলীর প্রশ্ন।

একটি ভিন্ন পদ্ধতির ব্যতিক্রমগুলি ব্যবহার করা হবে, যেমন:

try
{
    contents = OpenFile(file); // throws IO exception if file not found
    DoSomething(contents); // calls SomeTest() and throws exception on failure
}
catch(Exception e)
{
    DefaultAction();
    // and the exception should be at least logged...
}

এটি সহজ দেখাচ্ছে, তবে এটি কেবল তখনই প্রযোজ্য

  • কী ধরণের ব্যতিক্রম আশা করা যায় তা আমরা স্পষ্টভাবে জানি এবং DefaultAction()এটি প্রতিটিটির সাথে খাপ খায়
  • আমরা ফাইল প্রক্রিয়াটি সফল হওয়ার আশা করি এবং একটি অনুপস্থিত ফাইল বা ব্যর্থতা SomeTest()স্পষ্টতই একটি ভ্রান্ত শর্ত, সুতরাং এটির ব্যতিক্রম ছড়িয়ে দেওয়া উপযুক্ত।

19
Noooo ~! পতাকা পরিবর্তনশীল নয়, এটি অবশ্যই ভুল উপায়, কারণ এটি জটিল, বোঝা শক্ত (যেখানে-পতাকা-সত্য হয়ে ওঠে) এবং চুল্লী কোডটিকে শক্ত করে।
অ্যাবিক্স

যদি আপনি এটি সম্ভাব্য স্কোপ হিসাবে স্থানীয় হিসাবে সীমাবদ্ধ না। (function () { ... })()জাভাস্ক্রিপ্টে, { flag = false; ... }সি-এর মতো ইত্যাদিতে
herby

ব্যতিক্রম যুক্তিটির জন্য +1, যা দৃশ্যের উপর নির্ভর করে সবচেয়ে উপযুক্ত সমাধান হতে পারে।
স্টিভেন জিউরিস

4
+1 এই পারস্পরিক 'নুও!' মজার. আমি মনে করি স্থিতির পরিবর্তনশীল এবং প্রথম দিকে প্রত্যাবর্তন উভয় ক্ষেত্রেই যথাযথ। আরও জটিল রুটিনগুলিতে আমি স্ট্যাটাস ভেরিয়েবলের জন্য যাব কারণ জটিলতা যুক্ত করার পরিবর্তে এটি যা করে তা যুক্তিকে সুস্পষ্ট করে তোলে। কিছুতেই ভুল হয়নি।
গ্রসভেজেল

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

11

এটি বিমূর্ততার উচ্চতর স্তরে:

if (WeCanDoSomething(file))
{
   DoSomething(contents);
}
else
{
   DefaultAction();
} 

এবং এই বিবরণ পূরণ করে।

boolean WeCanDoSomething(file)
{
    if FileExists(file)
    {
        contents = OpenFile(file);
        return (SomeTest(contents));
    }
    else
    {
        return FALSE;
    }
}

11

কার্য একটি কাজ করা উচিত। তাদের এটি ভালভাবে করা উচিত। তাদের কেবল এটি করা উচিত।
- ক্লিন কোডে রবার্ট মার্টিন

কিছু লোকেরা এই পদ্ধতিকে কিছুটা চরম মনে হলেও এটি খুব পরিষ্কার। পাইথনে আমাকে চিত্রিত করার অনুমতি দিন:

def processFile(self):
    if self.fileMeetsTest():
        self.doSomething()
    else:
        self.defaultAction()

def fileMeetsTest(self):
    return os.path.exists(self.path) and self.contentsTest()

def contentsTest(self):
    with open(self.path) as file:
        line = file.readline()
        return self.firstLineTest(line)

যখন তিনি বলেন যে ফাংশনগুলির একটি কাজ করা উচিত তখন তার অর্থ একটি জিনিস। processFile()পরীক্ষার ফলাফলের উপর ভিত্তি করে একটি ক্রিয়া চয়ন করে এবং এটিই এটি করে। fileMeetsTest()পরীক্ষার সমস্ত শর্ত একত্রিত করে এবং এটিই এটি করে। contentsTest()প্রথম লাইনটি স্থানান্তরিত করে firstLineTest()এবং এটিই এটি করে।

এটি অনেকগুলি ফাংশনের মতো মনে হয় তবে এটি ব্যবহারিকভাবে সরাসরি ইংরেজির মতো পড়ে:

ফাইলটি প্রক্রিয়া করতে, পরীক্ষাটি পূরণ করে কিনা তা পরীক্ষা করে দেখুন। যদি তা হয় তবে কিছু করুন। অন্যথায়, ডিফল্ট পদক্ষেপ নিন। ফাইলটি উপস্থিত থাকলে পরীক্ষা করে থাকে এবং বিষয়বস্তু পরীক্ষায় উত্তীর্ণ হয়। সামগ্রীগুলি পরীক্ষা করতে, ফাইলটি খুলুন এবং প্রথম লাইনটি পরীক্ষা করুন। প্রথম লাইনের জন্য পরীক্ষা ...

মঞ্জুর, এটি সামান্য কথাই, তবে মনে রাখবেন যে যদি কোনও রক্ষণাবেক্ষণকারী বিশদটি যত্ন না করে তবে তিনি কেবলমাত্র 4 টি লাইনের কোডের পরে পড়া বন্ধ করতে পারেন processFile()এবং ফাংশনটি কী করে তার এখনও তার উচ্চ স্তরের জ্ঞান থাকবে।


5
+1 এটি ভাল পরামর্শ, তবে "এক জিনিস" গঠন কী বিমূর্ততার বর্তমান স্তরের উপর নির্ভর করে। প্রক্রিয়াফাইলে () হ'ল "একটি জিনিস", তবে দুটি জিনিস: ফাইলমিটটেষ্ট () এবং হয় ডসোমিংথিং () বা ডিফল্টঅ্যাকশন ()। আমি আশঙ্কা করি যে "একটি জিনিস" দিকটি এমন নতুনদেরকে বিভ্রান্ত করতে পারে যারা ধারণাটিকে অগ্রাধিকার দেয় না ।
কালেব

1
এটি একটি ভাল লক্ষ্য ... এটি সম্পর্কে আমার কেবল
এতটা

1
আমি এর মতো উদাহরণ ভেরিয়েবল হিসাবে জড়িত যুক্তিগুলি পাস করতে পছন্দ করি না। আপনি "অকেজো" উদাহরণ ভেরিয়েবলগুলি পূর্ণ পেয়েছেন এবং আপনার রাজ্যটি খুঁজে পেতে এবং আক্রমণকারীদের ভাঙ্গার অনেক উপায় রয়েছে।
hugomg

@ কালেব, প্রসেসফিল ​​() সত্যিই একটি কাজ করছে। কার্ল তার পোস্টে যেমন বলেছে, এটি কোন পদক্ষেপ নেবে তা সিদ্ধান্ত নিতে একটি পরীক্ষা ব্যবহার করছে এবং ক্রিয়া সম্ভাবনার প্রকৃত বাস্তবায়নকে অন্য পদ্ধতিতে পিছিয়ে দিচ্ছে। আপনি যদি আরও অনেক বিকল্প ক্রিয়া যুক্ত করতে থাকেন তবে তাত্ক্ষণিক পদ্ধতিতে যুক্তির কোনও বাসা বাঁধতে না পারায় এখনও পদ্ধতির একক উদ্দেশ্য মানদণ্ডটি মেটানো যেতে পারে।
S.Robins

6

এটিকে যাকে বলা হয় তার সাথে, আপনার কোডটি আরও প্রয়োজনীয়তাগুলি হ্যান্ডেল করতে বাড়ার সাথে সাথে এটি তীরের এন্টি প্যাটার্নে সহজেই বিকাশ লাভ করতে পারে ( https://softwareengineering.stackexchange.com/a/122625/33922 এ প্রদত্ত উত্তরের মাধ্যমে দেখানো হয়েছে ) এবং তারপরে নেস্টেড শর্তাধীন বিবৃতিগুলি সহ একটি তীরের মতো কোডগুলির বিশাল অংশগুলির ফাঁদে পড়ে।

লিঙ্কগুলি দেখুন যেমন;

http://codinghorror.com/blog/2006/01/flattening-arrow-code.html

http://lostechies.com/chrismissal/2009/05/27/anti-patterns-and-worst-practices-the-arrowhead-anti-pattern/

গুগলে এটি এবং অন্যান্য বিরোধী নিদর্শনগুলির মধ্যে আরও অনেক কিছু রয়েছে।

জেফ তার ব্লগে এই সম্পর্কিত কয়েকটি দুর্দান্ত টিপস সরবরাহ করেছে;

1) গার্ড ক্লজ দিয়ে শর্ত প্রতিস্থাপন করুন।

2) শর্তসাপেক্ষে ব্লকগুলি পৃথক ফাংশনে বিভক্ত করুন।

3) নেতিবাচক চেকগুলি ইতিবাচক চেকগুলিতে রূপান্তর করুন

4) সর্বদা সুবিধাবাদীভাবে ফাংশন থেকে যত তাড়াতাড়ি সম্ভব ফিরে আসুন।

প্রথম দিকের রিটার্ন সম্পর্কে স্টিভ ম্যাককনেলস পরামর্শ সম্পর্কে জেফের ব্লগে কিছু মন্তব্য দেখুন;

"পাঠ্যতা বাড়ায় যখন কোনও রিটার্ন ব্যবহার করুন: নির্দিষ্ট রুটিনগুলিতে, আপনি উত্তরটি জানার পরে, আপনি তাৎক্ষণিকভাবে কলিং রুটিনে ফিরিয়ে দিতে চান the রুটিনটি এমনভাবে সংজ্ঞায়িত করা হয় যে একবার এর পরে আর কোনও পরিষ্কারের প্রয়োজন হয় না ত্রুটি সনাক্ত করে, তাত্ক্ষণিকভাবে ফিরে না আসার অর্থ আপনার আরও কোড লিখতে হবে। "

...

"প্রতিটি রুটিনে রিটার্নের সংখ্যা হ্রাস করুন: একটি রুটিনটি যখন নীচের অংশে পড়ে এটি বুঝতে পারা যায় তবে এটি সম্ভবত কোথাও ফিরে আসার সম্ভাবনা সম্পর্কে আপনি অবগত নন that সেই কারণে, রিটার্নটি ন্যায়বিচারের সাথে ব্যবহার করুন - কেবল যখন তারা উন্নতি করবেন only পঠনযোগ্যতা। "

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


6

এটি ডিআরওয়াই, নো-গোটো এবং নো-মাল্টিপল-রিটার্ন বিধিগুলির সাথে সঙ্গতিপূর্ণ, আমার মতে স্কেলযোগ্য এবং পঠনযোগ্য:

success = FileExists(file);
if (success)
{
    contents = OpenFile(file);
    success = SomeTest(contents);
}
if (success)
{
    DoSomething(contents);
}
else
{
    DefaultAction();
}

1
মানগুলির সাথে সামঞ্জস্য করা অবশ্য ভাল কোডের সমান হয় না। আমি বর্তমানে কোডের এই স্নিপেটে অনিচ্ছুক।
ব্রায়ান নোব্লাচ

এটি কেবলমাত্র 2 ডিফল্টঅ্যাকশন () প্রতিস্থাপন করে; 2 টি অভিন্ন হলে শর্তাদি এবং একটি পতাকা পরিবর্তনশীল যুক্ত করে যা ইমো আরও খারাপ।
রায়াথাল

3
এর মতো একটি কনস্ট্রাক্ট ব্যবহারের সুবিধাটি হ'ল পরীক্ষার সংখ্যা বাড়ার সাথে সাথে কোড ifঅন্য এসের মধ্যে আরও বাসা বাঁধতে শুরু করে না if। এছাড়াও, ব্যর্থ কেস ( DefaultAction()) হ্যান্ডেল করার কোডটি কেবলমাত্র এক জায়গায় এবং ডিবাগিংয়ের উদ্দেশ্যে কোডটি সাহায্যকারী ফাংশনগুলির চারপাশে লাফ দেয় না এবং successভেরিয়েবলটি পরিবর্তিত হয় এমন লাইনে ব্রেকপয়েন্টগুলি যুক্ত করতে দ্রুত পরীক্ষাগুলি উত্তীর্ণ হওয়া (ট্রিগারযুক্তের উপরে) দেখায় ব্রেকপয়েন্ট) এবং কোনগুলি পরীক্ষা করা হয়নি (নীচে)।
হিমশীতল

1
Yeeaah, আমি ধরনের এটি পছন্দ, কিন্তু আমি মনে হয় আমি নামান্তর চাই successথেকে ok_so_far:)
Benjol

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

3

আমি এটিকে আলাদা পদ্ধতিতে বের করতে এবং তারপরে:

if(!FileExists(file))
{
    DefaultAction();
    return;
}

contents = OpenFile(file);
if(!SomeTest(contents))
{
    DefaultAction();
    return;
}

DoSomething(contents);

যা জন্য অনুমতি দেয়

if(!FileExists(file))
{
    DefaultAction();
    return Result.FileNotFound;
}

contents = OpenFile(file);
if(!SomeTest(contents))
{
    DefaultAction();
    return Result.TestFailed;
}

DoSomething(contents);
return Result.Success;            

তারপরে সম্ভবত আপনি DefaultActionকলগুলি সরিয়ে ফেলতে পারেন এবং DefaultActionকলারের জন্য এক্সিকিউট করা ছেড়ে দিতে পারেন :

Result OurMethod(file)
{
    if(!FileExists(file))
    {
        return Result.FileNotFound;
    }

    contents = OpenFile(file);
    if(!SomeTest(contents))
    {
        return Result.TestFailed;
    }

    DoSomething(contents);
    return Result.Success;            
}

void Caller()
{
    // something, something...

    var result = OurMethod(file);
    // if (result == Result.FileNotFound || result == Result.TestFailed), or just
    if (result != Result.Success)        
    {
        DefaultAction();
    }
}

আমি জিনে পিন্ডারের অ্যাপ্রোচও পছন্দ করি ।


3

এই বিশেষ ক্ষেত্রে, উত্তর যথেষ্ট সহজ ...

তার মাঝে একটি জাতি অবস্থা FileExistsএবং OpenFileফাইলটি মুছে ফেলা হবে সেখানে কি ঘটছে?

এই বিশেষ ক্ষেত্রে মোকাবেলার একমাত্র বুদ্ধিমান উপায় হ'ল FileExists:

contents = OpenFile(file);
if (!contents) // open failed
    DefaultAction();
else (SomeTest(contents))
    DoSomething(contents);

এটি ঝরঝরে করে এই সমস্যা সমাধান করে এবং কোড ক্লিনার করে তোলে।

সাধারণভাবে: সমস্যাটি পুনর্বিবেচনা করার চেষ্টা করুন এবং আরও একটি সমাধান প্রস্তুত করুন যা সমস্যাটি পুরোপুরি এড়িয়ে চলে।


2

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

সুতরাং আপনার উদাহরণ হতে পারে:

void DoABunchOfStuff()
{
    if(FileExists(file))
    {
        DoSomethingWithFileContent(file);
        return;
    }

    DefaultAction();
}

void DoSomethingWithFileContent(file)
{        
    var contents = GetFileContents(file)

    if(SomeTest(contents))
    {
        DoSomething(contents);
        return;
    }

    DefaultAction();
}

AReturnType GetFileContents(file)
{
    return OpenFile(file);
}

ব্যক্তিগতভাবে আমি অন্য ধারাটি ব্যবহার করতে আপত্তি করি না কারণ এটি যুক্তিটি কীভাবে কাজ করবে বলে স্পষ্টভাবে জানিয়েছে এবং তাই আপনার কোডের পঠনযোগ্যতা উন্নত করে। কিছু কোড বিউটিফিকেশন সরঞ্জামগুলি নেস্টিংয়ের যুক্তিকে নিরুৎসাহিত করার জন্য যদি বিবৃতিটি একটিতে সহজ করতে পছন্দ করে ।


2

নমুনা কোডে প্রদর্শিত কেসটি সাধারণত একটি ifবিবৃতিতে হ্রাস করা যেতে পারে । অনেক সিস্টেমে ফাইল-ওপেন ফাংশনটি যদি একটি অকার্যকর মান ফিরিয়ে দেয় তবে ফাইলটি ইতিমধ্যে বিদ্যমান নেই। কখনও কখনও এটি ডিফল্ট আচরণ; অন্য সময়, এটি একটি আর্গুমেন্টের মাধ্যমে নির্দিষ্ট করা আবশ্যক। এর অর্থ হল FileExistsপরীক্ষাটি বাদ দেওয়া যেতে পারে, যা অস্তিত্ব পরীক্ষা এবং ফাইল খোলার মধ্যে ফাইল মোছার ফলে দৌড়ের অবস্থার সাথেও সহায়তা করতে পারে।

file = OpenFile(path);
if(isValidFileHandle(file) && SomeTest(file)) {
    DoSomething(file);
} else {
    DefaultAction();
}

এটি সরাসরি অ্যাবস্ট্রাকশন-স্তর-মিশ্রণ ইস্যুটিকে সম্বোধন করে না কারণ এটি একাধিক, অপরিবর্তনীয় পরীক্ষার বিষয়টি পুরোপুরিভাবে সরিয়ে দেয়, যদিও ফাইল অস্তিত্ব পরীক্ষার ব্যবস্থা করা বিমূর্ত স্তরগুলি পৃথক করার সাথে বেমানান নয়। ধরে নিই যে অবৈধ ফাইল হ্যান্ডলগুলি "মিথ্যা" সমান এবং ফাইলের হাতলগুলি যখন সুযোগের বাইরে চলে যায়:

OpenFileIfSomething(path:String) : FileHandle {
    file = OpenFile(path);
    if (file && SomeTest(file)) {
        return file;
    }
    return null;
}

...

if ((file = OpenFileIfSomething(path))) {
    DoSomething(file);
} else {
    DefaultAction();
}

2

আমি ফ্রোজেনকোইয়ের সাথে একমত, যাইহোক, সি # এর জন্য, আমি ভেবেছিলাম এটি ট্রাইপার্স পদ্ধতিগুলির বাক্য গঠনটি অনুসরণ করতে সহায়তা করবে।

if(FileExists(file) && TryOpenFile(file, out contents))
    DoSomething(contents);
else
    DefaultAction();
bool TryOpenFile(object file, out object contents)
{
    try{
        contents = OpenFile(file);
    }
    catch{
        //something bad happened, computer probably exploded
        return false;
    }
    return true;
}

1

আপনার কোডটি কুৎসিত কারণ আপনি একক ফাংশনে খুব বেশি কাজ করছেন। আপনি হয় ফাইলটি প্রক্রিয়া করতে চান বা ডিফল্ট পদক্ষেপ নিতে চান, তাই বলে এটি শুরু করুন:

if (!ProcessFile(file)) { 
  DefaultAction(); 
}

পার্ল এবং রুবি প্রোগ্রামাররা লেখেন processFile(file) || defaultAction()

এখন প্রসেসফাইলে লিখুন:

if (FileExists(file)) { 
  contents = OpenFile(file);
  if (SomeTest(contents)) {
    processContents(contents);
    return true;
  }
}
return false;

1

অবশ্যই আপনি এই জাতীয় পরিস্থিতিতে কেবল এতদূর যেতে পারেন, তবে এখানে যাওয়ার একটি উপায়:

interface File<T> {
    function isOK():Bool;
    function getData():T;
}

var appleFile:File<Apple> = appleStorage.get(fileURI);
if (appleFile.isOK())
    eat(file.getData());
else
    cry();

আপনি অতিরিক্ত ফিল্টার চাইতে পারেন। তারপরে এটি করুন:

var appleFile = appleStorage.get(fileURI, isEdible);
//isEdible is of type Apple->Bool and will be used internally to answer to the isOK call
if (appleFile.isOK())
    eat(file.getData());
else
    cry();

যদিও এটি ঠিক ততটুকু অর্থপূর্ণও হতে পারে:

function eat(apple:Apple) {
     if (isEdible(apple)) 
         digest(apple);
     else
         die();
}
var appleFile = appleStorage.get(fileURI);
if (appleFile.isOK())
    eat(appleFile.getData());
else
    cry();

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


1

সুস্পষ্টর সাথে কী ভুল?

if(!FileExists(file)) {
    DefaultAction();
    return;
}
contents = OpenFile(file);
if(!SomeTest(contents))
{
    DefaultAction();
    return;
}        
DoSomething(contents);

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


0

আমি বুঝতে পারি যে এটি একটি পুরানো প্রশ্ন, তবে আমি একটি প্যাটার্ন লক্ষ্য করেছি যা উল্লেখ করা হয়নি; মূলত, পরে যে পদ্ধতি / গুলি আপনি কল করতে চান তা নির্ধারণের জন্য একটি ভেরিয়েবল সেট করে (যদি এর বাইরে ... অন্যথায় ...)।

কোডটি কাজ করা আরও সহজ করার জন্য এটি দেখার মতো অন্য একটি কোণ। এটি যখন আপনাকে কল করতে অন্য কোনও পদ্ধতি যুক্ত করতে বা উপযুক্ত পরিস্থিতিতে ডেকে আনা দরকার এমন উপযুক্ত পদ্ধতিটি পরিবর্তন করতে পারে তখন এটিও অনুমতি দেয়।

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

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

এটি 'ডোজোমিংথিং' হয়েছে কিনা এবং যেখানে না থাকলে, ডিফল্ট ক্রিয়াটি সম্পাদন করে কিনা তা আমরা যেখানে জিজ্ঞাসা করছি এমন প্রশ্নে জিজ্ঞাসিত উদাহরণ হিসাবে যেমন ব্যবহার করা যেতে পারে। অথবা প্রযোজ্য সময়ে সেট করতে, কল করতে, সেট করতে পারেন এমন প্রতিটি পদ্ধতির জন্য রাষ্ট্র থাকতে পারে, তারপরে প্রযোজ্য পদ্ধতিটিকে কল করুন যদি ... অন্যথায় ...

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

bool ActionDone = false;

if (Method_1(object_A)) // Test 1
{
    result_A = Method_2(object_A); // Result 1

    if (Method_3(result_A)) // Test 2
    {
        Method_4(result_A); // Action 1
        ActionDone = true;
    }
}

if (!ActionDone)
{
    Method_5(); // Default Action
}

0

নেস্টেড আইএফ কমাতে:

1 / প্রথম দিকে ফিরে;

2 / যৌগিক অভিব্যক্তি (শর্ট সার্কিট সচেতন)

সুতরাং, আপনার উদাহরণটি এ রকম রিফ্যাক্টর হতে পারে:

if( FileExists(file) && SomeTest(contents = OpenFile(file)) )
{
    DoSomething(contents);
    return;
}
DefaultAction();

0

আমি "রিটার্ন" সহ প্রচুর উদাহরণ দেখেছি যা আমি খুব ব্যবহার করি তবে মাঝে মাঝে আমি নতুন ফাংশন তৈরি করা এড়াতে এবং পরিবর্তে একটি লুপ ব্যবহার করতে চাই:

while (1) {
    if (FileExists(file)) {
        contents = OpenFile(file);
        if (SomeTest(contents)) {
           DoSomething(contents);
           break;
        } 
    }
    DefaultAction();
    break;
}

আপনি যদি কম লাইন লিখতে চান বা আপনি আমার হিসাবে অসীম লুপগুলি ঘৃণা করেন তবে আপনি লুপের ধরনটিকে "কর ... যখন (0)" এ পরিবর্তন করতে পারেন এবং শেষ "বিরতি" এড়াতে পারেন।


0

এই সমাধান সম্পর্কে কীভাবে:

content = NULL; //I presume OpenFile returns a pointer 
if(FileExists(file))
    contents = OpenFile(file);
if(content != NULL && SomeTest(contents))
    DoSomething(contents);
else
    DefaultAction();

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

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


0

স্পষ্টতই, সবচেয়ে মার্জিত এবং সংক্ষিপ্ত সমাধান হ'ল প্রিপ্রোসেসর ম্যাক্রো ব্যবহার করা।

#define DOUBLE_ELSE(CODE) else { CODE } } else { CODE }

যা আপনাকে এর মতো সুন্দর কোড লেখার অনুমতি দেয়:

if(FileExists(file))
{
    contents = OpenFile(file);
    if(SomeTest(contents))
    {
        DoSomething(contents);
    }
    DOUBLE_ELSE(DefaultAction();)

আপনি যদি প্রায়শই এই কৌশলটি ব্যবহার করেন তবে স্বয়ংক্রিয় ফর্ম্যাটিংয়ের উপর নির্ভর করা কঠিন হতে পারে এবং কিছু আইডিই আপনার ভ্রান্তচিত্তে ভুলভাবে অনুমান করা হয়েছে তা সম্পর্কে কিছুটা চিৎকার করতে পারে। এবং এই উক্তিটি যেমন রয়েছে, সমস্ত কিছু ট্রেডঅফ, তবে আমি মনে করি পুনরাবৃত্ত কোডের কুফলগুলি এড়াতে এটির কোনও খারাপ মূল্য দেওয়া উচিত নয়।


কিছু কিছু মানুষের জন্য, এবং কিছু ভাষায়, প্রাক প্রসেসর ম্যাক্রো হয় মন্দ কোড :)
Benjol

@ বেঞ্জল আপনি বলেছেন যে আপনি মন্দ পরামর্শের জন্য উন্মুক্ত ছিলেন, না? ;)
পিটার ওলসন

হ্যাঁ, একেবারে, এটি কেবল আপনার "
মন্দগুলি

4
এটি এত ভয়াবহ, আমি কেবল এটির উপরে
উঠে যেতে হয়েছিল

শিরলে, আপনি সিরিয়াস নন !!!!!!
টেক্সাসে জিম

-1

যেহেতু আপনি কৌতূহল থেকে জিজ্ঞাসা করেছেন, এবং আপনার প্রশ্নটি একটি নির্দিষ্ট ভাষার সাথে ট্যাগ করা হয়নি (যদিও এটি স্পষ্ট যে আপনার মনে মনে জরুরী ভাষাগুলি ছিল) তবে এটি যুক্তিযুক্ত হতে পারে যে অলস মূল্যায়নের পক্ষে সমর্থনকারী ভাষাগুলি সম্পূর্ণ ভিন্ন পদ্ধতির অনুমতি দেয়। এই ভাষাগুলিতে, প্রয়োজনের সময় এক্সপ্রেশনগুলি কেবল মূল্যায়ন করা হয়, সুতরাং আপনি "ভেরিয়েবলগুলি" সংজ্ঞায়িত করতে পারেন এবং কেবল তখনই ব্যবহার করতে পারবেন যখন এটির বোধগম্যতা আসে। উদাহরণস্বরূপ, অলস let/ inকাঠামোর সাথে একটি কল্পিত ভাষায় আপনি প্রবাহ নিয়ন্ত্রণ এবং লেখার কথা ভুলে যান:

let
  contents = ReadFile(file)
in
  if FileExists(file) && SomeTest(contents) 
    DoSomething(contents)
  else 
    DefaultAction()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.