Java Coding Specification 9 (Exception Log)

1. Exception handling


  1. [Mandatory] The exceptions defined in the Java class library that can be avoided by pre-checking RuntimeExceptionshould not be handled by means of catch, such as: NullPointerException, IndexOutOfBoundsExceptionetc.

    • Description: Except for exceptions that cannot pass the pre-check, for example, when parsing numbers in the form of strings, you have to catch NumberFormatException.
    • Normal example:if (obj != null) {...}
    • Counterexample:try { obj.method() } catch (NullPointerException e) {…}
  2. [Mandatory] Exceptions should not be used for process control and conditional control.

    • The original intention of exception design is to solve various unexpected situations in program operation, and the processing efficiency of exception is much lower than that of condition judgment.
  3. [Mandatory] Please distinguish between stable code and unstable code when catching.

    • Stable code: is code that doesn't go wrong anyway.
    • For the catch of unstable code, distinguish the exception type as much as possible, and then do the corresponding exception handling.
    • [Knock on the blackboard] try-catchIt is irresponsible to perform a large piece of code, so that the program cannot make the correct stress response according to different exceptions, and it is also not conducive to locating the problem.

    • Example: In the scenario of user registration, if the user enters illegal characters, or the user name already exists, or the user's password is too simple, the program will make a classification judgment and prompt the user.

  4. [Mandatory] Catch an exception to handle it, don't catch it and throw it away if you don't want to handle it, throw the exception to its caller if you don't want to handle it. The outermost business user must handle exceptions and convert them into content that users can understand.

  5. [Mandatory] A try block is placed in the transaction code. After a catch exception, if you need to roll back the transaction, you must pay attention to manually rolling back the transaction.

  6. [Mandatory] The finally block must close the resource object and stream object, and do try-catch if there is an exception.

    • If JDK7 and above, you can use try-with-resources method.
  7. [Mandatory] Do not finallyuse in blocks return.

    • After the return in the finally block returns, the method ends execution, and the method ends execution after it will not return, and the return statement in the try block will not be repeated.
  8. [Mandatory] The catching exception and the throwing exception must match exactly, or the catching exception is the parent class of the throwing exception.

    • Explanation: If the opponent is expected to throw a hydrangea, but actually receives a shot put, an accident will occur.
  9. [Mandatory] The return value of the method can be null, and it is not mandatory to return an empty collection, or an empty object, etc. But you must add comments to fully explain under what circumstances a null value will be returned.

    • This manual expressly prevents NPEs as the caller's responsibility. Even if the called method returns an empty collection or an empty object, it is not a peace of mind for the caller, and it is necessary to consider the situation of returning null in scenarios such as remote call failure, serialization failure, and runtime exception.
  10. [Recommended] Preventing NPE is the basic accomplishment of programmers.

    • Note the scenario generated by NPE:

      1. The return type is a basic data type. When returning an object of a wrapped data type, automatic unboxing may generate NPE.
        • Counter example: public int f() { return Integer object}, if null, automatically unbox and throw NPE.
      2. The query result of the database may be null.
      3. Even if the element in the collection isNotEmpty, the retrieved data element may be null.
      4. When a remote call returns an object, a null pointer judgment is always required to prevent NPE.
      5. For the data obtained in the session, it is recommended to check NPE to avoid null pointers.
      6. Cascading calls to obj.getA().getB().getC(); a series of calls can easily generate NPE.
    • Positive example: Use JDK8's Optional class to prevent NPE problems.

  11. [Recommended] Distinguish unchecked / checkedexceptions when defining them, avoid throwing them directly new RuntimeException(), let alone throw them, Exceptionor Throwableuse custom exceptions with business meaning.

    • It is recommended to define custom exceptions that have been defined in the industry, such as: DAOException/ ServiceExceptionetc.
  12. [Recommended] The "error code" must be used for the http/api open interface outside the company.

    • The application recommends that an exception is thrown;
    • Result method is preferred for cross-application RPC calls, encapsulation isSuccess()method, "error code", and "error brief message".
      • The reasons for using the Result method for the RPC method return method:
        • Using the throwing exception return method, the caller will generate a runtime error if it is not caught.
        • If you don't add stack information, just create a new custom exception and add an error message of your own understanding, it will not help the caller to solve the problem too much. If stack information is added, in the case of frequent call errors, the performance loss of data serialization and transmission is also a problem.
  13. [Recommended] Avoid repetitive code (Don't Repeat Yourself), the DRY principle.

    • Note: Copying and pasting the code at will will inevitably lead to the repetition of the code. When you need to modify it later, you need to modify all the copies, which is easy to miss. Extract common methods when necessary, or abstract public classes, or even componentize.
    • Positive example: There are multiple public methods in a class, and they all need to perform several lines of the same parameter verification operation. At this time, please extract:

      private boolean checkParam(DTO dto) {
          ...
      }

2. Log Protocol


  1. [Mandatory] The API in the logging system (Log4j, Logback) cannot be used directly in the application, but the API in the logging framework SLF4J should be used, and the logging framework of the facade mode should be used, which is conducive to the maintenance and the unification of the log processing methods of various classes.

    ```
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    private static final Logger logger = LoggerFactory.getLogger(Abc.class);
    ```
    
  2. [Mandatory] It is recommended to save log files for at least 15 days, because some exceptions have the characteristics of "week" frequency.

  3. [Mandatory] The naming method of extended logs (such as management, temporary monitoring, access logs, etc.) in the application:appName_logType_logName.log

    • logType: log type, recommended categories are stats/monitor/visit, etc.;
    • logName: log description.
    • Advantages: You can know what application the log file belongs to, what type, and what purpose through the file name, which is also helpful for classification and search.
    • Positive example: : Monitor time zone conversion exceptions separately in the mppserver application, such as:mppserver_monitor_timeZoneConvert.log
    • Note: It is recommended to classify logs, such as storing error logs and business logs separately, which is convenient for developers to view and monitor the system in time through logs.
  4. [Mandatory] For trace/debug/info level log output, you must use conditional output or placeholders.

    • illustrate:logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
      • If the log level is warn, the above log will not be printed, but the string concatenation operation will be performed. If the symbol is an object, the toString() method will be executed, which wastes system resources. The above operation is performed, but the final log is not printed.
    • Normal example:

      if (logger.isDebugEnabled()) {
          logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
      }
    • Counterexample:

      logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
  5. [Mandatory] To avoid repeatedly printing logs and wasting disk space, be sure to set this in log4j.xml additivity=false.

    • Normal example:
  6. [Mandatory] Exception information should include two types of information: crime scene information and exception stack information. If it is not processed, it will be thrown up through the keyword throws.

    • Normal example:logger.error(各类参数或者对象toString + "_" + e.getMessage(), e);
  7. [Recommended] Log carefully.

    • The production environment prohibits the output of debug logs; selectively outputs the info log;
    • If you use warn to record business behavior information when you just go online, you must pay attention to the log output volume to avoid bursting the server disk, and remember to delete these observation logs in time.
  8. [Recommended] You can use the warn log level to record user input parameter errors to avoid confusion when complaining. If it is not necessary, please do not display the error level in this scene to avoid frequent alarms.

    • Pay attention to the level of log output. The error level only records system logic errors, and the exception level only records system logic errors and exceptions.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325567251&siteId=291194637