2011-04-12 16 views
10

संभव डुप्लिकेट:
Best practices for exception management in JAVA or C#स्वच्छ कोड बनाने के लिए प्रयास ब्लॉक को पकड़ने के लिए सबसे अच्छा अभ्यास क्या है?

मैं stackoverflow पर a question आज पहले पढ़ा है और यह मेरे अपवाद से निपटने के लिए सबसे अच्छा अभ्यास है क्या बारे में सोचते हैं बनाया है।

तो, मेरे सवाल का है सबसे अच्छा अभ्यासके अपवाद को संभालने के लिए है क्या स्वच्छ और उच्च गुणवत्ता कोड का उत्पादन।

यहाँ मेरी कोड है, मुझे लगता है कि यह सीधे आगे चुप है, लेकिन मुझे पता है कि अगर मैं गलत या स्पष्ट नहीं कर रहा हूँ तो कृपया! मैंने विधियों में टेस्टेबिलिटी और समान अमूर्त स्तर को ध्यान में रखने की कोशिश की है।

हर रचनात्मक टिप्पणी का स्वागत किया है। :)

import java.awt.Point; 
import java.io.Closeable; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.util.List; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import com.google.common.base.Preconditions; 

/** 
* <p>This is a dummy code.</p> 
* The aim is present the best practice on exception separation and handling. 
*/ 
public class ExceptionHandlingDemo { 
    // System.out is not a good practice. Using logger is good for testing too (can be checked if the expected error messages are produced). 
    private Logger logger = LoggerFactory.getLogger(ExceptionHandlingDemo.class); 

    // instance of cannot work with List<Point> 
    private interface PointList extends List<Point> {} 

    /** 
    * The method that loads a list of points from a file. 
    * @param path - The path and the name of the file to be loaded. 
    * Precondition: path cannot be {@code null}. In such case {@link NullPointerException} will be thrown. 
    * Postcondition: if the file don't exist, some IOException occurs or the file doesn't contain the list the returned object is {@code null}. 
    * */ 
    /* (Google throws NullpointerExceptio) since it is not forbidden for the developers to throw it. I know this is arguable but this is out of topic for now. */ 
    public List<Point> loadPointList(final String path) { 
     Preconditions.checkNotNull(path, "The path of the file cannot be null"); 

     List<Point> pointListToReturn = null; 
     ObjectInputStream in = null; 

     try { 
      in = openObjectInputStream(path); 
      pointListToReturn = readPointList(in); 
     } catch (final Throwable throwable) { 
      handleException(throwable); 
     } finally { 
      close(in); 
     } 

     return pointListToReturn; 
    } 

    /*======== Private helper methods by now ========*/ 

    private ObjectInputStream openObjectInputStream(final String filename) throws FileNotFoundException, IOException { 
     return new ObjectInputStream(new FileInputStream(filename)); 
    } 

    private List<Point> readPointList(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { 
     final Object object = objectInputStream.readObject(); 

     List<Point> ret = null; 

     if (object instanceof PointList) { 
      ret = (PointList) object; 
     } 
     return ret; 
    } 

    private void handleException(final Throwable throwable) { 
     // I don't know the best practice here ... 
     logger.error(throwable.toString()); 
    } 

    private void close(final Closeable closeable) { 
     if (closeable != null) { 
      try { 
       closeable.close(); 
      } catch (IOException e) { 
       logger.error("Failed closing: %s", closeable); 
      } 
     } 
    } 

    /*======== Getters and setters by now. ========*/ 

    // ... 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     ExceptionHandlingDemo test = new ExceptionHandlingDemo(); 
     test.loadPointList("test-filename.ext"); 
    } 
} 

संपादित:

क्या मैं से बचने के लिए एक दूसरे के बाद पकड़ के मामलों की बहुत लिख रहा है चाहते हैं ...

+0

@xscape: मैं इसे निश्चित रूप से पढ़ रहा हूं, धन्यवाद। – uthomas

+2

