নিয়ন্ত্রণ প্রবাহ হিসাবে ব্যতিক্রমগুলি কি গুরুতর অ্যান্টিপ্যাটার্ন হিসাবে বিবেচিত হয়? যদি তাই হয় তবে কেন?


129

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

তাদের দু'জনেরই Controllerসিদ্ধান্ত রয়েছে যে কোথায় যেতে হবে এবং ডেটা গন্তব্য যুক্তিতে সরবরাহ করতে হবে। পুরাতন-স্কুল টেলিফোনের ডোমেন থেকে ব্যবহারকারীর ক্রিয়া, যেমন ডিটিএমএফ টোনগুলি, ক্রিয়া পদ্ধতির পরামিতি হয়ে ওঠে, তবে এর মতো কিছু ফেরানোর পরিবর্তে ViewResultতারা একটি নিক্ষেপ করেছিল StateTransitionException

আমি মনে করি মূল পার্থক্যটি ছিল ক্রিয়া পদ্ধতিগুলি ছিল voidফাংশন। আমি এই সত্যটি দিয়ে যা করেছি তা আমার মনে নেই তবে আমি মনে রাখার মতো রাস্তায় নামতেও দ্বিধা বোধ করছি কারণ ১৫ বছর আগের মতো এই কাজটি আমি অন্য কোনও কাজের ক্ষেত্রে প্রযোজনা কোডে কখনও দেখিনি । আমি ধরে নিয়েছিলাম এটি এটি একটি তথাকথিত অ্যান্টি-প্যাটার্ন ছিল sign

এই ঘটনাটি কি এবং যদি তাই হয় তবে কেন?

আপডেট: আমি যখন প্রশ্নটি জিজ্ঞাসা করেছি, ইতিমধ্যে আমার কাছে @ ম্যাসনওহিলারের উত্তর ছিল তাই আমি আমার উত্তরটিতে সবচেয়ে বেশি যুক্ত হওয়া উত্তরটি দিয়ে গেলাম। আমি মনে করি তার ভাল উত্তরও আছে।



25
পাইথনে, নিয়ন্ত্রণ প্রবাহ হিসাবে ব্যতিক্রমগুলি ব্যবহার করা "পাইথোনিক" হিসাবে বিবেচিত।
ব্যবহারকারী16764

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

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

8
ব্যতিক্রমগুলি কি সর্বদা কোনও অ্যাপ্লিকেশন প্রবাহকে নিয়ন্ত্রণ করে না?

উত্তর:


109

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

কেন, সাধারণভাবে এটি একটি অ্যান্টি-প্যাটার্নের দ্রুত সংক্ষিপ্তসার হিসাবে:

  • ব্যতিক্রমগুলি হ'ল সংক্ষেপে অত্যাধুনিক GOTO বিবৃতি
  • ব্যতিক্রম সহ প্রোগ্রামিং, সুতরাং কোড পড়তে এবং বুঝতে আরও অসুবিধার দিকে নিয়ে যায়
  • বেশিরভাগ ভাষায় ব্যতিক্রমগুলি ব্যবহার না করেই আপনার সমস্যার সমাধানের জন্য ডিজাইন করা বিদ্যমান নিয়ন্ত্রণ কাঠামো রয়েছে
  • দক্ষতার জন্য যুক্তিগুলি আধুনিক কম্পাইলারদের কাছে ঝোঁক ঝোঁক থাকে, যা নিয়ন্ত্রণ প্রবাহের জন্য ব্যতিক্রমগুলি ব্যবহৃত হয় না এমন ধারণার সাথে অনুকূল হয়ে যায়।

আরও গভীরতর তথ্যের জন্য ওয়ার্ডের উইকিতে আলোচনাটি পড়ুন।


এখানে এই প্রশ্নের সদৃশও দেখুন


18
আপনার উত্তরটি এটিকে শোনায় যেহেতু ব্যতিক্রমগুলি সমস্ত পরিস্থিতিতে খারাপ ,
whatsisname

