নেস্টেড ট্রাই-ক্যাচ ব্লকগুলি কী কোনও অ্যান্টি-প্যাটার্নটি ব্যবহার করে?


95

এটি কি একটি প্রতিষেধক? এটা কি গ্রহণযোগ্য অনুশীলন?

    try {
        //do something
    } catch (Exception e) { 
        try {
            //do something in the same line, but being less ambitious
        } catch (Exception ex) {
            try {
                //Do the minimum acceptable
            } catch (Exception e1) {
                //More try catches?
            }
        }
    }

আপনি কি আমাদের এই জন্য মামলা দিতে পারেন? আপনি শীর্ষ স্তরের ক্যাচে প্রতিটি ত্রুটি টাইপ কেন পরিচালনা করতে পারবেন না?
মরনস

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

@ লকিআস্তারি -আপনার উদাহরণটি শেষাংশে চেষ্টা করা .. যেখানে কোনও ক্যাচ নেই। এটি চেষ্টা বিভাগে নেস্টেড .. এটি আলাদা।
মরনস

4
কেন এটি অ্যান্টি-প্যাটার্ন হওয়া উচিত?

2
"আরও চেষ্টা করে ক্যাচ?"
জোয়েলফ্যান

উত্তর:


85

এটি কখনও কখনও অপরিবর্তনীয়, বিশেষত যদি আপনার পুনরুদ্ধার কোডটি একটি ব্যতিক্রম নষ্ট করে।

সুন্দর নয়, তবে কখনও কখনও কোনও বিকল্প নেই।


17
@ মিস্টারস্মিত - সবসময় না।
ওডে

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

5
@ মিস্টারস্মিত: আমি আংশিকভাবে পতাকা ভেরিয়েবলের সাথে নিয়ন্ত্রিত সিক্যুয়াল ট্র্যাচ-ক্যাচগুলিতে নেস্টেড ট্রাই-ক্যাচগুলি পছন্দ করব (যদি সেগুলি কার্যত একই ছিল)।
হতাশ

