• 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.

  • 相关阅读:
    剑指offer[19]——顺时针打印矩阵
    剑指offer[17]——树的子结构
    剑指offer[16]——合并两个排序的链表
    剑指offer[15]——反转链表
    剑指offer[14]——链表中倒数第k个结点
    剑指offer[13]——调整数组顺序使奇数位于偶数前面
    剑指offer[12]——数值的整数次方
    剑指offer[11]——二进制中1的个数
    剑指offer[10]——矩形覆盖
    linux的基本命令
  • 原文地址:https://www.cnblogs.com/gumuyueying/p/cleancode-ch7.html
Copyright © 2020-2023  润新知