14
@ ম্যাসনভিয়েল পার্থক্যটি হ'ল / যখন লুপগুলিতে তাদের প্রবাহ নিয়ন্ত্রণের পরিবর্তনগুলি পরিষ্কারভাবে থাকে এবং কোডটি পড়া সহজ করে তোলে। আপনি যদি আপনার কোডটিতে বিবৃতি দেওয়ার জন্য দেখতে পান তবে কোন ফাইলটিতে লুপের শেষ রয়েছে তা নির্ধারণের চেষ্টা করার দরকার নেই। গোটো খারাপ নয় কারণ কিছু godশ্বর বলেছিলেন যে তারা ছিল, এগুলি কেবল খারাপ কারণ তারা লুপিং নির্মাণগুলির চেয়ে অনুসরণ করা শক্ত। ব্যতিক্রমগুলি সমান, অসম্ভব নয় তবে যথেষ্ট কঠিন যে তারা জিনিসগুলিকে বিভ্রান্ত করতে পারে।
বিল কে

24
@ বিল্ক, তারপরে যুক্তি দিন, এবং কীভাবে ব্যতিক্রমগুলি গোটস হয় সে সম্পর্কে সরল বক্তব্য দেবেন না।
উইনস্টন ইওয়ার্ট

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

12
@ ম্যাট্টনজ: ifএবং foreachসূক্ষ্ম GOTOএস। সত্যি বলতে গেলে, আমি মনে করি গোটোর সাথে তুলনা সহায়ক নয়; এটি প্রায় অবমাননাকর শব্দের মতো। এতে যান ব্যবহার অন্তর্নিহিত মন্দ নয় - এটা বাস্তব সমস্যা রয়েছে, এবং ব্যতিক্রম পারে সেই ভাগ, কিন্তু তারা হয়তো নেই। এই সমস্যাগুলি শুনতে আরও সহায়ক হবে।
ইমন নারবোনে

110

ব্যতিক্রমগুলির জন্য যে ব্যবহারগুলি তৈরি করা হয়েছিল সেগুলি হ'ল "আমি কেবলমাত্র এমন পরিস্থিতির মুখোমুখি হয়েছি যে আমি এই মুহুর্তে সঠিকভাবে মোকাবেলা করতে পারি না, কারণ এটি পরিচালনা করার মতো পর্যাপ্ত প্রসঙ্গ আমার কাছে নেই, তবে যে রুটিন আমাকে ডেকেছিল (বা আরও কিছু কল করেছিল) স্ট্যাক) এটি পরিচালনা করার পদ্ধতিটি জানা উচিত ""

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

যদি আপনি এই দুটি কারণে কোনও কারণে ব্যতিক্রম ব্যবহার না করেন, সম্ভবত এটি করার আরও ভাল উপায়।


18
এটি যদিও প্রশ্নের উত্তর দেয় না। তাদের জন্য যা ডিজাইন করা হয়েছিল তা অপ্রাসঙ্গিক; কেবল প্রাসঙ্গিক বিষয় হ'ল নিয়ন্ত্রণ প্রবাহের জন্য এগুলি ব্যবহার করা কেন খারাপ, যা আপনি স্পর্শ করেননি এমন একটি বিষয়। উদাহরণস্বরূপ, সি ++ টেমপ্লেটগুলি একটি জিনিসের জন্য ডিজাইন করা হয়েছিল তবে রূপকোষের জন্য ব্যবহার করা পুরোপুরি সূক্ষ্ম, এমন কোনও ডিজাইনার যেমন প্রত্যাশা করেননি।
থমাস বোনিিনি

6
@ ক্রেলপ: ডিজাইনাররা কখনও অনেক কিছুই প্রত্যাশা করেনি, যেমন দুর্ঘটনাক্রমে টুরিং-সম্পূর্ণ টেম্পলেট সিস্টেমটি শেষ করে! সি ++ টেমপ্লেটগুলি এখানে ব্যবহারের জন্য খুব ভাল উদাহরণ।
ম্যাসন হুইলারের

15
@ ক্রেল্প - সি ++ টেমপ্লেটগুলি রূপকবিদ্যার জন্য 'পুরোপুরি সূক্ষ্ম' নয়। এগুলি একটি দুঃস্বপ্ন হয়ে থাকে যতক্ষণ না আপনি এগুলি ঠিক করেন এবং তারপরে আপনি কেবল টেমপ্লেট-প্রতিভা না হয়ে থাকলে কেবল লেখার কোডের দিকে ঝুঁকেন। আপনি আরও ভাল উদাহরণ চয়ন করতে পারেন।
মাইকেল কোহনে

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

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

29

ব্যতিক্রমগুলি কন্টিনিয়েশন এবং এর মতো শক্তিশালী GOTO। এগুলি সর্বজনীন নিয়ন্ত্রণ প্রবাহের নির্মাণ।

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

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

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


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

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

