"অন্য" পরিস্থিতিগুলিতে নিয়ন্ত্রণ প্রবাহ এটিকে অপ্রয়োজনীয় উপস্থাপন করে?


18

আমি মাঝে মাঝে নীচের উদাহরণের মতো কোডের উপর হোঁচট খেয়ে যাই (এই ফাংশনটি ঠিক কী করে তোলে এই প্রশ্নের ক্ষেত্রের বাইরে):

function doSomething(value) {
  if (check1(value)) {
    return -1;
  }
  else if (check2(value)) {
    return value;
  }
  else {
    return false;
  }
}

যেহেতু আপনি দেখতে পারেন, if, else ifএবং elseবিবৃতি সাথে ব্যবহার করা হয় returnবিবৃতি। এটি একটি নৈমিত্তিক পর্যবেক্ষকের কাছে মোটামুটি স্বজ্ঞাত বলে মনে হচ্ছে, তবে আমি মনে করি যে এটিগুলি (সফ্টওয়্যার বিকাশকারীর দৃষ্টিকোণ থেকে) else-এসটি ছেড়ে দেওয়া এবং কোডটি সরলীকরণ করার জন্য এটি আরও মার্জিত হবে :

function doSomething(value) {
  if (check1(value)) {
    return -1;
  }
  if (check2(value)) {
    return value;
  }
  return false;
}

এটি অর্থবোধ করে, কারণ একটি returnবিবৃতি অনুসরণকারী (একই স্কোপ) এর সমস্ত কিছু কখনই কার্যকর করা হবে না, উপরের কোডটি শব্দার্থগতভাবে প্রথম উদাহরণের সমান করে তুলবে।

উপরের কোনটি ভাল কোডিং অনুশীলন আরও ফিট করে? কোড পঠনযোগ্যতার বিষয়ে কোনও পদ্ধতির কোনও ত্রুটি আছে কি?

সম্পাদনা করুন: এই প্রশ্নটিকে রেফারেন্স হিসাবে সরবরাহ করে একটি সদৃশ পরামর্শ দেওয়া হয়েছে । আমি বিশ্বাস করি যে আমার প্রশ্নটি অন্য একটি বিষয়কে স্পর্শ করে, যেহেতু আমি অন্য প্রশ্নের মতো উপস্থাপন করা সদৃশ বিবৃতি এড়ানো সম্পর্কে জিজ্ঞাসা করছি না। উভয় প্রশ্নই পুনরাবৃত্তি হ্রাস করতে চায়, কিছুটা ভিন্ন উপায়েই।


14
elseএকটি ক্ষুদ্রতর ইস্যু, বড় সমস্যা স্পষ্টত একটি একক ফাংশন, যা ফাংশনের এপিআই হয়ে পড়েছে বাইরে দুই ধরনের তথ্য ফেরার হয়।
অ্যান্ডি

3
E_CLEARLY_NOTADUPE
কোজির

3
@ ডেভিডপ্যাকার: কমপক্ষে দুটি; তিনটি হতে পারে।-1এটি একটি সংখ্যা, falseএকটি বুলিয়ান, এবং valueএখানে নির্দিষ্ট করা হয়নি তাই এটি কোনও ধরণের অবজেক্ট হতে পারে।
Yay295

1
@ Yay295 আমি আশা করছি ing value এটি আসলে একটি পূর্ণসংখ্যা। যদি এটি কিছু হতে পারে তবে এটি আরও খারাপ।
অ্যান্ডি

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

উত্তর:


23

আমি ছাড়া একটি elseএবং এখানে কেন এটি পছন্দ :

function doSomething(value) {
  //if (check1(value)) {
  //  return -1;
  //}
  if (check2(value)) {
    return value;
  }
  return false;
}

কারণ এটি করে এমন কিছু ভাঙ্গেনি যা এটি করার কথা ছিল না।

এটির সমস্ত রূপগুলিতে ঘৃণ্য নির্ভরতা (কোনও ফাংশনের নামকরণ সহ check2()) বিচ্ছিন্ন করা যেতে পারে যে সমস্ত বিচ্ছিন্ন। কখনও কখনও আপনার প্রয়োজন elseকিন্তু আমি এখানে এটি দেখতে পাচ্ছি না।


আমি সাধারণত এটিকেও পছন্দ করি কারণ এখানে বর্ণিত কারণে। যাইহোক, আমি সাধারণত প্রতিটি ifব্লকের বন্ধে একটি মন্তব্য } //elseরাখি যাতে কোডটি পড়ার সময়, ifকোড ব্লকের পরে একমাত্র উদ্দেশ্যমূলক সম্পাদন হয় যদি ifবিবৃতিতে শর্তটি মিথ্যা ছিল। এই জাতীয় কিছু ছাড়াই, বিশেষত যদি ifব্লকের কোডটি আরও জটিল আকার ধারণ করে, তবে যে কেউ কোডটি বজায় রাখছেন তাদের পক্ষে এটি স্পষ্ট হতে পারে না যে শর্তটি সত্য ifহলে অভিপ্রায়টি কখনই ব্লকের অতীতকে কার্যকর ifকরা উচিত নয়।
মাকেন

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

