বৈধতা চেক সহ নিয়ন্ত্রণ প্রবাহের জন্য স্টাইল


27

আমি নিজেকে প্রচুর কোড লিখতে পাই:

int myFunction(Person* person) {
  int personIsValid = !(person==NULL);
  if (personIsValid) {
     // do some stuff; might be lengthy
     int myresult = whatever;
     return myResult;
  }
  else {
    return -1;
  }
}

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

int netWorth(Person* person) {
  if (Person==NULL) {
    return -1;
  }
  if (!(person->isAlive))  {
    return -1;
  }
  int assets = person->assets;
  if (assets==-1)  {
    return -1;
  }
  int liabilities = person->liabilities;
  if (liabilities==-1) {
    return -1;
  }
  return assets - liabilities;
}

আমি এখানে স্টাইলিস্টিক পছন্দ সম্পর্কে মন্তব্য করতে আগ্রহী। [স্বতন্ত্র বক্তব্যগুলির বিবরণ সম্পর্কে খুব বেশি চিন্তা করবেন না; এটি সামগ্রিক নিয়ন্ত্রণ প্রবাহ যা আমার আগ্রহী]]


8
আপনার উদাহরণে মোটামুটি গুরুতর স্পেসিফিকেশন ত্রুটি রয়েছে তা আমাকে উল্লেখ করার অনুমতি দিন। যদি উদাহরণস্বরূপ, সম্পদ == 42 এবং দায় == 43, আপনি ব্যক্তিকে অস্তিত্বহীন ঘোষণা করবেন।
জন আর। স্ট্রোহাম

একটি ব্যতিক্রম ছুঁড়ে না দেওয়া এবং ক্লায়েন্ট কোডের বৈধতাগুলি পরিচালনা করার সুযোগ দেবে না?
তুলিনাস কর্ডোভা

@ তুলিনস কর্ডোভা ব্যতিক্রমগুলি উপলভ্য নাও হতে পারে, বা সম্ভবত অবৈধ ডেটা যথেষ্ট ব্যতিক্রমী নয় যে স্ট্যাক ট্রেস ইত্যাদি নির্মাণের কার্যকারিতা প্রভাব গ্রহণযোগ্য।
হাল্ক

উত্তর:


27

এই জাতীয় সমস্যার জন্য মার্টিন ফোলার প্রস্তাবিত স্পেসিফিকেশন প্যাটার্ন :

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

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

আমি এটি যেভাবে দেখছি, মূল ধারণাটি "নিষ্কাশন" কোড যা ডেডিকেটেড পদ্ধতি (গুলি) / অবজেক্টগুলিতে চেক করে।

আপনার netWorthউদাহরণ সহ, এটি নিম্নলিখিত হিসাবে সন্ধান করতে পারে:

int netWorth(Person* person) {
  if (isSatisfiedBySpec(person)) {
    return person->assets - person->liabilities;
  }
  log("person doesn't satisfy spec");
  return -1;
}

#define BOOLEAN int // assuming C here
BOOLEAN isSatisfiedBySpec(Person* person) {
  return Person != NULL
      && person->isAlive
      && person->assets != -1
      && person->liabilities != -1;
}

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

আমি সাধারণত একটি উত্সর্গীকৃত অবজেক্টে "স্পেক" সম্পর্কিত পদ্ধতিগুলি গ্রুপ / এক্সট্রাক্ট করি, যদিও আপনার কেসটি এটি ছাড়াই ঠিক আছে।

  // ...
  Specification s, *spec = initialize(s, person);
  if (spec->isSatisfied()) {
    return person->assets - person->liabilities;
  }
  log("person doesn't satisfy spec");
  return -1;
  // ...

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


8

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

int netWorth(Person* person) { 
    if(validPerson(person)) {
        int assets = person->assets;
        int liabilities = person->liabilities;
        return assets - liabilities;
    }
    else {
        return -1;
    }
}

bool validPerson(Person* person) { 
    if(person!=NULL && person->isAlive
      && person->assets !=-1 && person->liabilities != -1)
        return true;
    else
        return false;
}

2
কেন তুমি আছে ifমধ্যে validPerson? কেবল person!=NULL && person->isAlive && person->assets !=-1 && person->liabilities != -1পরিবর্তে ফিরে আসুন।
ডেভিড হামেন

3

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

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

আপনার উদাহরণের এই পুনরুদ্ধার বিবেচনা করুন:

int myFunction(Person* person) {
  int personIsValid = !(person==NULL);
  if (personIsValid) {
     return myFunctionWork(person)
  }
  else {
    return -1;
  }
}

int myFunction(Person *person) {
  assert( person != NULL);  
  // Do work and return
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.