zoukankan      html  css  js  c++  java
  • 【转】降低代码嵌套层数的两种方法

    原文: https://blog.csdn.net/tq1086/article/details/109580462

    -----------------------------------------------------------------------------------------------------

    嵌套层次过深会导致代码难以理解和修改,也容易出现逻辑分支缺失,引入缺陷。导致嵌套层次过深的原因主要有两点:一是不恰当的嵌套,二是逻辑过于复杂。针对这两种情况,可以分别采用提前返回和封装的手法处理。

    1 提前返回

    一些代码在使用逻辑判断、循环和异常捕获时,嵌套层次不合理,导致嵌套层次过深。这种情况通常表现为,某个分支中的代码非常简短。这时可以采用提前返回的方式,压缩嵌套层级。

    Listing 1: 嵌套不合理

    public static Error checkError(List<DataTable<String, String>> result) {
        Error error = new Error();
    
        if (result.size() > 0) {
            Iterator<Map<String, String>> it = result.get(0).iterator();
            if (it.hasNext()) {
                Map<String, String> e = it.next();
                if (e.containsKey("code")) {
                    String code = e.get("code");
                    if ("0".equals(code)) {
                        return null;
                    } else {
                        error.setCode(Integer.parseInt(code.replace("0x", ""), 16));
                        error.setMessage(e.get("message"));
                        return error;
                    }
                } else {
                    error.setCode(Error.NET_WORK_ERR.errorCode);
                    error.setMessage("ERROR 1");
                    return error;
                }
            } else {
                error.setCode(Error.NET_WORK_ERR.errorCode);
                error.setMessage("ERROR 2");
                return error;
            }
        } else {
            error.setCode(Error.NET_WORK_ERR.errorCode);
            error.setMessage("ERROR 3");
            return error;
        }
    }
    

    Listing 2: 提前返回

    public static Error checkSmsError(List<DataTable<String, String>> result) {
        Error error = new Error();
        if (result.isEmpty()) {
            error.setCode(Error.NET_WORK_ERR.errorCode);
            error.setMessage("ERROR 1");
            return error;
        }
    
        Iterator<Map<String, String>> it = result.get(0).iterator();
        if (!it.hasNext()) {
            error.setCode(Error.NET_WORK_ERR.errorCode);
            error.setMessage("ERROR 2");
            return error;
        }
    
        Map<String, String> e = it.next();
        if (!e.containsKey("code")) {
            error.setCode(Error.NET_WORK_ERR.errorCode);
            error.setMessage("ERROR 3");
            return error;
        }
    
        String code = e.get("code");
        if ("0".equals(code)) {
            return null;
        }
    
        String message = e.getOrDefault("message", "");
        if (HelperUtil.shouldPreventSmsError(code, message)) {
            return null;
        }
    
        error.setCode(Integer.parseInt(code.replace("0x", ""), 16));
        error.setMessage(message);
        return error;
    }
    

    提前返回还有一种do-while(0)模式:

    Listing 3: 嵌套不合理

    FILE *f1 = fopen("a.txt", "r");
    if (f1 != NULL) {
        FILE *f2 = fopen("b.txt", "r");
        if (f2 != NULL) {
            FILE *f3 = fopen("b.txt", "r");
            if (f3 != NULL) {
                int result = do_something(f1, f2, f3);
                fclose(f1);
                fclose(f2);
                fclose(f3);
                return result;
            } else {
                fclose(f1);
                fclose(f2);
                return -1;
            }
        } else {
            fclose(f1);
            return -1;
        }
    } else {
        return -1;
    }
    

    Listing 4: 提前返回 do-while(0)

    int result = 0;
    FILE *f1 = NULL;
    FILE *f2 = NULL;
    FILE *f3 = NULL;
    
    do {
        FILE *f1 = fopen("a.txt", "r");
        if (f1 == NULL) {
            break;
        }
        FILE *f2 = fopen("b.txt", "r");
        if (f2 == NULL) {
            break;
        }
        FILE *f3 = fopen("c.txt", "r");
        if (f3 == NULL) {
            break;
        }
    
        result = do_something(f1, f2, f3);
    } while (0);
    
    if (f1 != NULL) {
        fclose(f1);
    }
    if (f2 != NULL) {
        fclose(f1);
    }
    if (f3 != NULL) {
        fclose(f1);
    }
    
    return result;
    

    2 封装

    除了嵌套不合理外,逻辑复杂也是导致嵌套层次过深的主要原因。对于这种情况可以采用封装的方法处理。

    Listing 5: 逻辑复杂

    double discountRate = 1.0;
    int extraDiscount = 0;
    
    if (itemId == Item.FRUIT) {
        if (itemCount >= 10) {
            discountRate = 0.9;
        } else if (itemCount >= 50) {
            discountRate = 0.85;
            extraDiscount = 10;
        } else if (itemCount >= 100) {
            discountRate = 0.8;
            extraDiscount = 20;
        }
    } else if (itemId == Item.MILK) {
        if (itemCount >= 20) {
            discountRate = 0.88;
        }    
    } else {
        if (itemCount >= 30) {
            discountRate = 0.9;
        }
    }
    
    double originalPrice = itemCount * itemPrice;
    double price = originalPrice * discountRate - extraDiscount;
    

    Listing 6: 封装

    interface DiscountStrategy {
        double getDiscountedPrice(int itemCount, double originalPrice);
    }
    
    class NormalDiscountStrategy implements DiscountStrategy {
        public double getDiscountedPrice(int itemCount, double originalPrice) {
            double rate = 1.0;
            if (itemCount > 30) {
                rate = 0.9;
            }
            return originalPrice * rate;
        }
    }
    
    class MilkDiscountStrategy implements DiscountStrategy {
        public double getDiscountedPrice(int itemCount, double originalPrice) {
            double rate = 1.0;
            if (itemCount > 20) {
                rate = 0.88;
            }
            return originalPrice * rate;
        }
    }
    
    class FruitDiscountStrategy implements DiscountStrategy {
        public double getDiscountedPrice(int itemCount, double originalPrice) {
            double rate = 1.0;
            int extra = 0;
    
            if (itemCount >= 10) {
                rate = 0.9;
            } else if (itemCount >= 50) {
                rate = 0.85;
                extra = 10;
            } else if (itemCount >= 100) {
                rate = 0.8;
                extra = 20;
            }
    
            return originalPrice * rate - extra;
        }
    }
    
    class DiscountStrategyFactory {
        DiscountStrategy getDiscountStrategy(int itemId) {
            switch (itemId) {
            case Item.FRUIT:
                return new FruitDiscountStrategy();
            case Item.MILK:
                return new MilkDiscountStrategy();
            default:
                return new NormalDiscountStrategy();
            }
        }
    }
    
    double originalPrice = itemCount * itemPrice;
    double price = DiscountStrategyFactory.getDiscountStrategy(itemId).getDiscountedPrice(itemCount, originalPrice);
    

    采用封装的方法,总的代码行数会增加。但是每个模块(类、方法)的内聚更高,可复用性更好,客户端代码的编写变得更简单

  • 相关阅读:
    2019年6月4号总结
    2019年5月21号总结
    2019年5月8号总结
    2019年5月6号总结
    2019年5月5号总结
    2019年4月18号总结
    java错误笔记之判断字符知否为空出错
    错误笔记:静态方法不能实例化,直接用类名.方法名调用
    Thymeleaf中"th:each""th:if"的用法解析
    @ResponseBody 表示返回的是josn
  • 原文地址:https://www.cnblogs.com/oxspirt/p/14188400.html
Copyright © 2011-2022 走看看