27

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

if (x < 0) {
    return false;
} else if (x > 0) {
    return true;
} else {
    throw new IllegalArgumentException();
}

এখানে আপনি স্পষ্টভাবে মান এর উপর নির্ভর করে x তিনটি ক্ষেত্রেই । আপনি যদি শেষটি বাদ দিতে চান elseতবে এটি কম পরিষ্কার হবে।

যদি আপনার কেসগুলি একে অপরের উপর সরাসরি নির্ভর না করে থাকে তবে এটিকে বাদ দিন:

if (x < 0) {
    return false;
}
if (y < 0) {
    return true;
}
return false;

প্রসঙ্গ ছাড়াই এটি একটি সাধারণ উদাহরণে দেখানো কঠিন, তবে আমি আশা করি আপনি আমার বক্তব্যটি পেয়ে গেছেন।


6

আমি দ্বিতীয় বিকল্প (পৃথক পছন্দ ifsসঙ্গে else ifএবং তাড়াতাড়ি return) কিন্তু যে যতদিন কোড ব্লক ছোট

কোড ব্লক যদি দীর্ঘ হয় তবে এটি ব্যবহার করা আরও ভাল else if , কারণ কোডগুলির মধ্যে রয়েছে এমন কয়েকটি বহির্গমন পয়েন্ট সম্পর্কে আপনার কাছে পরিষ্কার ধারণা নেই।

উদাহরণ স্বরূপ:

function doSomething(value) {
  if (check1(value)) {
    // ...
    // imagine 200 lines of code
    // ...
    return -1;
  }
  if (check2(value)) {
    // ...
    // imagine 150 lines of code
    // ...
    return value;
  }
  return false;
}

else ifসেক্ষেত্রে এটি আরও ভাল ব্যবহার , রিটার্ন কোডটি একটি ভেরিয়েবলে সংরক্ষণ করুন এবং শেষে কেবল একটি রিটার্ন বাক্য রাখুন।

function doSomething(value) {
  retVal=0;
  if (check1(value)) {
    // ...
    // imagine 200 lines of code
    // ...
    retVal=-1;
  } else if (check2(value)) {
    // ...
    // imagne 150 lines of code
    retVal=value;
  }
  return retVal;
}

তবে কারও পক্ষে ফাংশনগুলি সংক্ষিপ্ত হওয়ার জন্য প্রচেষ্টা করা উচিত, আমি এটিকে সংক্ষিপ্ত রাখব এবং প্রথম কোড স্নিপেটের মতো তাড়াতাড়ি প্রস্থান করবো।


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

1
একটি কৌতূহল যুক্তি। return3 লাইনের মধ্যে ifতাই এটি else if200 লাইনের কোডের পরেও আলাদা নয় । আপনি এখানে যে একক রিটার্ন স্টাইলটি প্রবর্তন করছেন তা হ'ল গ এবং অন্যান্য ভাষার traditionতিহ্য যা ব্যতিক্রমগুলি সহ ত্রুটিগুলি রিপোর্ট করে না। মূল বিষয়টি ছিল সংস্থান পরিষ্কার করার জন্য একটি একক জায়গা তৈরি করা। ব্যতিক্রম ভাষাগুলি এর জন্য একটি finallyব্লক ব্যবহার করে। আমি মনে করি এটির একটি ব্রেক পয়েন্ট স্থাপনের জন্য একটি জায়গা তৈরি করে যদি আপনার ডিবাগারটি আপনাকে কোঁকড়া বন্ধনী বন্ধ করে ফাংশনগুলিতে একটি রাখে না।
candied_orange

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

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

2
আমি এখানে ডেভিডপ্যাকারের সাথে আছি। একক রিটার্ন শৈলী আমাদের অ্যাসাইনমেন্ট পয়েন্টগুলির পরে সমস্ত অ্যাসাইনমেন্ট পয়েন্ট পাশাপাশি কোড অধ্যয়ন করতে বাধ্য করে। প্রারম্ভিক রিটার্ন শৈলীর প্রস্থান পয়েন্টগুলি অধ্যয়ন করা আমার কাছে দীর্ঘ বা সংক্ষিপ্ত পছন্দ হবে। এতক্ষণ ভাষাটি শেষ অবধি ব্লক করার অনুমতি দেয়।
candied_orange

4

আমি উভয় বিভিন্ন পরিস্থিতিতে ব্যবহার করি। একটি বৈধতা যাচাই করে, আমি অন্যটি বাদ দিই। একটি নিয়ন্ত্রণ প্রবাহে, আমি অন্যটি ব্যবহার করি।

bool doWork(string name) {
  if(name.empty()) {
    return false;
  }

  //...do work
  return true;
}

বনাম

bool doWork(int value) {
  if(value % 2 == 0) {
    doWorkWithEvenNumber(value);
  }
  else {
    doWorkWithOddNumber(value);
  }
}

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