31
চেষ্টা করুন {লেনদেন.কম (); } ক্যাচ {চেষ্টা করুন {ট্রানজেকশন.রোলব্যাক (); } ক্যাচ {সিরিয়াসলগিং ()} notsoseriouslogging (); a একটি প্রয়োজনীয় নেস্টেড
ট্রাই

3
কমপক্ষে কোনও পদ্ধতিতে ক্যাচ ব্লকটি বের করুন, ছেলেরা! আসুন কমপক্ষে এটি পঠনযোগ্য করে তুলি।
মিঃ কোচিজ

43

আমি এটিকে একটি অ্যান্টিপ্যাটার্ন বলে মনে করি না, কেবলমাত্র ব্যাপকভাবে অপব্যবহার করা হয়েছে।

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

তবে এমন অনেক সময় রয়েছে যে আপনি এটি সহায়তা করতে পারবেন না।

try{
     transaction.commit();
   }catch{
     logerror();
     try{
         transaction.rollback(); 
        }catch{
         seriousLogging();
        }
   }

এছাড়াও, ব্যর্থ রোলব্যাকটি ইঙ্গিত করতে আপনার কোথাও একটি অতিরিক্ত বুল প্রয়োজন ...


19

যুক্তিটি ঠিক আছে - কিছু পরিস্থিতিতে ফ্যালব্যাক পদ্ধতির চেষ্টা করার জন্য এটি সঠিক ধারণা তৈরি করতে পারে, যা নিজেই ব্যতিক্রমী ঘটনাগুলি অনুভব করতে পারে .... তাই এই প্যাটার্নটি বেশ অনেকটা অনিবার্য।

তবে কোডটি আরও ভাল করার জন্য আমি নীচের পরামর্শ দেব:

  • রিফ্যাক্টর অভ্যন্তরীণ চেষ্টা করুন ... ব্লকগুলি আলাদা ফাংশন হিসাবে ধরুন, যেমন attemptFallbackMethodএবং attemptMinimalRecovery
  • যে বিশেষ ব্যতিক্রম ধরা পড়েছে সে সম্পর্কে আরও সুনির্দিষ্ট হন। আপনি কি সত্যিই কোনও ব্যতিক্রম সাবক্লাস আশা করেন এবং যদি তাই হয় তবে আপনি কি সত্যিই সেগুলি একইভাবে পরিচালনা করতে চান?
  • কোনও finallyব্লক আরও অর্থবোধ করতে পারে কিনা তা বিবেচনা করুন - এটি সাধারণত "রিসোর্স ক্লিনআপ কোড" বলে মনে হয় এমন কোনও কিছুর ক্ষেত্রে এটি হয় is

14

ঠিক আছে. বিবেচনা করার জন্য একটি রিফ্যাক্টরিং হ'ল কোডটিকে তার নিজস্ব পদ্ধতিতে চাপ দেওয়া এবং সাফল্যের জন্য প্রারম্ভিক প্রস্থানগুলি ব্যবহার করা, আপনাকে একই স্তরে কিছু করার বিভিন্ন প্রচেষ্টা লিখতে দেওয়া:

try {
    // do something
    return;
} catch (Exception e) {
    // fall through; you probably want to log this
}
try {
    // do something in the same line, but being less ambitious
    return;
} catch (Exception e) {
    // fall through again; you probably want to log this too
}
try {
    // Do the minimum acceptable
    return;
} catch (Exception e) {
    // if you don't have any more fallbacks, then throw an exception here
}
//More try catches?

একবার এটির মতো ছিন্ন হয়ে গেলে আপনি কৌশল কৌশলতে এটি মোড়ানোর বিষয়ে ভাবতে পারেন।

interface DoSomethingStrategy {
    public void doSomething() throws Exception;
}

class NormalStrategy implements DoSomethingStrategy {
    public void doSomething() throws Exception {
        // do something
    }
}

class FirstFallbackStrategy implements DoSomethingStrategy {
    public void doSomething() throws Exception {
        // do something in the same line, but being less ambitious
    }
}

class TrySeveralThingsStrategy implements DoSomethingStrategy {
    private DoSomethingStrategy[] strategies = {new NormalStrategy(), new FirstFallbackStrategy()};
    public void doSomething() throws Exception {
        for (DoSomethingStrategy strategy: strategies) {
            try {
                strategy.doSomething();
                return;
            }
            catch (Exception e) {
                // log and continue
            }
        }
        throw new Exception("all strategies failed");
    }
}

তারপরে কেবল এটি ব্যবহার করুন TrySeveralThingsStrategyযা এক ধরণের যৌগিক কৌশল (একটির মূল্যের জন্য দুটি নিদর্শন!)।

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


7

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


6

প্রতি সেফ কোনও অ্যান্টি-প্যাটার্ন নয়, এমন একটি কোড প্যাটার্ন যা আপনাকে বলবে যে রিফ্যাক্টর করতে হবে।

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

থাম্বের এই নিয়ম রবার্ট সি মার্টিনের "ক্লিন কোড" বইয়ের পরামর্শের ভিত্তিতে রচিত:

যদি 'চেষ্টা' শব্দটি কোনও ফাংশনে বিদ্যমান থাকে তবে এটি ফাংশনে প্রথম শব্দ হওয়া উচিত এবং ক্যাচ / অবশেষে ব্লক হওয়ার পরে কিছুই হওয়া উচিত নয়।

"ছদ্ম-জাভা" এর একটি দ্রুত উদাহরণ। ধরুন আমাদের কাছে এরকম কিছু রয়েছে:

try {
    FileInputStream is = new FileInputStream(PATH_ONE);
    String configData = InputStreamUtils.readString(is);
    return configData;
} catch (FileNotFoundException e) {
    try {
        FileInputStream is = new FileInputStream(PATH_TWO);
        String configData = InputStreamUtils.readString(is);
        return configData;
    } catch (FileNotFoundException e) {
        try {
            FileInputStream is = new FileInputStream(PATH_THREE);
            String configData = InputStreamUtils.readString(is);
            return configData;
        } catch (FileNotFoundException e) {
            return null;
        }
    }
}

তারপরে আমরা প্রতিটি চেষ্টা করে ক্যাচ রিফ্যাক্টর করতে পারি এবং এক্ষেত্রে প্রতিটি ট্রাই-ক্যাচ ব্লক একই জিনিসটি চেষ্টা করে তবে বিভিন্ন স্থানে (কতটা সুবিধাজনক: ডি), আমাদের কেবল চেষ্টা-ধরা ব্লকগুলির একটি অনুলিপি করতে হবে এবং এটির একটি পদ্ধতি তৈরি করতে হবে ।

public String loadConfigFile(String path) {
    try {
        FileInputStream is = new FileInputStream(path);
        String configData = InputStreamUtils.readString(is);
        return configData;
    } catch (FileNotFoundException e) {
        return null;
    }
}

এখন আমরা এটি আগের মতো একই উদ্দেশ্যে ব্যবহার করি।

String[] paths = new String[] {PATH_ONE, PATH_TWO, PATH_THREE};

String configData;
for(String path : paths) {
    configData = loadConfigFile(path);
    if (configData != null) {
        break;
    }
}

আমি আশা করি এটি সাহায্য করবে :)