1
লেজ পুনরাবৃত্তি একটি দুর্দান্ত বোনাস হত (তারা ভবিষ্যতে এটি ফাংশন বৈশিষ্ট্য হ্রাস করা হয়) তবে হ্যাঁ, আমি বলব বৈশিষ্ট্য সম্পর্কিত কারণে এটি ভিবি, ফ্ল্যাশ, অ্যাপলেটস ইত্যাদির বিরুদ্ধে জিতেছে। যদি এটি জটিলতা হ্রাস না করে এবং হস্তের সাথে সাধারণভাবে যেমন স্বাভাবিক হয় তবে এটির কোনও পর্যায়ে আসল প্রতিযোগিতা হত। আমি বর্তমানে একটি জঘন্য সি # + জাভা স্ট্যাকের জন্য 21 টি কনফিগারেশন ফাইলের পুনরায় লেখা পরিচালনা করতে নোড.জেএস চালিয়ে যাচ্ছি এবং আমি জানি যে আমি কেবল সেখানে আছি না। এটি যা ভাল তাতে খুব ভাল।
এরিক পুনরায়

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

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

19

অন্যরা যেমন উল্লেখ করেছেন, ( উদাহরণস্বরূপ এই স্ট্যাক ওভারফ্লো প্রশ্নে ), অন্তত বিস্মিত হওয়ার নীতিটি কেবলমাত্র প্রবাহ নিয়ন্ত্রণের উদ্দেশ্যে ব্যতিক্রমগুলি অতিরিক্ত মাত্রায় ব্যবহার করা নিষিদ্ধ করবে। অন্যদিকে, কোনও নিয়ম 100% সঠিক নয়, এবং সবসময় এমন ক্ষেত্রে দেখা যায় যে ব্যতিক্রমগুলি "ঠিক সঠিক সরঞ্জাম" - অনেকটা gotoনিজের মতো , উপায় অনুসারে, যা জাভা-র মতো ভাষাতে breakএবং জাহাজ হিসাবে জাহাজে আসে continueভারী নেস্টেড লুপগুলি থেকে ঝাঁপ দেওয়ার প্রায়শই সঠিক উপায়, যা সর্বদা এড়ানো যায় না।

নিম্নলিখিত ব্লগ পোস্টটি অ-স্থানীয়দের জন্য একটি জটিল বরং বরং আকর্ষণীয় ব্যবহারের ক্ষেত্রে ব্যাখ্যা করেছে ControlFlowException:

এটি ব্যাখ্যা করে যে কীভাবে JOOQ এর ভিতরে (জাভার জন্য একটি এসকিউএল অ্যাবস্ট্রাকশন লাইব্রেরি) (অস্বীকৃতি: আমি বিক্রেতার পক্ষে কাজ করি), কিছু "বিরল" শর্ত পূরণ হওয়ার পরে এই ধরনের ব্যতিক্রমগুলি মাঝে মাঝে এসকিউএল রেন্ডারিং প্রক্রিয়াটি বাতিল করতে ব্যবহৃত হয়।