0

একমাত্র পরিস্থিতি যা আমি এর আগে দেখেছি তা হল কোডের মতো:

List<?> toList() {
    if (left != null && right != null) {
        Arrays.asList(merge(left, right));
    }
    if (left != null) {
        return Arrays.asList(left);
    }
    if (right != null) {
        return Arrays.asList(right);
    }
    return Arrays.asList();
}

এখানে স্পষ্টতই কিছু ভুল আছে। সমস্যাটি হচ্ছে, এটি returnযুক্ত করা বা Arrays.asListঅপসারণ করা উচিত কিনা তা পরিষ্কার নয় । সম্পর্কিত পদ্ধতির গভীর পরিদর্শন ছাড়া আপনি এটিকে ঠিক করতে পারবেন না। আপনি যদি অন্যথায় অবরুদ্ধ হন তবে সর্বদা সম্পূর্ণ পরিসীমা ব্যবহার করে এই অস্পষ্টতা এড়াতে পারেন। এই:

List<?> toList() {
    if (left != null && right != null) {
        Arrays.asList(merge(left, right));
    } else if (left != null) {
        return Arrays.asList(left);
    } else if (right != null) {
        return Arrays.asList(right);
    } else {
        return Arrays.asList();
    }
}

আপনি প্রথমে স্পষ্টরূপে রিটার্ন যোগ না করলে সংকলন করবেন না (স্থিরভাবে পরীক্ষিত ভাষায়) if

কিছু ভাষা এমনকি প্রথম শৈলীর অনুমতি দেয় না। আমি এটি কেবল কঠোরভাবে আবশ্যক প্রসঙ্গে বা দীর্ঘ পদ্ধতিতে পূর্ব শর্তগুলির জন্য ব্যবহার করার চেষ্টা করি:

List<?> toList() {
    if (left == null || right == null) {
        throw new IllegalStateException()
    }
    // ...
    // long method
    // ...
}

-2

যদি আপনি কোডটি অনুসরণ করার চেষ্টা করছেন বা খারাপ অনুশীলনের মাধ্যমে ফাংশনটি থেকে তিনটি প্রস্থান করা সত্যিই বিভ্রান্তিকর।

যদি ফাংশনটির জন্য আপনার একক প্রস্থান পয়েন্ট থাকে তবে এলিজগুলি প্রয়োজন।

var result;
if(check1(value)
{
    result = -1;
}
else if(check2(value))
{
    result = value;
}
else 
{
    result = 0;
}
return result;

আসলে আরও আরও যেতে দেয়।

var result = 0;
var c1 = check1(value);
var c2 = check2(value);

if(c1)
{
    result = -1;
}
else if(c2)
{
    result = value;
}

return result;

যথেষ্ট পরিমাণে আপনি ইনপুট বৈধতার একক প্রারম্ভিক রিটার্নের জন্য তর্ক করতে পারেন। যদি আপনার যুক্তিটি যদি হয় তবে কেবল পুরো বাল্কটিকে মোড়ানো এড়িয়ে চলুন।


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

a: প্রশ্নের মধ্যে কোন ভাষা নির্দিষ্ট করা হয়নি। বি: আমি মনে করি আপনি এই বিষয়ে ভুল। একক ফেরতের জন্য যথেষ্ট কারণ রয়েছে। এটি জটিলতা হ্রাস করে এবং পাঠযোগ্যতা বাড়ায়
ইওয়ান

1
কখনও কখনও এটি জটিলতা হ্রাস করে, কখনও কখনও এটি বাড়িয়ে তোলে। Wiki.c2.com/?ArrowAntiPattern
রবার্ট জনসন

না, আমি মনে করি এটি সর্বদা চক্রবৃত্তীয় জটিলতা হ্রাস করে, আমার দ্বিতীয় উদাহরণটি দেখুন। চেক 2 সর্বদা চলমান
ইওয়ান

প্রারম্ভিক রিটার্ন পাওয়া একটি অপ্টিমাইজেশন যা শর্তসাপেক্ষে কিছু কোড সরিয়ে কোডকে জটিল করে তোলে
ইওয়ান

-3

আমি অপ্রয়োজনীয় বিবৃতি বাদ দেওয়া পছন্দ করি। আমি যখনই এটি দেখি (কোড পর্যালোচনা বা রিফ্যাক্টরিংয়ে) আমি ভাবছি যে লেখক নিয়ন্ত্রণ প্রবাহটি বুঝতে পেরেছিলেন এবং কোডটিতে কোনও ত্রুটি থাকতে পারে।

যদি লেখক বিশ্বাস করেন যে অন্য বিবৃতিটি প্রয়োজনীয় ছিল এবং এইভাবে রিটার্নের বিবৃতিটির নিয়ন্ত্রণ প্রবাহের প্রভাবগুলি বুঝতে না পারে তবে অবশ্যই এই ধরণের এবং সাধারণভাবে এই ধরণের বোঝার অভাবগুলি বাগের প্রধান উত্স।


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