एक साइड नोट के रूप में, मैं अनुशंसा करता हूं कि आप अपने निजी सहायक विधियों को 'स्थैतिक' चिह्नित करें, क्योंकि वे यही हैं: वे इनपुट लेते हैं और उन इनपुटों के आधार पर आउटपुट का उत्पादन करते हैं। जब मैंने आपकी विधि घोषणा पर कोई 'स्थिर' कीवर्ड नहीं देखा, तो मुझे यह जांचने के लिए मजबूर होना पड़ा कि क्या विधियों ने वास्तव में किसी भी राज्य का उपयोग नहीं किया है, जो खराब है, क्योंकि कोड मुझे इसे पढ़ने के लिए महत्वपूर्ण कुछ पर ध्यान केंद्रित करने के लिए मजबूर नहीं करता है। यह प्रश्न यह बताता है कि: http://stackoverflow.com/questions/3346764/should-java-methods-be-static-by-default –

+0

@ ब्रूनो रीइस: धन्यवाद, मैं इसे पढ़ूंगा। – uthomas

उत्तर

2

जांचे हुए अपवादों है कि मैं परेशान करने के लिए नहीं जा रहा हूँ के लिए, मैं हमेशा org.apache.commons.lang.UnhandledException का उपयोग करता हूं।

उदाहरण

/** 
* Calls Thread.sleep(millis) 
*/ 
public static void threadSleep(final long millis) { 
    try { 
     Thread.sleep(millis); 
    } catch (final InterruptedException e) { 
     throw new UnhandledException(e); 
    } 
} 
5

पहली नजर में कुछ सुझाव के लिए:

  1. आप Throwable पकड़ नहीं करना चाहिए और इसके बजाय के रूप में संभव के रूप में एक अपवाद के विशिष्ट पकड़ने। Throwable पकड़ने के साथ दिक्कत यह है कि OutOfMemoryError और तरह तरह Error वर्ग शामिल नहीं है। आप उन लोगों को पारित करना चाहते हैं (वे किसी कारण से अनचेक हैं)।
  2. जब आप अपवाद हमेशा अपवाद गुजरती हैं और लॉग न सिर्फ अपनी toString()। स्टैक ट्रेस के बिना समस्याओं का निदान करना बहुत मुश्किल है।
  3. आप शायद एक सामान्य अपवाद हैंडलिंग विधि नहीं करना चाहती।

तो स्थानों पर आप अपवाद को पकड़ने आप कुछ इस तरह हैं:

} catch (IOException e) { 
    logger.error("some relevant message", e); 
    // now handle the exception case 
} 

संदेश यदि संभव हो तो कुछ प्रासंगिक जानकारी शामिल करना चाहिए। कुछ भी जो समस्या को ट्रैक करने में मदद कर सकता है जब कोई लॉग के माध्यम से शिकार कर रहा है।

+0

मैं एक सामान्य अपवाद हैंडलिंग विधि बनाना चाहता था। क्या आप मुझे समझा सकते हैं कि यह बुरा अभ्यास क्यों है? मेरा मतलब है कि मैं देख सकता हूं कि इस तरह से मैं कुछ अपवादों को निगल सकता हूं जो ऐसा नहीं होना चाहिए, लेकिन अब तक मुझे व्यवसाय तर्क को साफ रखने के लिए कोई बेहतर तरीका नहीं पता था। तो जो मैं नहीं देखना चाहता था वह एक-दूसरे के बाद मामलों को पकड़ना है ... – uthomas

+0

यदि आपके पास कोड का एक सामान्य ब्लॉक है जिसे आप कुछ अपवादों के लिए पुन: उपयोग करना चाहते हैं तो एक सामान्य विधि ठीक होगी। इस समय आपके पास उस विधि में केवल एक पंक्ति है, इसलिए कॉल करने के स्थान पर यह कोई कम कोड नहीं है। यदि आप इसे रखते हैं तो आपको प्रासंगिक संदेश को पास करने के लिए कम से कम एक विधि चर जोड़ना चाहिए। मुझे नहीं लगता कि यह आपके व्यापार तर्क में विशिष्ट लॉगिंग और विशिष्ट अपवाद हैंडलिंग के लिए अशुद्ध है। यदि आप स्वयं कोड के समान ब्लॉक को दोहराते हैं तो मैं इसे बाहर कर दूंगा (यहां तक ​​कि एक सामान्य नियम के रूप में)। – WhiteFang34

1

हमेशा सबसे विशिष्ट अपवाद संभव पकड़ने - में अन्यथा कभी नहीं फेंकने योग्य पकड़ने।