এই ধরনের শর্তগুলির উদাহরণগুলি:

  • অনেকগুলি বাঁধাই মানগুলির মুখোমুখি। কিছু ডাটাবেসগুলি তাদের এসকিউএল স্টেটমেন্টগুলিতে বিন্যাসের মানগুলিকে নির্বিচারে সমর্থন করে না (এসকিউএলাইট: 999, ইংরাজী 10.1.0: 1024, সিবাজ এএসই 15.5: 2000, এসকিউএল সার্ভার ২০০৮: ২১০০)। এই ক্ষেত্রে, JOOQ এসকিউএল রেন্ডারিং পর্বটি বাতিল করে এবং ইনক্লাইড বাইন্ড মান সহ এসকিউএল বিবৃতিটিকে পুনরায় রেন্ডার করে। উদাহরণ:

    // Pseudo-code attaching a "handler" that will
    // abort query rendering once the maximum number
    // of bind values was exceeded:
    context.attachBindValueCounter();
    String sql;
    try {
    
      // In most cases, this will succeed:
      sql = query.render();
    }
    catch (ReRenderWithInlinedVariables e) {
      sql = query.renderWithInlinedBindValues();
    }
    

    যদি আমরা স্পষ্টরূপে এএসটি ক্যোয়ারী থেকে প্রতিবারের জন্য এটির মানগুলি স্পষ্টভাবে বের করেছি, আমরা এই 999% প্রশ্নের জন্য মূল্যবান সিপিইউ চক্রগুলি নষ্ট করব না যা এই সমস্যায় ভুগছে না।

  • কিছু যুক্তি অপ্রত্যক্ষভাবে একটি API এর মাধ্যমে উপলভ্য যা আমরা কেবল "আংশিকভাবে" চালাতে চাই। UpdatableRecord.store()পদ্ধতি একটি উত্পন্ন INSERTবা UPDATEবিবৃতি উপর নির্ভর করে Recordএর অভ্যন্তরীণ পতাকা। "বাইরের" থেকে, আমরা জানি না কী ধরণের যুক্তি রয়েছে store()(যেমন আশাবাদী লকিং, ইভেন্ট শ্রোতাদের পরিচালনা ইত্যাদি) তাই আমরা যখন ব্যাচের বিবৃতিতে বেশ কয়েকটি রেকর্ড সংরক্ষণ করি তখন আমরা সেই যুক্তিটির পুনরাবৃত্তি করতে চাই না, যেখানে আমরা store()কেবলমাত্র এসকিউএল বিবৃতি তৈরি করতে চাই , বাস্তবে এটি কার্যকর করা হয় না। উদাহরণ:

    // Pseudo-code attaching a "handler" that will
    // prevent query execution and throw exceptions
    // instead:
    context.attachQueryCollector();
    
    // Collect the SQL for every store operation
    for (int i = 0; i < records.length; i++) {
      try {
        records[i].store();
      }
    
      // The attached handler will result in this
      // exception being thrown rather than actually
      // storing records to the database
      catch (QueryCollectorException e) {
    
        // The exception is thrown after the rendered
        // SQL statement is available
        queries.add(e.query());                
      }
    }
    

    যদি আমরা store()যুক্তিটিকে "পুনরায় ব্যবহারযোগ্য" এপিআই-তে পরিণত করে থাকি যা এসকিউএলটি কার্যকরভাবে প্রয়োগ না করার জন্য কাস্টমাইজ করা যেতে পারে , তবে আমরা খুব শক্তভাবে পুনরায় ব্যবহারযোগ্য এপিআই বজায় রাখার পরিবর্তে আরও শক্তিশালী হয়ে উঠতে চাই।

উপসংহার

সংক্ষেপে বলতে gotoগেলে , এই অ-স্থানীয় ব্যবহারের বিষয়টি ম্যাসন হুইলার তার উত্তরে যা বলেছিল তার ঠিক ঠিক একই সাথে :

"আমি কেবলমাত্র এমন পরিস্থিতির মুখোমুখি হয়েছি যে আমি এই মুহুর্তে সঠিকভাবে মোকাবেলা করতে পারি না, কারণ এটি পরিচালনা করার মতো আমার কাছে যথেষ্ট প্রসঙ্গ নেই, তবে যে রুটিন আমাকে ডেকেছিল (বা কল স্ট্যাককে আরও কিছু বলা হয়েছে) কীভাবে এটি পরিচালনা করতে হবে তা জানতে হবে । "

এর উভয় ব্যবহারই ControlFlowExceptionsতাদের বিকল্পগুলির তুলনায় কার্যকর করা সহজ ছিল, যা প্রাসঙ্গিক ইন্টার্নালগুলির বাইরে রিফ্যাক্টর না করেই আমাদের অনেকগুলি যুক্তি পুনরায় ব্যবহার করতে দেয়।

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


11

নিয়ন্ত্রণ প্রবাহের জন্য ব্যতিক্রমগুলি ব্যবহারকে সাধারণত একটি অ্যান্টি-প্যাটার্ন হিসাবে বিবেচনা করা হয় তবে ব্যতিক্রমগুলি রয়েছে (কোনও পাং উদ্দেশ্যে নয়)।

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

আপনার সফ্টওয়্যারটির একটি বাগ যা একটি ফাংশনকে অবৈধ যুক্তিগুলির সাথে ডেকে আনে, যেমন nullযেখানে অনুমতি দেয় না, এটি একটি ব্যতিক্রমী শর্ত।

ব্যতিক্রমী নয় এমন কিছুতে ব্যতিক্রম ব্যবহার করে আপনি যে সমস্যার সমাধান করার চেষ্টা করছেন তার জন্য আপনি অনুপযুক্ত বিমূর্ততা ব্যবহার করছেন।

