删除重复代码会导致冗余操作?

removing duplicate code cause redundant operation?

void caller()
{
    int var;

    var = setvar();
    if (var == 1)
        func1();
    else if (var == 3)
        func3();
    else if (var == 8)
        func8();
}

void func1()
{
    common();
    //do something case 1 specific...
}

void func3()
{
    common();
    //do something case 3 specific...
}

void func8()
{
    common();
    //do something case 8 specific...
}

在这种情况下,我觉得很不舒服,因为我有重复的函数 common() 可以写在 caller()去除重复项的功能。所以我可以像这样更改上面的代码:

void caller()
{
    int var;

    var = setvar();
    if (var == 1 || var == 3 || var == 8)
        common();
    if (var == 1)
        func1();
    else if (var == 3)
        func3();
    else if (var == 8)
        func8();
}

void func1()
{ //do something case 1 specific... }

void func3()
{ //do something case 3 specific... }

void func8()
{ //do something case 8 specific... }

然而,我在这种情况下也感到非常不舒服,因为 caller() 函数现在检查 var 的值两次。

我没有太多的编码经验,所以我不知道要考虑什么来选择哪个更好。什么是更好的代码,为什么?我需要考虑什么?

我会选择第二种方法。

首先,我将通过分离验证函数(改进调试)并使用 switch case 来根据 var.

的值确定要 运行 的函数来改进此代码。

优点:

  • 您只需查看 isAllowed 个数字,即可轻松了解函数 common() 的使用位置。
  • 不需要在您使用它的每个函数中都写 common()。如果你在数百个函数中使用它,那将是多余的,你可能会忘记一个。
  • 轻松可视化何时应用 common()

缺点:

  • 您必须根据 isAllowed 定义的整数在 switch/case 中添加或删除大小写(根据您的喜好使用 if/else)。如果您忘记添加案例或发生错误,可能会导致火灾 default
  • 您仔细检查变量的值。
int isAllowed(int var){
    return var == 1 || var == 3 || var == 8;
}

void caller()
{
    int var = setVar();
    if (isAllowed(var)){
        common();
        switch(var){
            case 1:
                func1();
                break;
            case 3:
                func3();
                break;
            case 8:
                func8();
                break;
            default:
                break;
        }
    }
}

您可以使用函数指针:

void caller()
{
    int var = setvar();
    void (*func)() = NULL;

    if (var == 1)
        func = func1;
    else if (var == 3)
        func = func3;
    else if (var == 8)
        func = func8;
    else return; // or error handling

    common();
    func();
}

如果一个特殊的common用于特定的情况,那么可以使用两个函数指针,一个用于common部分,另一个用于func部分。

void caller()
{
    int var = setvar();
    void (*func)() = NULL;
    void (*fcommon)() = common; // default common

    if (var == 1) {
        func = func1;
    } else if (var == 3) {
        func = func3;
    } else if (var == 8) {
        fcommon = common_for_8;
        func = func8;
    } else {
        return; // or error handling
    }

    fcommon();
    func();
}

如果 common 仅供 func1func3func8 调用,那么第一个选项更好 - 没有理由 caller了解一下common,更不用说直接调用了。

理想情况下,caller 不应该关心 func1func3func8 在内部做什么;它应该只关心它们采用什么参数以及它们 return 的值。假设您需要添加另一个函数(我们称之为 func5)。它也需要调用 common 吗?或者不是吗?如果您需要更改 func3 的行为以使其不再调用 common 怎么办?

使用第一个选项,您将 common 的知识本地化到实际使用它的函数,这将使维护和调试更容易。