【转】降低代码嵌套层数的两种方法

【转】降低代码嵌套层数的两种方法

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

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

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

1 提前返回

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

Listing 1: 嵌套不合理

public static Error checkError(List> result) {

Error error = new Error();

if (result.size() > 0) {

Iterator> it = result.get(0).iterator();

if (it.hasNext()) {

Map 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> result) {

Error error = new Error();

if (result.isEmpty()) {

error.setCode(Error.NET_WORK_ERR.errorCode);

error.setMessage("ERROR 1");

return error;

}

Iterator> it = result.get(0).iterator();

if (!it.hasNext()) {

error.setCode(Error.NET_WORK_ERR.errorCode);

error.setMessage("ERROR 2");

return error;

}

Map 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);

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

相关推荐

GTX 960 vs GTX 770:预算王者还是性能霸主?
365bet线

GTX 960 vs GTX 770:预算王者还是性能霸主?

📅 07-02 👁️ 4366
冰箱抽屉裂:如何修复和预防?
华为怎么进BT365

冰箱抽屉裂:如何修复和预防?

📅 06-28 👁️ 270
奥斯卡颁奖典礼列表
华为怎么进BT365

奥斯卡颁奖典礼列表

📅 07-08 👁️ 3467