তবে পারফরম্যান্স পেনাল্টিও হতে পারে। কিছু ভাষার কম-বেশি দক্ষ ব্যতিক্রম হ্যান্ডলিং বাস্তবায়ন রয়েছে, সুতরাং আপনার পছন্দের ভাষাটিতে যদি দক্ষ ব্যতিক্রম হ্যান্ডলিং না থাকে তবে এটি খুব ব্যয়বহুল, পারফরম্যান্স-ভিত্তিক * হতে পারে।

তবে অন্যান্য ভাষাগুলি, উদাহরণস্বরূপ রুবিতে নিয়ন্ত্রণ প্রবাহের ক্ষেত্রে ব্যতিক্রমের মতো সিনট্যাক্স রয়েছে। ব্যতিক্রমী পরিস্থিতি raise/ rescueঅপারেটররা পরিচালনা করে । কিন্তু আপনি ব্যবহার করতে পারেন throw/ catchব্যতিক্রম মত নিয়ন্ত্রণ প্রবাহ নির্মান জন্য **।

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

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

** এটি কোনও প্রোগ্রামারকে অন্য ভাষা থেকে রুবিতে আসার জন্য খুব বিভ্রান্তকর হতে পারে throwএবং catchএটি উভয়ই অন্যান্য ভাষায় ব্যতিক্রম সম্পর্কিত কীওয়ার্ড।


1
"1" ব্যতিক্রমী কিছু নয় এমন ব্যতিক্রম ব্যবহার করে আপনি যে সমস্যার সমাধান করার চেষ্টা করছেন তার জন্য আপনি অনুপযুক্ত বিমূর্ততা ব্যবহার করছেন ""
জর্জিও

8

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

status = getValue(&inout);
if (status < 0)
{
    logError("message");
    return status;
}

doSomething(*inout);

অথবা আপনার ভাষার সমতুল্য, একটি ত্রুটি অবস্থা, ইত্যাদি একটি মান সঙ্গে একটি tuple ফেরার মত প্রায়শই বাতলান যারা কিভাবে "ব্যয়বহুল" ব্যতিক্রম হ্যান্ডলিং যা মানুষের সঙ্গে মানুষের অবহেলা সব অতিরিক্ত ifবিবৃতি যে উপরোক্ত মত প্রয়োজন হয় যদি আপনি ডন যুক্ত করতে ' টি ব্যতিক্রম ব্যবহার করবেন না।

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

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


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

5

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

পাইথনে বহু-স্তরের বিরতি বা গোটো স্টেটমেন্টের অভাবের কারণে আমি মাঝে মাঝে ব্যতিক্রমগুলি ব্যবহার করেছি:

class GOTO(Exception):
  pass

try:
  # Do lots of stuff
  # in here with multiple exit points
  # each exit point does a "raise GOTO()"
except GOTO:
  pass
except Exception as e:
  #display error

6
আপনি যদি একটি গভীরভাবে নেস্টেড বিবৃতি কোথাও হিসাব সমাপ্ত করার এবং কিছু সাধারণ ধারাবাহিকতা কোড যেতে থাকে, তাহলে মৃত্যুদণ্ড এই বিশেষ পথ খুব সম্ভবত আউট একটি ফাংশন হিসাবে উপাদান করা যেতে পারে, সঙ্গে returnস্থানে goto
9000

3
@ 9000 আমি ঠিক একই জিনিস সম্পর্কে মন্তব্য করতে চলেছি ... try:1 বা 2 লাইনে ব্লক রাখুন দয়া করে, কখনই নয় try: # Do lots of stuff
wim

1
@ 9000, কিছু ক্ষেত্রে, নিশ্চিত তবে তারপরে আপনি স্থানীয় ভেরিয়েবলের অ্যাক্সেস হারাবেন এবং প্রক্রিয়াটি সুসংগত, লিনিয়ার প্রক্রিয়া হওয়ার পরে আপনি আপনার কোডটি অন্য কোনও জায়গায় সরিয়ে নিয়েছেন।
গাহোয়া

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

4

আসুন যেমন একটি ব্যতিক্রম ব্যবহার স্কেচ করা যাক:

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

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

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


হুঁ, আসলেই কি বিপরীত অবস্থানের পক্ষে হ্রাস, বা অপর্যাপ্ত বা সংক্ষিপ্ত যুক্তিযুক্ত? আমি সত্যিই কৌতূহলী।
জোপ এগেন