ভালো উদাহরণ. এই উদাহরণটি সত্যই আমাদের ধরণের রিঅ্যাক্টরযুক্ত কোডের। তবে অন্য কিছু সময় নেস্টেড ট্রাই-ক্যাচ করা দরকার।
linehrr

4

এটি অবশ্যই কোডের পঠনযোগ্যতা হ্রাস পাচ্ছে। আমি বলব, যদি আপনার সুযোগ থাকে তবে বাসা বাঁধতে চেষ্টা করুন ক্যাচগুলি।

যদি আপনার চেষ্টা করে বাসা বাঁধতে হয় তবে সর্বদা এক মিনিটের জন্য থামুন এবং ভাবেন:

  • আমি তাদের একত্রিত করার সুযোগ আছে?

    try {  
      ... code  
    } catch (FirstKindOfException e) {  
      ... do something  
    } catch (SecondKindOfException e) {  
      ... do something else    
    }
    
  • আমি কি কেবল নতুন পদ্ধতিতে নেস্টেড অংশটি বের করতে পারি? কোডটি অনেক বেশি পরিষ্কার হবে।

    ...  
    try {  
      ... code  
    } catch (FirstKindOfException e) {  
       panicMethod();  
    }   
    ...
    
    private void panicMethod(){   
    try{  
    ... do the nested things  
    catch (SecondKindOfException e) {  
      ... do something else    
      }  
    }
    

এটি যদি আপনার একক পদ্ধতিতে তিন বা ততোধিক স্তরের চেষ্টা করে বাসা বাঁধতে হয় তবে তা স্পষ্ট।


3

আমি নেটওয়ার্ক কোডে এই প্যাটার্নটি দেখেছি এবং এটি প্রকৃত অর্থে উপলব্ধি করে। সিউডোকোডে এখানে মূল ধারণাটি রয়েছে:

try
   connect;
catch (ConnectionFailure)
   try
      sleep(500);
      connect;
   catch(ConnectionFailure)
      return CANT_CONNECT;
   end try;
end try;

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


2

আমি এই পরিস্থিতিটিকে এর মতো সমাধান করেছি (ফ্যালব্যাক দিয়ে চেষ্টা করুন):

$variableForWhichINeedFallback = null;
$fallbackOptions = array('Option1', 'Option2', 'Option3');
while (!$variableForWhichINeedFallback && $fallbackOptions){
    $fallbackOption = array_pop($fallbackOptions);
    try{
        $variableForWhichINeedFallback = doSomethingExceptionalWith($fallbackOption);
    }
    catch{
        continue;
    }
}
if (!$variableForWhichINeedFallback)
    raise new ExceptionalException();

2

আমি এটি একটি পরীক্ষার ক্লাসে (জুনিত) কাকতালীয়ভাবে "করণীয়" করতে পেরেছি, যেখানে সেটআপ () পদ্ধতিটি কোনও ব্যতিক্রম ছুঁড়ে এমন কোনও কনস্ট্রাক্টরে অবৈধ কনস্ট্রাক্টর পরামিতি সহ বস্তু তৈরি করতে হয়েছিল।

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

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


0

আমি আসলে এটি একটি অ্যান্টিপ্যাটার্ন মনে করি।

কিছু ক্ষেত্রে আপনি একাধিক চেষ্টা করতে পারেন, তবে আপনি কী ধরণের ত্রুটি খুঁজছেন তা যদি আপনি জানেন না তবে উদাহরণস্বরূপ:

public class Test
{
    public static void Test()
    {            
        try
        {
           DoOp1();
        }
        catch(Exception ex)
        {
            // treat
        }

        try
        {
           DoOp2();
        }
        catch(Exception ex)
        {
            // treat
        }

        try
        {
           DoOp3();
        }
        catch(Exception ex)
        {
            // treat
        }
    }

    public static void Test()
    {
        try
        {
            DoOp1();
            DoOp2();
            DoOp3();
        }
        catch (DoOp1Exception ex1)
        {
        }
        catch (DoOp2Exception ex2)
        {
        }
        catch (DoOp3Exception ex3)
        {
        }
    }
}

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

সুতরাং, আপনি কী ধরণের ত্রুটি খুঁজছেন তা যদি জানেন তবে সুনির্দিষ্ট করুন । একই পদ্ধতির অভ্যন্তরে নেস্টেড বা একাধিক চেষ্টা করার দরকার নেই।


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

0

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


0

জাভাতে কোথাও অ্যান্টি প্যাটার্ন হিসাবে উল্লেখ করা হয়নি। হ্যাঁ আমরা কয়েকটি বিষয়কে ভাল অনুশীলন এবং খারাপ অনুশীলন বলি।

যদি কোনও ক্যাচ ব্লকের ভিতরে চেষ্টা / ক্যাচ ব্লকের প্রয়োজন হয় তবে আপনি এটি সহায়তা করতে পারবেন না। আর এর বিকল্প নেই। ক্যাচ ব্লক যেমন ব্যতিক্রম নিক্ষেপ করা হয় তবে চেষ্টা অংশ হিসাবে কাজ করতে পারে না।

উদাহরণ স্বরূপ :

String str=null;
try{
   str = method(a);
}
catch(Exception)
{
try{
   str = doMethod(a);
}
catch(Exception ex)
{
  throw ex;
}

এখানে উপরের উদাহরণে পদ্ধতিটি ব্যতিক্রম ছুঁড়েছে তবে doMethod (পদ্ধতি ব্যতিক্রম পরিচালনার জন্য ব্যবহৃত) এমনকি ব্যতিক্রম ছুঁড়ে। এক্ষেত্রে আমাদের চেষ্টা করে ক্যাচ ব্যবহারের মধ্যে চেষ্টা করতে হবে।

কিছু না করার পরামর্শ দেওয়া হচ্ছে যা হ'ল ..

try 
{
  .....1
}
catch(Exception ex)
{
}
try 
{
  .....2
}
catch(Exception ex)
{
}
try 
{
  .....3
}
catch(Exception ex)
{
}
try 
{
  .....3
}
catch(Exception ex)
{
}
try 
{
  .....4
}
catch(Exception ex)
{
}

এই পূর্বে 12 উত্তর উপর কিছু সারগর্ভ প্রস্তাব বলে মনে হচ্ছে না
মশা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.