আমি অবাক হয়েছি কেউ এই বিকল্পটির পরামর্শ দেয়নি, তাই যদিও প্রশ্নটি প্রায় সময় হয়ে গেছে আমি এটিকে যুক্ত করব: এই ইস্যুটির সুরাহা করার একটি ভাল উপায় হ'ল চলমান অবস্থার উপর নজর রাখতে ভেরিয়েবল ব্যবহার করা। এটি এমন একটি প্রযুক্তি যা gotoক্লিনআপ কোডে পৌঁছানোর জন্য ব্যবহৃত হয় কিনা তা ব্যবহার করা যায়। যে কোনও কোডিং কৌশল হিসাবে, এটির পক্ষে মতামত এবং বোধগম্যতা রয়েছে এবং প্রতিটি পরিস্থিতির জন্য উপযুক্ত হবে না তবে আপনি যদি এমন কোনও শৈলী চয়ন করেন তবে এটি বিবেচনা করার মতো especially বিশেষত যদি আপনি gotoগভীরভাবে নেস্টেড ifএস না দিয়ে এড়াতে চান ।
মূল ধারণাটি হ'ল, যে কোনও ক্লিনআপ ক্রিয়াকলাপ গ্রহণের প্রয়োজন হতে পারে তার জন্য একটি ভেরিয়েবল রয়েছে যার মূল্য থেকে আমরা বলতে পারি যে ক্লিনআপটি করা দরকার কি না।
আমি gotoপ্রথমে সংস্করণটি দেখাব , কারণ এটি মূল প্রশ্নের কোডের নিকটে।
int foo(int bar)
{
int return_value = 0;
int something_done = 0;
int stuff_inited = 0;
int stuff_prepared = 0;
if (do_something(bar)) {
something_done = 1;
} else {
goto cleanup;
}
if (init_stuff(bar)) {
stuff_inited = 1;
} else {
goto cleanup;
}
if (prepare_stuff(bar)) {
stufF_prepared = 1;
} else {
goto cleanup;
}
return_value = do_the_thing(bar);
cleanup:
if (stuff_prepared) {
unprepare_stuff();
}
if (stuff_inited) {
uninit_stuff();
}
if (something_done) {
undo_something();
}
return return_value;
}
অন্যান্য কয়েকটি কৌশলগুলির মধ্যে এটির একটি সুবিধা হ'ল, যদি আরম্ভের ফাংশনগুলির ক্রম পরিবর্তন করা হয় তবে সঠিক পরিচ্ছন্নতাটি ঘটবে - উদাহরণস্বরূপ, switchঅন্য উত্তরে বর্ণিত পদ্ধতিটি ব্যবহার করে , যদি আরম্ভের ক্রম পরিবর্তন হয়, তবেswitch কিছু পরিষ্কার করার চেষ্টা এড়াতে খুব সাবধানে সম্পাদনা করতে হবে আসলে প্রথমদিকে আরম্ভ করা হয়নি।
এখন, কিছু যুক্তিযুক্ত হতে পারে যে এই পদ্ধতিটি অতিরিক্ত পরিমাণে ভেরিয়েবল যুক্ত করে - এবং প্রকৃতপক্ষে এই ক্ষেত্রে এটি সত্য - তবে বাস্তবে সাধারণত একটি বিদ্যমান ভেরিয়েবল ইতিমধ্যে ট্র্যাক করে, বা প্রয়োজনীয় অবস্থার উপর নজর রাখতে পারে। উদাহরণস্বরূপ, যদি prepare_stuff()প্রকৃতপক্ষে কলটি হয় malloc()বা তার কাছে হয় open()তবে ফেরত পয়েন্টার বা ফাইল বিবরণী ধারণকারী চলকটি ব্যবহার করা যেতে পারে - উদাহরণস্বরূপ:
int fd = -1;
....
fd = open(...);
if (fd == -1) {
goto cleanup;
}
...
cleanup:
if (fd != -1) {
close(fd);
}
এখন, আমরা অতিরিক্তভাবে একটি ভেরিয়েবলের মাধ্যমে ত্রুটির স্থিতি ট্র্যাক করি, আমরা এড়াতে পারি goto সম্পূর্ণরূপে , এবং এখনও সঠিকভাবে পরিষ্কার করতে পারি না, এমন ইনডেন্টেশন না থাকলে যা আমাদের আরও আরম্ভ করার প্রয়োজন হয়:
int foo(int bar)
{
int return_value = 0;
int something_done = 0;
int stuff_inited = 0;
int stuff_prepared = 0;
int oksofar = 1;
if (oksofar) {
if (do_something(bar)) {
something_done = 1;
} else {
oksofar = 0;
}
}
if (oksofar) {
if (init_stuff(bar)) {
stuff_inited = 1;
} else {
oksofar = 0;
}
}
if (oksofar) {
if (prepare_stuff(bar)) {
stuff_prepared = 1;
} else {
oksofar = 0;
}
}
if (oksofar) {
return_value = do_the_thing(bar);
}
if (stuff_prepared) {
unprepare_stuff();
}
if (stuff_inited) {
uninit_stuff();
}
if (something_done) {
undo_something();
}
return return_value;
}
আবার এর সম্ভাব্য সমালোচনা রয়েছে:
- সমস্ত "যদি" এর অভিনয় ক্ষতিগ্রস্ত করবেন না? না - কারণ সাফল্যের ক্ষেত্রে, আপনাকে যে কোনও উপায়ে সমস্ত চেক করতে হবে (অন্যথায় আপনি সমস্ত ত্রুটির ক্ষেত্রে পরীক্ষা করছেন না); এবং ব্যর্থতার ক্ষেত্রে বেশিরভাগ সংকলক ব্যর্থতার ক্রমটি অনুকূল করে তোলে
if (oksofar) ক্লিনআপ কোডে (জিসিসি অবশ্যই করে) কোনও একক লাফের জন্য চেকগুলির তোলে - এবং কোনও ক্ষেত্রে ত্রুটি কেস কার্য সম্পাদনের জন্য সাধারণত কম সমালোচিত হয়।
এটি কি আরও একটি পরিবর্তনশীল যুক্ত করছে না? এই ক্ষেত্রে হ্যাঁ, তবে প্রায়শই return_valueভেরিয়েবলটি oksofarএখানে যে ভূমিকা পালন করে তা ব্যবহার করতে পারেন । যদি আপনি ধারাবাহিক উপায়ে ত্রুটিগুলি ফিরিয়ে আনতে আপনার ফাংশনগুলি গঠন করেন তবে আপনি ifপ্রতিটি ক্ষেত্রে দ্বিতীয়টি এড়াতে পারেন :
int return_value = 0;
if (!return_value) {
return_value = do_something(bar);
}
if (!return_value) {
return_value = init_stuff(bar);
}
if (!return_value) {
return_value = prepare_stuff(bar);
}
এর মতো কোডিংয়ের একটি সুবিধা হ'ল ধারাবাহিকতাটির অর্থ হ'ল যে কোনও জায়গাতেই মূল প্রোগ্রামার রিটার্নের মানটি ঘাড়ে থাম্বের মতো চেক করতে ভুলে গিয়েছে, যাতে বাগগুলি খুঁজে পাওয়া খুব সহজ হয়ে যায় (যে এক শ্রেণির) বাগগুলি।
সুতরাং - এটি (এখনও) আরও একটি স্টাইল যা এই সমস্যাটি সমাধান করতে ব্যবহার করা যেতে পারে। সঠিকভাবে ব্যবহৃত হয়েছে এটি খুব পরিষ্কার, সামঞ্জস্যপূর্ণ কোডের অনুমতি দেয় - এবং কোনও কৌশল হিসাবে, ভুল হাতে এটি দীর্ঘায়িত এবং বিভ্রান্তিকর কোড উত্পাদন করতে শেষ করতে পারে :-)