zoukankan      html  css  js  c++  java
  • Clean Code–Chapter 7 Error Handling

    Error handling is important, but if it obscures logic, it's wrong.

    Use Exceptions Rather Than Return Codes

    Separate the normal operations with error handlings.

    e.g.

    Bad code:

    public class DeviceController {
        ...
        public void sendShutDown() {
            DeviceHandle handle = getHandle(DEV1);
            // Check the state of the device
            if (handle != DeviceHandle.INVALID) {
                // Save the device status to the record field
                retrieveDeviceRecord(handle);
                // If not suspended, shut down
                if (record.getStatus() != DEVICE_SUSPENDED) {
                    pauseDevice(handle);
                    clearDeviceWorkQueue(handle);
                    closeDevice(handle);
                } else {
                    logger.log("Device suspended. Unable to shut down");
                }
            } else {
                logger.log("Invalid handle for: " + DEV1.toString());
            }
        }
        ...
    }

    Good code:

    public class DeviceController {
        ...
        public void sendShutDown() {
            try {
                tryToShutDown();
            } catch (DeviceShutDownError e) {
                logger.log(e);
            }
        }
        private void tryToShutDown() throws DeviceShutDownError {
            DeviceHandle handle = getHandle(DEV1);
            DeviceRecord record = retrieveDeviceRecord(handle);
            pauseDevice(handle);
            clearDeviceWorkQueue(handle);
            closeDevice(handle);
        }
        private DeviceHandle getHandle(DeviceID id) {
            ...
            throw new DeviceShutDownError("Invalid handle for: " + id.toString());
            ...
        }
        ...
    }

    Write Your Try-Catch-Finally Statement First

    It is good practice to start with a try-catch-finally statement when you are writing code that could throw exceptions.

    (本节中有关单元测试的讲解,没看明白,留待以后回顾再看。)

    Use Unchecked Exceptions

    Checked exceptions is an Open/Closed Principle violation.

    (C# doesn't have checked exceptions.)

    Provide Context with Exceptions

    To determine the source and location of an error.

    Mention the operation that failed and the type of failure.

    Define Exception Classes In terms of a Caller's Needs

    Most important concern: how they are caught.

    In most exception handling situations, the work that we do is relatively standard regardless of the actual cause. So we can simplify our code considerably by wrapping the third-party APIs.

    e.g.

    Bad code:

    ACMEPort port = new ACMEPort(12);
    try {
        port.open();
    } catch (DeviceResponseException e) {
        reportPortError(e);
        logger.log("Device response exception", e);
    } catch (ATM1212UnlockedException e) {
        reportPortError(e);
        logger.log("Unlock exception", e);
    } catch (GMXError e) {
        reportPortError(e);
        logger.log("Device response exception");
    }
    finally {
        …
    }

    Good code:

    LocalPort port = new LocalPort(12);
    try {
        port.open();
    }
    catch (PortDeviceFailure e) {
        reportError(e);
        logger.log(e.getMessage(), e);
    }
    finally {
        …
    }
    
    public class LocalPort {
        private ACMEPort innerPort;
        public LocalPort(int portNumber) {
            innerPort = new ACMEPort(portNumber);
        }
        public void open() {
            try {
                innerPort.open();
            } catch (DeviceResponseException e) {
                throw new PortDeviceFailure(e);
            } catch (ATM1212UnlockedException e) {
                throw new PortDeviceFailure(e);
            } catch (GMXError e) {
                throw new PortDeviceFailure(e);
            }
        }
        …
    }

    Define the Normal Flow

    Use the Special Case Pattern. Create a class or configure an object so that it handles a special case for you. When you do, the client code doesn't have to deal with exceptional behavior. That behavior is encapsulated in the special case object.

    Don't Return Null

    When we return null, we are essentially creating work for ourselves and foisting problems upon our callers.

    If you are tempted to return null from a method, consider throwing an exception or returning a special case object instead. If you are calling a null-returning method from a third-party API, consider wrapping that method with a method that either throws an exception or returns a special case object.

    e.g.

    Bad code:

    List<Employee> employees = getEmployees();
    if (employees != null) {
        for(Employee e : employees) {
            totalPay += e.getPay();
        }
    }

    Good code:

    List<Employee> employees = getEmployees();
    for(Employee e : employees) {
        totalPay += e.getPay();
    }
    
    public List<Employee> getEmployees() {
        if( .. there are no employees .. )
            return Collections.emptyList();
    }

    Don't Pass Null

    Conclusion

    We can write robust clean code if we see error handling as a separate concern, something that is viewable independently of our main logic. To the degree that we are able to do that, we can reason about it independently, and we can make great strides in the maintainability of our code.

  • 相关阅读:
    Django(60)Django内置User模型源码分析及自定义User
    Django(59)验证和授权
    Django(58)viewsets视图集详解
    Django(57)Generic类视图
    正则表达式
    JMeter之检查点(JSON断言)
    JMeter之检查点(响应断言)
    JMeter之参数化(一)
    JMeter之一个简单的性能测试
    JMeter基础
  • 原文地址:https://www.cnblogs.com/gumuyueying/p/cleancode-ch7.html
Copyright © 2011-2022 走看看