আমি ঠিক এই দুর্দশার মুখোমুখি হয়েছি, আমি আশা করছিলাম আপনি আমার নীচের প্রশ্নটি সম্পর্কে কী ভাবছেন তা আপনি দেখতে পাচ্ছেন? Recursively ব্যতিক্রম ব্যবহার কারণ (বার্তা) একটি শীর্ষ স্তরের ব্যতিক্রম জন্য স্তূপাকার codereview.stackexchange.com/questions/107862/...
CL22

@ জোডস আমি আপনার আকর্ষণীয় কৌশলটি সবেমাত্র পড়েছি, তবে আপাতত আমি বেশ ব্যস্ত। আশা করি অন্য কেউ এই বিষয়ে তার আলো ফেলবেন।
জোপ এগজেন

4

প্রোগ্রামিং কাজ সম্পর্কে

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

যতবারই কোনও পদ্ধতি কল করা হয়, কলারটি বলছে "আমি এই কাজটি করতে জানি না, তবে আপনি কীভাবে জানেন, তাই আপনি আমার জন্য এটি করেন।"

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

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

একটি ব্যতিক্রমী সাদৃশ্য

ধরা যাক আপনার একটি ছুতার, একটি নদীর গভীরতানির্ণয় এবং একটি বৈদ্যুতিনবিদ রয়েছে। আপনি আপনার ডোবা ঠিক করতে প্লাম্বার করতে চান, তাই তিনি এটি একবার দেখুন। এটি খুব কার্যকর নয় যদি তিনি কেবল আপনাকে বলেন, "দুঃখিত, আমি এটি ঠিক করতে পারি না It's এটি ভেঙে গেছে।" হেল, এটি আরও খারাপ যদি তিনি একবার নজর রাখেন, চলে যান এবং আপনাকে একটি চিঠি মেইল ​​করে বলেন যে সে ঠিক করতে পারে না। এখন আপনাকে নিজের মেইল ​​পরীক্ষা করতে হবে এমনকি আপনি জানতে চান যে তিনি যা চান তা করেননি didn't

আপনি যা পছন্দ করেন তা হ'ল তাকে আপনাকে বলতে হবে, "দেখুন, আমি এটি ঠিক করতে পারিনি কারণ আপনার পাম্পটি কাজ করছে না বলে মনে হচ্ছে" "

এই তথ্যের সাহায্যে আপনি সিদ্ধান্ত নিতে পারেন যে আপনি চান বৈদ্যুতিনবিদ সমস্যার দিকে নজর দিন the সম্ভবত বৈদ্যুতিনবিদ ছুতার সম্পর্কিত কিছু আবিষ্কার করবে এবং আপনাকে ছুতার এটি ঠিক করতে হবে।

হেক, আপনি এমনকি আপনি একটি তাড়িতী, আপনি হয়ত জানেন না হয়ত জানেন না যারা আপনার যা দরকার। আপনি কোনও বাড়ি মেরামত ব্যবসায় কেবলমাত্র মধ্যম-পরিচালনা এবং আপনার ফোকাস নদীর গভীরতানির্ণয়। সুতরাং আপনি সমস্যার বিষয়ে মনিবকে বলুন এবং তারপরে তিনি বৈদ্যুতিনবিদকে এটি ঠিক করতে বলেছেন।

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

সুতরাং ... একটি বিরোধী প্যাটার্ন?

ঠিক আছে, তাই বুঝতে বিন্দু ব্যতিক্রম প্রথম ধাপ। পরেরটিটি অ্যান্টি-প্যাটার্নটি কী তা বুঝতে হবে।

অ্যান্টি-প্যাটার্ন হিসাবে যোগ্য হতে, এটি করা দরকার

  • সমস্যা টার সমাধান কর
  • এর অবশ্যই নেতিবাচক পরিণতি রয়েছে

প্রথম পয়েন্টটি সহজেই পূরণ করা যায় - সিস্টেমটি কাজ করেছে, তাই না?

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

তবে তা নিশ্চিত ক্ষতি নয়। এটি জিনিসগুলি করার একটি দরিদ্র উপায়, এবং অদ্ভুত, তবে একটি বিরোধী নিদর্শন? না ... ঠিক অদ্ভুত।


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

"এটি জিনিসগুলি করার একটি দরিদ্র উপায়" - এটিকে কী এন্টি-প্যাটার্ন হিসাবে শ্রেণিবদ্ধ করার পক্ষে যথেষ্ট হওয়া উচিত নয়?
পারে_ফ্যাক্টর

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