ধারাবাহিকতা স্বার্থে, এটিকে রিফ্যাক্টরের প্রয়োজন ছাড়াই ত্রুটি পরিচালনার সাথে আমাদের কোডটি গুটিয়ে রাখতে সক্ষম হওয়া কী বোঝায়?
এর উত্তর দেওয়ার জন্য, কেবলমাত্র একটি ভেরিয়েবলের সুযোগের চেয়ে বেশি দেখার প্রয়োজন ।
এমনকি যদি ভেরিয়েবল সুযোগে থেকে যায়, তবে এটি অবশ্যই নির্ধারিত হবে না ।
ট্রায়াল ব্লকের পরিবর্তনশীল ঘোষণা করে - সংকলক এবং মানব পাঠকদের কাছে - যে এটি কেবলমাত্র সেই ব্লকের ভিতরে অর্থবহ। এটি প্রয়োগ করার জন্য এটি সংকলকটির পক্ষে কার্যকর।
ট্রাই ব্লকের পরে আপনি যদি ভেরিয়েবলটি স্কোপে থাকতে চান তবে আপনি এটিকে ব্লকের বাইরে ঘোষণা করতে পারেন:
var zerothVariable = 1_000_000_000_000L;
int firstVariable;
try {
// Change checked to unchecked to allow the overflow without throwing.
firstVariable = checked((int)zerothVariable);
}
catch (OverflowException e) {
Console.Error.WriteLine(e.Message);
Environment.Exit(1);
}
এটি প্রকাশ করে যে ভেরিয়েবল চেষ্টা ব্লকের বাইরে অর্থবহ হতে পারে। সংকলক এটি অনুমতি দেবে।
তবে এটি অন্য কারণটিও দেখায় যে সচেষ্ট ব্লকে পরিচয় করিয়ে দেওয়ার পরে ভেরিয়েবলগুলি স্কোপে রাখার জন্য সাধারণত কার্যকর হবে না। সি # সংকলক নির্দিষ্ট অ্যাসাইনমেন্ট বিশ্লেষণ করে এবং কোনও ভেরিয়েবলের মান পড়া নিষিদ্ধ করে যা এটি প্রমাণিত হয় নি যে একটি মান দেওয়া হয়েছে। সুতরাং আপনি এখনও ভেরিয়েবল থেকে পড়তে পারবেন না।
ধরুন ট্রাই ব্লকের পরে আমি ভেরিয়েবল থেকে পড়ার চেষ্টা করেছি:
Console.WriteLine(firstVariable);
এটি একটি সংকলন-সময় ত্রুটি দেবে :
CS0165 অচিহ্নযুক্ত স্থানীয় ভেরিয়েবল 'ফার্স্ট ভেরিয়েবল' এর ব্যবহার
আমি ক্যাচ ব্লকে এনভায়রনমেন্ট.এক্সিটকে ডেকেছি , তাই আমি জানি কনসোল.ব্রাইটলাইনকে কল করার আগে ভেরিয়েবলটি বরাদ্দ করা হয়েছে। সংকলক এটি অনুমান করে না।
সংকলকটি এত কঠোর কেন?
আমি এটিও করতে পারি না:
int n;
try {
n = 10; // I know this won't throw an IOException.
}
catch (IOException) {
}
Console.WriteLine(n);
এই বিধিনিষেধটি দেখার একটি উপায় হ'ল সি # তে নির্দিষ্ট অ্যাসাইনমেন্ট বিশ্লেষণটি খুব পরিশীলিত নয়। তবে এটি দেখার অন্য একটি উপায় হ'ল আপনি যখন ক্যাচ ক্লজ সহ একটি ট্রাই ব্লকে কোড লিখবেন, আপনি সংকলক এবং যে কোনও মানব পাঠক উভয়কেই বলছেন যে এটির মতো আচরণ করা উচিত এটি সম্ভবত চালানো সম্ভব নয়।
আমার অর্থটি বোঝানোর জন্য, ধারণা করুন যে সংকলকটি উপরের কোডটিকে অনুমতি দিয়েছে, তবে তারপরে আপনি চেষ্টা ব্লকে একটি ফাংশনটিতে যুক্ত করেছেন যা আপনি ব্যক্তিগতভাবে জানেন যে কোনও ব্যতিক্রম ছুঁড়ে না । গ্যারান্টি দিতে সক্ষম না হয়ে যে ডাকা ফাংশনটি একটি IOException
ছুঁড়েছে না, সংকলক জানতে পারে না যে n
এটি নির্ধারিত হয়েছিল এবং তারপরে ছুঁড়েছে না, সংকলকটি আপনাকে রিফ্যাক্টর করতে হবে।
এটি বলার অপেক্ষা রাখে না যে, ক্যাচ ক্লজ সহ ট্রাই ব্লকে নির্ধারিত কোনও চলক অবশ্যই পরে নির্ধারিত হয়েছে কিনা তা নির্ধারণের ক্ষেত্রে অত্যন্ত পরিশীলিত বিশ্লেষণের মাধ্যমে, সংকলকটি আপনাকে কোডটি লিখন এড়াতে সহায়তা করে যা সম্ভবত পরে বিচ্ছেদ হওয়ার সম্ভাবনা রয়েছে। (সর্বোপরি, একটি ব্যতিক্রম ধরা এর অর্থ সাধারণত আপনি ভাবেন যে কোনওটি নিক্ষিপ্ত হতে পারে))
আপনি ভেরিয়েবলটি সমস্ত কোড পাথের মাধ্যমে নির্ধারিত হয়েছে তা নিশ্চিত করতে পারেন।
আপনি চেষ্টা ব্লকের আগে ভেরিয়েবলকে একটি মান দিয়ে বা ক্যাচ ব্লকে কোড সংকলন করতে পারেন। এইভাবে, এটি এখনও শুরু বা বরাদ্দ করা হবে, এমনকি যদি চেষ্টা ব্লকের অ্যাসাইনমেন্টটি না ঘটে। উদাহরণ স্বরূপ:
var n = 0; // But is this meaningful, or just covering a bug?
try {
n = 10;
}
catch (IOException) {
}
Console.WriteLine(n);
বা:
int n;
try {
n = 10;
}
catch (IOException) {
n = 0; // But is this meaningful, or just covering a bug?
}
Console.WriteLine(n);
যারা সংকলন। তবে কেবলমাত্র এমন কিছু করা ভাল যদি আপনি প্রদত্ত ডিফল্ট মানটি বোঝায় * এবং সঠিক আচরণ করে and
মনে রাখবেন, এই দ্বিতীয় ক্ষেত্রে যেখানে আপনি চেষ্টা ব্লক এবং সমস্ত ক্যাপ ব্লকে ভেরিয়েবল নির্ধারণ করেন, যদিও আপনি চেষ্টা করার পরে ভেরিয়েবলটি পড়তে পারেন, আপনি এখনও একটি সংযুক্ত finally
ব্লকের ভিতরে ভেরিয়েবলটি পড়তে পারবেন না , কারণ আমরা প্রায়শই যা ভাবি তার থেকে বেশি পরিস্থিতিতে মৃত্যুদণ্ড কার্যকর করা একটি প্রচেষ্টা অবিরত রাখতে পারে ।
* উপায় দ্বারা, কিছু কিছু ভাষায়, C ও C মত ++ উভয় uninitialized ভেরিয়েবল অনুমতি এবং না তাদের কাছ থেকে পড়া রোধ করার জন্য নির্দিষ্ট কাজ বিশ্লেষণ আছে। যেহেতু অবিস্মরণীয় মেমরিটি পড়ার ফলে প্রোগ্রামগুলি ননডেস্টেরিস্টিক এবং ত্রুটিযুক্ত ফ্যাশনে আচরণ করে , তাই সাধারণত কোনও আরম্ভকারী সরবরাহ না করে সেই ভাষাগুলিতে ভেরিয়েবলগুলি এড়ানোর পরামর্শ দেওয়া হয়। সি # এবং জাভার মতো নির্দিষ্ট অ্যাসাইনমেন্ট বিশ্লেষণের ভাষায়, সংকলক আপনাকে অবিবেচনাযুক্ত পরিবর্তনগুলি পড়তে বা অর্থহীন মানগুলির সাথে আরম্ভ করার কম মন্দ থেকে রক্ষা করে যা পরবর্তীকালে অর্থবোধক হিসাবে ভুল ব্যাখ্যা করা যেতে পারে।
আপনি এটিকে এমন কোড পাথ করতে পারেন যেখানে ভেরিয়েবল নির্ধারিত নয় একটি ব্যতিক্রম (বা ফিরে) নিক্ষেপ করুন।
যদি আপনি কিছু ক্রিয়া সম্পাদন করার পরিকল্পনা করেন (যেমন লগিং) এবং ব্যতিক্রমটি পুনর্বিবেচনা বা অন্য ব্যতিক্রম নিক্ষেপ করেন এবং ভেরিয়েবলটি নির্ধারিত না হয় এমন কোনও ক্যাচ ক্লাউজে এটি ঘটে থাকে, তবে সংকলকটি জানতে পারবে যে ভেরিয়েবলটি নির্ধারিত হয়েছে:
int n;
try {
n = 10;
}
catch (IOException e) {
Console.Error.WriteLine(e.Message);
throw;
}
Console.WriteLine(n);
এটি সংকলন করে, এবং এটি একটি যুক্তিসঙ্গত পছন্দও হতে পারে। যাইহোক, প্রকৃত অ্যাপ্লিকেশনে, যদি না ব্যতিক্রম শুধুমাত্র ফেলে দেওয়া হয় পরিস্থিতিতে যেখানে এটি এমনকি অর্থে দেখা যায় না পুনরুদ্ধার করার চেষ্টা করতে * , আপনি কি নিশ্চিত যে আপনি এখনও সংক্রামক হয় তা নিশ্চিত করা উচিত এবং সঠিকভাবে এটা হ্যান্ডলিং কোথাও ।
(আপনি এই পরিস্থিতিতে শেষ অবধি ব্লকটি ভেরিয়েবলটি পড়তে পারবেন না, তবে এটির মতো আপনার মনে হওয়া উচিত নয় - সর্বোপরি, অবশেষে ব্লকগুলি সর্বদা চলমান থাকে, এবং এই ক্ষেত্রে চলকটি সর্বদা নির্ধারিত হয় না ।)
* উদাহরণস্বরূপ, অনেক অ্যাপ্লিকেশনগুলির একটি ক্যাচ ক্লজ নেই যা একটি আউটআফ মেমরি এক্স্পেসেশন পরিচালনা করে কারণ তারা এ সম্পর্কে যা কিছু করতে পারে তা কমপক্ষে ক্রাশ হওয়ার মতো খারাপও হতে পারে ।
আপনি সত্যিই করতে পারেন কোডটি রিফ্যাক্টর চান।
আপনার উদাহরণে, আপনি পরিচয় করিয়ে দিন firstVariable
এবংsecondVariable
চেষ্টা করুন ব্লকগুলি। যেমনটি আমি বলেছি, চেষ্টা করা ব্লকগুলিতে তাদের নির্ধারিত হওয়ার আগে আপনি সেগুলি সংজ্ঞায়িত করতে পারেন যাতে তারা পরবর্তী সময়ে সুযোগে থাকবে এবং আপনি সর্বদা নির্ধারিত হয়ে গেছে তা নিশ্চিত করে আপনি তাদের কাছ থেকে পড়তে পারবেন এমন সংকলকটিকে সন্তুষ্ট / চালিত করতে পারেন।
কিন্তু এই ব্লকগুলির পরে প্রদর্শিত কোডটি সম্ভবত তাদের সঠিকভাবে অর্পণ করা হয়েছে তার উপর নির্ভর করে। যদি এটি হয় তবে আপনার কোডটি প্রতিবিম্বিত হওয়া উচিত এবং তা নিশ্চিত করা উচিত।
প্রথমত, (এবং হওয়া উচিত) আপনি কি সেখানে ত্রুটিটি পরিচালনা করতে পারেন? ব্যতিক্রম হ্যান্ডলিংয়ের অন্যতম কারণ হ'ল ত্রুটিগুলি যেখানে তারা কার্যকরভাবে পরিচালনা করতে পারে তা পরিচালনা করা সহজ করে , এমনকি যেখানে এটি ঘটে তার কাছাকাছি না হলেও।
আপনি যদি সেই ফাংশনটির আরম্ভ এবং সেই ভেরিয়েবলগুলি ব্যবহার করে আসলে ত্রুটিটি পরিচালনা করতে না পারেন, তবে চেষ্টা ব্লকটি সেই ফাংশনে মোটেই না হওয়া উচিত, তবে পরিবর্তে কোথাও উচ্চতর হওয়া উচিত (যেমন, কোডটিকে যে ফাংশনটি, বা কোড বলে যে কল যে কোড)। কেবলমাত্র নিশ্চিত হয়ে নিন যে আপনি দুর্ঘটনাক্রমে অন্য কোথাও ছুঁড়ে দেওয়া ব্যতিক্রম ধরছেন না এবং ভুল করে ধরেছেন যে এটি আরম্ভ করার সময় firstVariable
এবং এটি ছড়িয়ে দেওয়া হয়েছিল secondVariable
।
আর একটি পদ্ধতি হ'ল কোডটি চেষ্টা করে যা চেষ্টা ব্লকে ভেরিয়েবল ব্যবহার করে। এটি প্রায়শই যুক্তিসঙ্গত হয়। আবার, আপনি যদি তাদের আরম্ভকারীদের কাছ থেকে একই ব্যাতিক্রমটি ধরেন তবে আশেপাশের কোড থেকেও ছুঁড়ে ফেলা যেতে পারে, আপনি নিশ্চিত হওয়া উচিত যে আপনি যখন তাদের পরিচালনা করার ক্ষেত্রে সেই সম্ভাবনাটিকে অবহেলা করছেন না।
(আমি ধরে নিচ্ছি যে আপনি আপনার উদাহরণগুলির তুলনায় আরও জটিল হিসাবে অভিব্যক্তিগুলির সাথে ভেরিয়েবলগুলি সূচনা করছেন, যেমন তারা আসলে একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারে এবং এছাড়াও যে আপনি সম্ভবত সমস্ত সম্ভাব্য ব্যতিক্রম ধরার পরিকল্পনা করছেন না , তবে নির্দিষ্ট ব্যতিক্রমগুলি কেবল ধরার জন্য) আপনি অনুমান করতে পারেন এবং অর্থপূর্ণভাবে পরিচালনা করতে পারেন It's এটি সত্য যে সত্যিকারের পৃথিবী সবসময় এত সুন্দর হয় না এবং উত্পাদন কোডটি কখনও কখনও এটি করে তবে আপনার লক্ষ্য এখানে দুটি নির্দিষ্ট ভেরিয়েবল শুরু করার সময় ঘটে যাওয়া ত্রুটিগুলি পরিচালনা করা, সুতরাং সেই নির্দিষ্টটির জন্য আপনি যে কোনও ক্যাচ ক্লজ লিখেন handle উদ্দেশ্য ত্রুটিগুলি যে কোনও ক্ষেত্রে সুনির্দিষ্ট হওয়া উচিত))
তৃতীয় উপায়টি হ'ল ব্যর্থ হতে পারে এমন কোডটি বের করা এবং চেষ্টা করে যা এটি পরিচালনা করে এটি তার নিজস্ব পদ্ধতিতে। এটি কার্যকর যদি আপনি প্রথমে ত্রুটিগুলি সম্পূর্ণরূপে মোকাবেলা করতে চান এবং তারপরে অজান্তে কোনও ব্যতিক্রম ধরা পড়ার বিষয়ে চিন্তা করবেন না যা এর পরিবর্তে অন্য কোথাও পরিচালনা করা উচিত।
ধরুন, উদাহরণস্বরূপ, আপনি ভেরিয়েবল বরাদ্দ করতে ব্যর্থ হওয়ার পরে অবিলম্বে অ্যাপ্লিকেশনটি ছাড়তে চান। (স্পষ্টতই সমস্ত ব্যতিক্রম হ্যান্ডলিং মারাত্মক ত্রুটির জন্য নয়; এটি কেবল একটি উদাহরণ এবং আপনি কীভাবে আপনার অ্যাপ্লিকেশন সমস্যার প্রতিক্রিয়া দেখাতে চান তা নাও হতে পারে।) আপনি এরকম কিছু করতে পারেন:
// In real life, this should be named more descriptively.
private static (int firstValue, int secondValue) GetFirstAndSecondValues()
{
try {
// This code is contrived. The idea here is that obtaining the values
// could actually fail, and throw a SomeSpecificException.
var firstVariable = 1;
var secondVariable = firstVariable;
return (firstVariable, secondVariable);
}
catch (SomeSpecificException e) {
Console.Error.WriteLine(e.Message);
Environment.Exit(1);
throw new InvalidOperationException(); // unreachable
}
}
// ...and of course so should this.
internal static void MethodThatUsesTheValues()
{
var (firstVariable, secondVariable) = GetFirstAndSecondValues();
// Code that does something with them...
}
সেই কোডটি একাধিক মান ফেরত দেওয়ার জন্য সি # 7.0 এর বাক্য গঠন সহ একটি ভ্যালুটুপলকে ডিকনস্ট্রাক্ট করে , তবে আপনি যদি এখনও সি # এর পূর্ববর্তী সংস্করণে থাকেন তবে আপনি এখনও এই কৌশলটি ব্যবহার করতে পারেন; উদাহরণস্বরূপ, আপনি প্যারামিটারগুলি ব্যবহার করতে পারেন, বা একটি কাস্টম অবজেক্ট ফিরিয়ে আনতে পারেন যা উভয় মান সরবরাহ করে । তদ্ব্যতীত, যদি দুটি ভেরিয়েবলগুলি আসলে কড়াভাবে সম্পর্কিত না হয় তবে সম্ভবত দুটি পৃথক পদ্ধতি থাকা ভাল ।
বিশেষত আপনার যদি এর মতো একাধিক পদ্ধতি থাকে তবে মারাত্মক ত্রুটি সম্পর্কে ব্যবহারকারীকে অবহিত করার জন্য এবং প্রস্থান করার জন্য আপনার কোডকে কেন্দ্রীভূত করা বিবেচনা করা উচিত। (উদাহরণস্বরূপ, আপনি একটি লিখতে পারে Die
একটি সঙ্গে পদ্ধতি message
প্যারামিটার।) লাইন আসলে মৃত্যুদন্ড কার্যকর করা হয় না তাই আপনি না প্রয়োজন (এবং উচিত নয়) এটির জন্য একটি ধরা দফা লিখুন।throw new InvalidOperationException();
কোনও নির্দিষ্ট ত্রুটি দেখা দিলে ছেড়ে যাওয়া বাদ দিয়ে আপনি কখনও কখনও এমন কোড লিখতে পারেন যা আপনি যদি অন্য কোনও ব্যতিক্রমকে বাদ দেন যা মূল ব্যতিক্রমটিকে আবৃত করে । (এই পরিস্থিতিতে আপনার দ্বিতীয়, অ্যাক্সেসযোগ্য থ্রো এক্সপ্রেশনটির প্রয়োজন হবে না ))
উপসংহার: ব্যাপ্তি চিত্রের কেবল একটি অংশ।
আপনি কেবল ভেরিয়েবলের ঘোষণাগুলি তাদের কার্যভার থেকে পৃথক করে রিফ্যাক্টরিং ছাড়াই ত্রুটি পরিচালনার সাথে আপনার কোড মোড়ানোর প্রভাব অর্জন করতে পারেন (বা, যদি আপনি পছন্দ করেন তবে খুব সহজেই কোনও সংশোধনকারী)। আপনি যদি সি # এর সুনির্দিষ্ট কার্যনির্বাহী বিধিগুলি পূরণ করেন এবং চেষ্টা ব্লকের আগে একটি ভেরিয়েবল ঘোষণা করে এর সংস্থাগুলি এটির অনুমতি দেয়। তবে আরও রিফ্যাক্টরিং আপনার সেরা বিকল্প হতে পারে।
try.. catch
একটি নির্দিষ্ট ধরণের কোড ব্লক এবং যতগুলি কোড ব্লক যায়, আপনি একটিতে একটি ভেরিয়েবল ঘোষণা করতে পারবেন না এবং সেই একই ভেরিয়েবলটিকে স্কোপ হিসাবে বিবেচনা করতে পারবেন না।