রায়ান ডেভিসের রুবি কুইকআরফ বলেছেন (ব্যাখ্যা ছাড়াই):
ব্যতিক্রম উদ্ধার করবেন না। কখনোই না। অথবা আমি তোমাকে ছুরিকাঘাত করব।
কেন না? সঠিক কাজটি কী?
রায়ান ডেভিসের রুবি কুইকআরফ বলেছেন (ব্যাখ্যা ছাড়াই):
ব্যতিক্রম উদ্ধার করবেন না। কখনোই না। অথবা আমি তোমাকে ছুরিকাঘাত করব।
কেন না? সঠিক কাজটি কী?
উত্তর:
টিএল; ডিআর : StandardError
সাধারণ ব্যতিক্রম ধরার জন্য পরিবর্তে ব্যবহার করুন । যখন মূল ব্যতিক্রমটি পুনরায় উত্থাপিত হয় (উদাহরণস্বরূপ কেবল ব্যতিক্রম লগ করতে উদ্ধার করার সময়), উদ্ধার Exception
করা সম্ভবত ঠিক আছে।
Exception
মূল রুবি এর ব্যতিক্রম অনুক্রমের , তাই যখন আপনি rescue Exception
আপনার কাছ থেকে উদ্ধার সবকিছু যেমন উপশ্রেণী সহ SyntaxError
, LoadError
এবং Interrupt
।
উদ্ধারকারী প্রোগ্রামটি থেকে বেরিয়ে আসার জন্য Interrupt
ব্যবহারকারীকে বাধা দেয় CTRLC।
উদ্ধার করা SignalException
প্রোগ্রামকে সংকেতগুলিতে সঠিকভাবে প্রতিক্রিয়া জানাতে বাধা দেয়। এটি বাদ দিয়ে অদৃশ্য হবে kill -9
।
উদ্ধার করা SyntaxError
মানেeval
ব্যর্থতা নিঃশব্দে এটি করবে।
এগুলি সমস্ত এই প্রোগ্রামটি চালিয়ে এবং এর চেষ্টা করে CTRLCবা kill
এটির মাধ্যমে প্রদর্শিত হতে পারে :
loop do
begin
sleep 1
eval "djsakru3924r9eiuorwju3498 += 5u84fior8u8t4ruyf8ihiure"
rescue Exception
puts "I refuse to fail or be stopped!"
end
end
থেকে উদ্ধার করা Exception
এমনকি ডিফল্টও নয়। এরকম
begin
# iceberg!
rescue
# lifeboats
end
Exception
এটি থেকে উদ্ধার করে না , এ থেকে উদ্ধার করে StandardError
। আপনার সাধারণত ডিফল্টর চেয়ে নির্দিষ্ট কিছু নির্দিষ্ট করা উচিত StandardError
, তবে এটিকে সঙ্কুচিত করার পরিবর্তে সুযোগটি Exception
প্রশস্ত করা থেকে বিরত থাকতে হবে এবং বিপর্যয়মূলক ফলাফল আসতে পারে এবং বাগ-শিকারকে অত্যন্ত কঠিন করে তুলতে পারে।
আপনার যদি এমন পরিস্থিতি থেকে উদ্ধার পেতে চান StandardError
এবং ব্যতিক্রমের সাথে আপনার যদি কোনও ভেরিয়েবলের প্রয়োজন হয় তবে আপনি এই ফর্মটি ব্যবহার করতে পারেন:
begin
# iceberg!
rescue => e
# lifeboats
end
যা এর সমান:
begin
# iceberg!
rescue StandardError => e
# lifeboats
end
Exception
লগিং / রিপোর্টিংয়ের উদ্দেশ্যে যে কয়েকটি সাধারণ ক্ষেত্রে এটি থেকে উদ্ধার করা বুদ্ধিমানের একটি তা হ'ল এই ক্ষেত্রে আপনার অবিলম্বে ব্যতিক্রমটি পুনরায় উত্থাপন করা উচিত:
begin
# iceberg?
rescue Exception => e
# do some logging
raise # not enough lifeboats ;)
end
Throwable
জাভা ধরার মতো
ADAPTER_ERRORS = [::ActiveRecord::StatementInvalid, PGError, Mysql::Error, Mysql2::Error, ::ActiveRecord::JDBCError, SQLite3::Exception]
এবং তার পরেও করতে পারেনrescue *ADAPTER_ERRORS => e
বাস্তব নিয়ম হল: দূরে ব্যতিক্রম নিক্ষেপ করবেন না। আপনার উক্তিটির লেখকের উদ্দেশ্যমূলকতা প্রশ্নবিদ্ধ, যেমনটি প্রমাণ দিয়ে শেষ হয়েছে
অথবা আমি তোমাকে ছুরিকাঘাত করব
অবশ্যই সচেতন থাকুন যে সংকেতগুলি (ডিফল্টরূপে) ব্যতিক্রম ছুঁড়ে দেয় এবং সাধারণত দীর্ঘস্থায়ী প্রক্রিয়াগুলি একটি সিগন্যালের মাধ্যমে শেষ হয়, সুতরাং ব্যতিক্রম ধরা এবং সিগন্যাল ব্যতিক্রমগুলিতে সমাপ্ত না করা আপনার প্রোগ্রামটিকে থামিয়ে দেওয়া খুব কঠিন করে তুলবে। সুতরাং এটি করবেন না:
#! /usr/bin/ruby
while true do
begin
line = STDIN.gets
# heavy processing
rescue Exception => e
puts "caught exception #{e}! ohnoes!"
end
end
না, সত্যিই, এটা করবেন না। এটি কাজ করে কিনা তা দেখতে চালাও না।
তবে, বলুন আপনার কাছে একটি থ্রেডযুক্ত সার্ভার রয়েছে এবং আপনি সমস্ত ব্যতিক্রমগুলি না চান:
thread.abort_on_exception = true
)। তারপরে আপনার সংযোগ হ্যান্ডলিং থ্রেডে এটি পুরোপুরি গ্রহণযোগ্য:
begin
# do stuff
rescue Exception => e
myLogger.error("uncaught #{e} exception while handling connection: #{e.message}")
myLogger.error("Stack trace: #{backtrace.map {|l| " #{l}\n"}.join}")
end
উপরেরটি রুবির ডিফল্ট ব্যতিক্রম হ্যান্ডলারটির ভিন্নতার সাথে কাজ করে, এই সুবিধা দিয়ে যে এটি আপনার প্রোগ্রামটিকেও হত্যা করে না। তার অনুরোধ হ্যান্ডলারের মাধ্যমে রেলগুলি এটি করে।
সিগন্যাল ব্যতিক্রমগুলি মূল থ্রেডে উত্থাপিত হয়। পটভূমি থ্রেডগুলি সেগুলি পাবেন না, সুতরাং সেগুলি সেখানে ধরার চেষ্টা করার কোনও মানে নেই।
এটি একটি উত্পাদনের পরিবেশে বিশেষত কার্যকর, যেখানে আপনি যখনই কিছু ভুল হয় তখন আপনার প্রোগ্রামটি কেবল থামতে চান না । তারপরে আপনি আপনার লগগুলিতে স্ট্যাকের ডাম্পগুলি গ্রহণ করতে পারেন এবং নির্দিষ্ট ব্যতিক্রমের সাথে কল চেইনে আরও নিখুঁতভাবে মোকাবেলা করতে আপনার কোডে যুক্ত করতে পারেন।
আরও লক্ষ করুন যে আরও একটি রুবি আইডিয়োম রয়েছে যা এর একই প্রভাব:
a = do_something rescue "something else"
এই লাইনে, যদি do_something
কোনও ব্যতিক্রম উত্থাপন করা হয় , তবে এটি রুবির হাতে ধরা পড়ে, ফেলে দেওয়া হয় এবং a
নির্ধারিত হয় "something else"
।
সাধারণত, এটি করবেন না, বিশেষ ক্ষেত্রে যেখানে আপনি জানেন যে আপনাকে চিন্তার দরকার নেই except একটি উদাহরণ:
debugger rescue nil
দ্য debugger
ফাংশন আপনার কোডে একটি ব্রেকপয়েন্ট সেট করতে বরং একটি চমৎকার উপায়, কিন্তু যদি পাগল একটি ডিবাগার বাহিরে দৌড়োনো এবং, এটি একটি ব্যতিক্রম উত্থাপন। এখন তাত্ত্বিকভাবে আপনার প্রোগ্রামে থাকা ডিবাগ কোডটি ফেলে রাখা উচিত নয় (পিএফএফ! কেউ তা করে না!) তবে আপনি কোনও কারণে কিছুক্ষণ সেখানে রাখতে চাইবেন, তবে ক্রমাগত আপনার ডিবাগারটি চালাবেন না।
বিঃদ্রঃ:
আপনি যদি অন্য কারও প্রোগ্রাম চালিয়ে যান যা সিগন্যাল ব্যতিক্রমগুলি ধরে এবং সেগুলি উপেক্ষা করে, (উপরের কোডটি বলুন) তবে:
pgrep ruby
বা ps | grep ruby
আপনার আপত্তিজনক প্রোগ্রামটির পিআইডি সন্ধান করুন এবং তারপরে চালান kill -9 <PID>
। আপনি যদি অন্য কারও প্রোগ্রামের সাথে কাজ করছেন যা যাই হোক না কেন কারণেই এই উপেক্ষা-ব্যতিক্রম ব্লকগুলির সাথে ঝাঁকুনি দিচ্ছে, তবে এটিকে মূল লাইনের শীর্ষে রেখে দেওয়া হ'ল একটি সম্ভাব্য কপ-আউট:
%W/INT QUIT TERM/.each { |sig| trap sig,"SYSTEM_DEFAULT" }
এই অবিলম্বে সসীম, ব্যতিক্রম হ্যান্ডলার বাইপাস দ্বারা স্বাভাবিক পরিসমাপ্তি সংকেত সাড়া প্রোগ্রাম ঘটায় কোন পরিষ্করণ সঙ্গে । সুতরাং এটি ডেটা ক্ষতি বা অনুরূপ হতে পারে। সাবধান হও!
আপনার যদি এটি করার দরকার হয়:
begin
do_something
rescue Exception => e
critical_cleanup
raise
end
আপনি আসলে এটি করতে পারেন:
begin
do_something
ensure
critical_cleanup
end
দ্বিতীয় ক্ষেত্রে, critical cleanup
প্রতিবার ফোন করা হবে, কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হোক না।
kill -9
।
ensure
একটি ব্যতিক্রম উত্থাপিত হয়েছে কিনা তা নির্বিশেষে একটি চলবে, যখন ব্যতিক্রমটি উত্থাপিত rescue
হলে কেবল চলবে।
না rescue Exception => e
(ব্যতিক্রম এবং পুনরায় বাড়াতে) - অথবা আপনি পারে একটি সেতু বন্ধ চালনা করা।
ধরা যাক আপনি গাড়িতে আছেন (রুবি চালাচ্ছেন)। আপনি সম্প্রতি ওভার-দ্য এয়ার আপগ্রেড সিস্টেমের সাথে একটি নতুন স্টিয়ারিং হুইল ইনস্টল করেছেন (যা ব্যবহার করে eval
) তবে আপনি জানেন না যে কোনও একটি প্রোগ্রামার সিনট্যাক্সে গণ্ডগোল করেছেন।
আপনি একটি সেতুতে রয়েছেন, এবং বুঝতে পারবেন আপনি রেলিংয়ের দিকে কিছুটা এগিয়ে যাচ্ছেন, তাই আপনি বাম দিকে ঘুরছেন।
def turn_left
self.turn left:
end
ওহো! সম্ভবত এটি ভাল নয় luck ভাগ্যক্রমে, রুবি একটি উত্থাপন করে SyntaxError
।
গাড়ি সঙ্গে সঙ্গে থামানো উচিত - তাই না?
নাঃ।
begin
#...
eval self.steering_wheel
#...
rescue Exception => e
self.beep
self.log "Caught #{e}.", :warn
self.log "Logged Error - Continuing Process.", :info
end
বিপ বিপ
সতর্কতা: ধরা পড়া সিনট্যাক্স এরর ব্যতিক্রম।
তথ্য: লগড ত্রুটি - ক্রমাগত প্রক্রিয়া।
আপনি কিছু ভুল লক্ষ্য, এবং আপনি জরুরি অবস্থা বিরতি উপর স্ল্যাম ( ^C
: Interrupt
)
বিপ বিপ
সতর্কতা: বাধা ব্যতিক্রম ধরা পড়ে।
তথ্য: লগড ত্রুটি - ক্রমাগত প্রক্রিয়া।
হ্যাঁ - এটি খুব একটা সাহায্য করে নি। আপনি রেলের খুব কাছেই রয়েছেন, তাই আপনি গাড়িটি পার্কে রেখেছেন ( kill
আইএন SignalException
:)।
বিপ বিপ
সতর্কতা: সিগন্যাল এক্সসেপশন ব্যতিক্রম ধরা পড়ে।
তথ্য: লগড ত্রুটি - ক্রমাগত প্রক্রিয়া।
শেষ সেকেন্ডে, আপনি কীগুলি ( kill -9
) টানুন , এবং গাড়িটি থামবে, আপনি স্টিয়ারিং হুইলে এগিয়ে গেলেন (এয়ারব্যাগটি উত্সাহিত করতে পারে না কারণ আপনি দয়া করে প্রোগ্রামটি বন্ধ করেন নি - আপনি এটি সমাপ্ত করেছেন), এবং কম্পিউটার আপনার গাড়ির পিছনে এটি সামনে সিটে স্ল্যাম। কাগজগুলির উপর কোকের একটি অর্ধ পূর্ণ ক্যান ছড়িয়ে পড়ে। পিছনে মুদিগুলি চূর্ণ করা হয় এবং বেশিরভাগটি ডিমের কুসুম এবং দুধে .াকা থাকে। গাড়ী গুরুতর মেরামতের এবং পরিষ্কার প্রয়োজন। (ডেটা হ্রাস)
আশা করি আপনার কাছে বীমা (ব্যাকআপ) রয়েছে। ওহ হ্যাঁ - কারণ এয়ারব্যাগটি ফুলে উঠেনি, আপনি সম্ভবত আহত হয়েছেন (বহিস্কার, ইত্যাদি)।
কিন্তু অপেক্ষা করো! সেখানেঅধিককারণ আপনি কেন ব্যবহার করতে পারেন rescue Exception => e
!
ধরা যাক আপনি সেই গাড়ি, এবং গাড়ীটি নিরাপদ থামার গতি অতিক্রম করে থাকলে আপনি এয়ারব্যাগটি ফুলে যায় তা নিশ্চিত করতে চান।
begin
# do driving stuff
rescue Exception => e
self.airbags.inflate if self.exceeding_safe_stopping_momentum?
raise
end
নিয়মটির এখানে ব্যতিক্রম এখানে রয়েছে: আপনি Exception
ব্যতিক্রমটি পুনরায় উত্থাপন করলেই আপনি তা ধরতে পারবেন । সুতরাং, আরও ভাল নিয়ম হ'ল কখনই গ্রাস না করা Exception
এবং ত্রুটিটিকে সর্বদা পুনরায় উত্থাপন করা।
তবে রুবির মতো ভাষায় রেসকিউ যোগ করা দু'টোই সহজ এবং কোনও সমস্যা পুনরায় উত্থাপনের আগে উদ্ধার বিবৃতি দেওয়া কিছুটা অ-ডিআরওয়াই অনুভব করে। এবং আপনি বিবৃতিটি ভুলতে চান নাraise
। এবং যদি আপনি এটি করেন তবে ভাগ্য সেই ত্রুটিটি অনুসন্ধান করার চেষ্টা করছে।
ধন্যবাদ, রুবি দুর্দান্ত, আপনি ensure
কীওয়ার্ডটি ব্যবহার করতে পারেন , যা কোডটি চালিত করে তা নিশ্চিত করে। ensure
শব্দ কোন ব্যাপার কি কোড চালানো হবে - যদি একটি ব্যতিক্রম নিক্ষিপ্ত হয়, যদি এক না হয়, একমাত্র ব্যতিক্রম যদি হচ্ছে পৃথিবীর শেষ দিন (অথবা অন্যান্য অসম্ভাব্য ঘটনা)।
begin
# do driving stuff
ensure
self.airbags.inflate if self.exceeding_safe_stopping_momentum?
end
পরিস্ফুটন! এবং যে কোড যাইহোক চালানো উচিত। আপনার যদি কেবল rescue Exception => e
ব্যতিক্রমটি অ্যাক্সেসের প্রয়োজন হয় বা আপনি যদি কেবল ব্যতিক্রমটিতে কোড চালনা করতে চান তবে আপনার ব্যবহার করা উচিত reason এবং ত্রুটি পুনরায় উত্থাপন মনে রাখবেন। প্রত্যেকবার.
দ্রষ্টব্য: @ নিলাল হিসাবে উল্লেখ করা হয়েছে, সর্বদা চালানো নিশ্চিত করুন । এটি ভাল কারণ কখনও কখনও আপনার প্রোগ্রামটি আপনার কাছে মিথ্যা বলতে পারে এবং সমস্যাগুলি দেখা দিলেও ব্যতিক্রম ছুঁড়ে না ফেলে দিতে পারে। এয়ারব্যাগগুলিতে স্ফীতকরণের মতো সমালোচনামূলক কাজগুলির সাথে আপনার অবশ্যই তা নিশ্চিত হওয়া দরকার যে তা যাই হোক না কেন ঘটুক। এ কারণেই, প্রতিবার গাড়ি থামার সময় চেক করা, কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় বা না, এটি একটি ভাল ধারণা। যদিও বেশিরভাগ প্রোগ্রামিং প্রসঙ্গে এয়ারব্যাগগুলি স্ফীত করা কিছুটা অস্বাভাবিক কাজ হলেও বেশিরভাগ ক্লিনআপ কাজের ক্ষেত্রে এটি আসলে বেশ সাধারণ।
ensure
বিকল্প হিসাবে অংশটি rescue Exception
বিভ্রান্তিমূলক - উদাহরণটি বোঝায় যে তারা সমতুল্য, তবে যেমনটি বলা হয়েছে ensure
যে কোনও ব্যতিক্রম আছে বা নেই, তাই এখন আপনার এয়ারব্যাগগুলি ফুলে উঠবে কারণ আপনি 5 এমএফ ছাড়িয়ে গেছেন যদিও কিছু ভুল হয়নি।
কারণ এটি সমস্ত ব্যতিক্রম ক্যাপচার করে। এটা যে আপনার প্রোগ্রাম থেকে পুনরুদ্ধার করতে পারেন সম্ভাবনা কম কোনো তাদের।
আপনার কেবলমাত্র ব্যতিক্রমগুলি পরিচালনা করা উচিত যা আপনি কীভাবে পুনরুদ্ধার করবেন জানেন। আপনি যদি কোনও নির্দিষ্ট ব্যতিক্রমের পূর্বাভাস না দিয়ে থাকেন তবে এটি পরিচালনা করবেন না, জোরে ক্র্যাশ করুন (লগটিতে বিশদটি লিখুন), তারপরে লগগুলি নির্ধারণ করুন এবং কোডটি ঠিক করুন।
গিলে নেওয়া ব্যতিক্রম খারাপ, এটি করবেন না।
এটি নিয়মের একটি নির্দিষ্ট কেস যে আপনি কীভাবে পরিচালনা করতে জানেন না এমন কোনও ব্যতিক্রম ধরা উচিত নয় । আপনি যদি এটি পরিচালনা করতে না জানেন তবে সিস্টেমের অন্য কোনও অংশটিকে এটি ধরতে এবং পরিচালনা করতে দেওয়া ভাল better
আমি স্রেফ মধুবাজার.ইও সম্পর্কে এটি সম্পর্কে একটি দুর্দান্ত ব্লগ পোস্ট পড়েছি :
আপনি কেন ব্যতিক্রমটিকে উদ্ধার করবেন না
ব্যতিক্রম উদ্ধার করার ক্ষেত্রে সমস্যাটি হ'ল এটি ব্যতিক্রম থেকে উত্তরাধিকারসূত্রে প্রাপ্ত প্রতিটি ব্যতিক্রমকে উদ্ধার করে। কোনটি .... তাদের সব!
এটি একটি সমস্যা কারণ কিছু ব্যতিক্রম রয়েছে যা রুবি অভ্যন্তরীণভাবে ব্যবহার করে। আপনার অ্যাপ্লিকেশনের সাথে তাদের কিছু করার নেই এবং এগুলি গ্রাস করে খারাপ জিনিস ঘটবে।
এখানে কয়েকটি বড় লোক রয়েছে:
সিগন্যাল এক্সসেপশন :: বাধা - আপনি এটিকে উদ্ধার করে ফেললে আপনি নিয়ন্ত্রণ-সি-তে আঘাত করে আপনার অ্যাপ্লিকেশন থেকে প্রস্থান করতে পারবেন না।
স্ক্রিপ্টএরর :: সিনট্যাক্স এরির - সিনট্যাক্স ত্রুটি গিলানো মানে পটসের মতো জিনিস ("কিছু ভুলে গেছেন) নিঃশব্দে ব্যর্থ হবে।
NoMemoryError - আপনার প্রোগ্রামটি সমস্ত র্যাম ব্যবহার করার পরে যখন চলতে থাকে তখন কী করতে চান জানতে চান? আমিও না.
begin do_something() rescue Exception => e # Don't do this. This will swallow every single exception. Nothing gets past it. end
আমি অনুমান করছি যে আপনি সিস্টেম-স্তরের ব্যতিক্রমগুলি সত্যিই গ্রাস করতে চান না। আপনি কেবল আপনার অ্যাপ্লিকেশন স্তরের সমস্ত ত্রুটি ধরতে চান। ব্যতিক্রমগুলি আপনার কোড তৈরি করেছে।
ভাগ্যক্রমে, এটির একটি সহজ উপায় আছে।