এটি একটি সাধারণ পরিস্থিতি এবং এটি মোকাবেলার অনেকগুলি সাধারণ উপায় রয়েছে। একটি প্রচলিত উত্তর এখানে আমার প্রচেষ্টা। আমি যদি কিছু মিস করি তবে মন্তব্য করুন এবং আমি এই পোস্টটি আপ টু ডেট রাখব।
এটি একটি তীর
আপনি যা আলোচনা করছেন তা তীর বিরোধী-প্যাটার্ন হিসাবে পরিচিত । এটিকে তীর বলা হয় কারণ নেস্টেড আইএফএসের চেইন কোড ব্লকগুলি গঠন করে যা আরও দূরে এবং ডানদিকে প্রসারিত হয় এবং তারপরে বাম দিকে ফিরে যায় এবং একটি ভিজ্যুয়াল তীর গঠন করে যা কোড সম্পাদক পেনের ডানদিকে "পয়েন্ট" করে।
গার্ড দিয়ে তীর সমতল করুন
তীর এড়ানোর কয়েকটি সাধারণ উপায় এখানে আলোচনা করা হয়েছে । সর্বাধিক সাধারণ পদ্ধতি হ'ল গার্ড প্যাটার্ন ব্যবহার করা , যাতে কোডটি প্রথমে ব্যতিক্রম প্রবাহকে পরিচালনা করে এবং তারপরে মূল প্রবাহকে পরিচালনা করে, যেমন পরিবর্তে
if (ok)
{
DoSomething();
}
else
{
_log.Error("oops");
return;
}
... তুমি ব্যবহার কর ...
if (!ok)
{
_log.Error("oops");
return;
}
DoSomething(); //notice how this is already farther to the left than the example above
যখন প্রহরীগুলির একটি দীর্ঘ সিরিজ থাকে তখন কোডটি যথেষ্টভাবে ফ্ল্যাট করে কারণ সমস্ত প্রহরী সমস্তদিকে বামদিকে উপস্থিত হয় এবং আপনার আইফএস বাসা বাঁধে না। তদতিরিক্ত, আপনি যুক্তিসঙ্গত অবস্থাকে এর সম্পর্কিত ত্রুটির সাথে দৃষ্টিভঙ্গি করে যাচ্ছেন যা যা ঘটছে তা বলার পক্ষে এটি আরও সহজ করে তোলে:
তীর:
ok = DoSomething1();
if (ok)
{
ok = DoSomething2();
if (ok)
{
ok = DoSomething3();
if (!ok)
{
_log.Error("oops"); //Tip of the Arrow
return;
}
}
else
{
_log.Error("oops");
return;
}
}
else
{
_log.Error("oops");
return;
}
গার্ড:
ok = DoSomething1();
if (!ok)
{
_log.Error("oops");
return;
}
ok = DoSomething2();
if (!ok)
{
_log.Error("oops");
return;
}
ok = DoSomething3();
if (!ok)
{
_log.Error("oops");
return;
}
ok = DoSomething4();
if (!ok)
{
_log.Error("oops");
return;
}
এটি পড়ার জন্য অবজেক্টিভ এবং কোয়ান্টেফাইয়েলি সহজ কারণ কারণ
- প্রদত্ত লজিক ব্লকের জন্য {এবং} অক্ষর একত্রে আরও কাছাকাছি রয়েছে
- একটি নির্দিষ্ট লাইন বুঝতে মানসিক প্রসঙ্গে প্রয়োজনীয় পরিমাণ কম is
- শর্তের সাথে যুক্ত যুক্তির সম্পূর্ণতা এক পৃষ্ঠায় থাকার সম্ভাবনা বেশি
- পৃষ্ঠা / চোখের ট্র্যাকটি স্ক্রোল করার কোডারটির প্রয়োজনীয়তা হ্রাস করা হয়
কীভাবে শেষে সাধারণ কোড যুক্ত করা যায়
প্রহরী রীতির সমস্যাটি হ'ল এটি "সুবিধাবাদী প্রত্যাবর্তন" বা "সুবিধাবাদী প্রস্থান" বলে যাকে বলে তার উপর নির্ভর করে। অন্য কথায়, এটি প্রতিটি এবং প্রতিটি ক্রিয়াকলাপের প্রস্থানের ঠিক এক পয়েন্ট থাকা উচিত এমন প্যাটার্নটি ভেঙে দেয়। এটি দুটি কারণে সমস্যা:
- এটি কিছু লোককে ভুল উপায়ে ঘষে, উদাহরণস্বরূপ যে ব্যক্তিরা পাস্কেলে কোড শিখেছে তারা শিখেছে যে একটি ফাংশন = একটি প্রস্থানস্থান।
- এটি কোডের এমন একটি বিভাগ সরবরাহ করে না যা প্রস্থান করার পরে কার্যকর হয় তা যাই হোক না কেন , হাতে থাকা বিষয়।
নীচে আমি ভাষা বৈশিষ্ট্য ব্যবহার করে বা সমস্যাটি পুরোপুরি এড়িয়ে এই সীমাবদ্ধতাটি ঘিরে কাজ করার জন্য কিছু বিকল্প সরবরাহ করেছি।
বিকল্প 1. আপনি এটি করতে পারবেন না: ব্যবহার করুন finally
দুর্ভাগ্যক্রমে, সি ++ বিকাশকারী হিসাবে আপনি এটি করতে পারবেন না। তবে শেষ পর্যন্ত কীওয়ার্ড ধারণ করে এমন ভাষার জন্য এটি প্রথম নম্বর।
try
{
if (!ok)
{
_log.Error("oops");
return;
}
DoSomething(); //notice how this is already farther to the left than the example above
}
finally
{
DoSomethingNoMatterWhat();
}
বিকল্প 2. সমস্যাটি এড়ান: আপনার কার্যগুলি পুনর্গঠন করুন
কোডটি দুটি কার্যে বিভক্ত করে আপনি সমস্যা এড়াতে পারেন। এই সমাধানটি যে কোনও ভাষার জন্য কাজ করার সুবিধা রয়েছে এবং তদ্ব্যতীত এটি চক্রবৃত্তীয় জটিলতাও হ্রাস করতে পারে যা আপনার ত্রুটি হারকে হ্রাস করার একটি প্রমাণিত উপায় এবং যে কোনও স্বয়ংক্রিয় ইউনিট পরীক্ষার স্বাতন্ত্র্যকে উন্নত করে।
এখানে একটি উদাহরণ:
void OuterFunction()
{
DoSomethingIfPossible();
DoSomethingNoMatterWhat();
}
void DoSomethingIfPossible()
{
if (!ok)
{
_log.Error("Oops");
return;
}
DoSomething();
}
বিকল্প 3. ভাষা কৌশল: একটি নকল লুপ ব্যবহার করুন
অন্য একটি সাধারণ কৌতুক আমি দেখতে পাচ্ছি যখন ব্যবহার করা হচ্ছে (সত্য) এবং বিরতি, অন্য উত্তরগুলিতে দেখানো হয়েছে।
while(true)
{
if (!ok) break;
DoSomething();
break; //important
}
DoSomethingNoMatterWhat();
যদিও goto
এটি ব্যবহারের চেয়ে কম "সৎ" , এটি রিফ্যাক্টর করার সময় গণ্ডগোল হওয়ার ঝুঁকি কম, কারণ এটি স্পষ্টত যুক্তির ক্ষেত্রের সীমানা চিহ্নিত করে। আপনার লেবেলগুলি কে বা আপনার goto
বিবৃতি কেটে পেস্ট করে এমন একটি নিষ্পাপ কোডার বড় সমস্যার কারণ হতে পারে! (এবং প্রকৃতপক্ষে প্যাটার্নটি এখন এত সাধারণ যে আমি মনে করি এটি স্পষ্টভাবে অভিপ্রায়টি যোগাযোগ করে, এবং তাই এটি মোটেই "বে "মান" নয়)।
এই বিকল্পগুলির অন্যান্য রূপ রয়েছে। উদাহরণস্বরূপ, এক switch
পরিবর্তে ব্যবহার করতে পারে while
। কোনও break
কীওয়ার্ড সহ যে কোনও ভাষা নির্মাণ সম্ভবত কাজ করবে।
বিকল্প 4. অবজেক্ট লাইফ চক্রটি উত্সাহিত করুন
অন্য একটি পদ্ধতির অবজেক্ট লাইফ চক্রটি লাভ করে। আপনার প্যারামিটারগুলি ধরে রাখার জন্য একটি প্রসঙ্গ অবজেক্ট ব্যবহার করুন (যা আমাদের নিষ্পাপ উদাহরণটিতে সন্দেহজনকভাবে অভাব রয়েছে) এবং আপনার কাজ শেষ হয়ে গেলে তা নিষ্পত্তি করে দিন।
class MyContext
{
~MyContext()
{
DoSomethingNoMatterWhat();
}
}
void MainMethod()
{
MyContext myContext;
ok = DoSomething(myContext);
if (!ok)
{
_log.Error("Oops");
return;
}
ok = DoSomethingElse(myContext);
if (!ok)
{
_log.Error("Oops");
return;
}
ok = DoSomethingMore(myContext);
if (!ok)
{
_log.Error("Oops");
}
//DoSomethingNoMatterWhat will be called when myContext goes out of scope
}
দ্রষ্টব্য: আপনার পছন্দের ভাষার অবজেক্ট লাইফ চক্রটি আপনি বুঝতে পেরেছেন তা নিশ্চিত হন। এটি কাজ করার জন্য আপনার কিছু প্রকারের ডিটারমিনিস্টিক আবর্জনা সংগ্রহের প্রয়োজন, অর্থাৎ আপনাকে জানতে হবে কখন ধ্বংসকারীকে ডাকা হবে। কিছু ভাষায় আপনাকে Dispose
ডেস্ট্রাক্টরের পরিবর্তে ব্যবহার করতে হবে ।
বিকল্প 4.1। অবজেক্ট লাইফ চক্রটি উত্সাহিত করুন (মোড়কের ধরণ)
আপনি যদি কোনও অবজেক্ট-ভিত্তিক পদ্ধতির ব্যবহার করতে চলেছেন তবে পাশাপাশি এটি সঠিকভাবে করতে পারে। এই বিকল্পটি ক্লাসআপের প্রয়োজনীয় সংস্থানগুলি, সেইসাথে এর অন্যান্য ক্রিয়াকলাপগুলিকে "মোড়ানো" করতে একটি শ্রেণি ব্যবহার করে।
class MyWrapper
{
bool DoSomething() {...};
bool DoSomethingElse() {...}
void ~MyWapper()
{
DoSomethingNoMatterWhat();
}
}
void MainMethod()
{
bool ok = myWrapper.DoSomething();
if (!ok)
_log.Error("Oops");
return;
}
ok = myWrapper.DoSomethingElse();
if (!ok)
_log.Error("Oops");
return;
}
}
//DoSomethingNoMatterWhat will be called when myWrapper is destroyed
আবার, নিশ্চিত হয়ে নিন যে আপনি নিজের অবজেক্টের জীবনচক্রটি বুঝতে পেরেছেন।
বিকল্প 5. ভাষার কৌশল: শর্ট সার্কিট মূল্যায়ন ব্যবহার করুন
আরেকটি কৌশল হ'ল শর্ট সার্কিট মূল্যায়নের সুবিধা নেওয়া ।
if (DoSomething1() && DoSomething2() && DoSomething3())
{
DoSomething4();
}
DoSomethingNoMatterWhat();
এই সমাধানটি && অপারেটর যেভাবে কাজ করে তার সুবিধা গ্রহণ করে। && এর বাম দিকটি মিথ্যাতে মূল্যায়ন করলে ডান হাতের দিকটি কখনই মূল্যায়ন করা হয় না।
কমপ্যাক্ট কোডের প্রয়োজন হয় এবং যখন কোডটি খুব বেশি রক্ষণাবেক্ষণের সম্ভাবনা না দেখায় এই কৌশলটি সবচেয়ে কার্যকর তখন উদাহরণস্বরূপ আপনি একটি সুপরিচিত অ্যালগরিদম প্রয়োগ করছেন। আরও সাধারণ কোডিংয়ের জন্য এই কোডটির কাঠামো খুব ভঙ্গুর; এমনকি যুক্তিতে সামান্য পরিবর্তনও মোট পুনরায় লেখার সূত্রপাত করতে পারে।