मेरे लिए सबसे महत्वपूर्ण बात यह है कि आपके पास खाली पकड़ ब्लॉक नहीं है - इनमें से एक यह जानने के लिए एक अद्भुत समय ले सकता है कि वास्तव में प्रयास में कुछ अपवाद फेंकता है या नहीं।

मैं व्यक्तिगत रूप से जितनी जल्दी हो सके चेक अपवादों को हटाना पसंद करता हूं और यदि संभव हो तो उन्हें पूर्व/पोस्ट स्थिति जांच के साथ प्रतिस्थापित कर सकता हूं। कम डिग्री के लिए अनचेक अपवादों के साथ ही - हालांकि अनचेक अपवाद वास्तव में ऑब्जेक्ट स्थिति सुनिश्चित करने के लिए पैरामीटर जांच जैसे प्रोग्रामर त्रुटि को इंगित करने के लिए एक बहुत अच्छा तरीका है (हालांकि आवेषण अभी तक बेहतर हो सकते हैं)

+0

+1 कभी खाली नहीं पकड़ ब्लॉक होने के लिए - और चलाने PMD/FindBugs यह क्या करता है, तो अपने लकड़हारा फेंकता है, जबकि आप एक अपवाद प्रवेश कर रहे हैं – artbristol

+0

लेने के लिए? – apollodude217

+0

उम्मीद है कि आपके अपवाद के कारण स्टेडर के अपवाद के बारे में रिपोर्ट करने के लिए पर्याप्त स्मार्ट है, इसलिए कम से कम आपके पास कुछ है। –

0

कुछ विकल्प जिन्हें आप चुन सकते हैं।

  1. अपवादों के सबसे महत्वपूर्ण अनुदानों में से एक यह है कि आप सभी मामलों के लिए एकमात्र अपवाद हैंडलर हो सकते हैं। जब आप अपना कोड लिखते हैं तो आपको पहले कार्यक्षमता के बारे में सोचना चाहिए और केवल अपवाद हैंडलिंग के बारे में सोचना चाहिए। नतीजतन आप कुछ स्थानों पर अनचेक अपवादों के लिए प्रयास/पकड़ सकते हैं और चेक अपवादों के लिए throws SomeCheckedException के रूप में अपनी विधियों की घोषणा कर सकते हैं। यह आपको अपवाद हैंडलर की न्यूनतम संख्या रखने की अनुमति देता है।

  2. यदि आपको नहीं पता कि अपवाद के साथ वास्तव में क्या करना है, तो बस इसे फिर से करें।

  3. यदि आप चेक अपवाद पकड़ते हैं लेकिन आप नहीं चाहते हैं कि आपके कोड का उपयोग करने वाले क्लाइंट अपवादों को संसाधित करें, तो आप अनचेक में अपवाद अपडेट को चेक कर सकते हैं। (। हाइबरनेट इस तरह से अपवाद प्रक्रियाओं वे जाँच की एसक्यूएल अपवाद को पकड़ने और बजाय इस बात का अनियंत्रित अपवाद फेंक)
  4. पिछले सिफारिश अपने लिए सुविधाजनक नहीं हैं, तो आप भी कुछ विकल्प चुन सकते हैं:
    • तुम सिर्फ जोड़ सकते हैं प्रवेश और एक ही अपवाद rethrow
    • आप initCause() विधि
    • साथ नया अपवाद फेंकने आपको लगता है कि कोड है कि अपने कोड का आह्वान originial अपवाद बारे में कुछ पता नहीं करना चाहिए सोच सकते द्वारा अपवाद जंजीरों का उपयोग कर सकते, या तो आप के द्वारा इस संगृहीत कर सकता है नया अपवाद बनाना या fillInStackTrace() विधि का उपयोग करके।
  5. थ्रोबल पकड़ने के बारे में। हां तरीकों से आपको इसे पकड़ना नहीं चाहिए। लेकिन एक नियम के रूप में जो ग्राहक आपके प्रोग्राम का उपयोग करता है, उसे उत्साह देखने की ज़रूरत नहीं है, नतीजतन, आप कुछ अपवाद हैंडलर में थ्रोबल को पकड़ सकते हैं जो श्रृंखला में शीर्ष है।
संबंधित मुद्दे