【问题标题】:Is there a name for this anti-pattern (a function with modes)?这种反模式(具有模式的函数)有名称吗?
【发布时间】:2016-03-05 00:43:16
【问题描述】:

程序员经常会注意到他在几个地方有一些非常相似的代码。可以说这里有类似代码的实例。 (为了清楚起见,这是一个玩具示例。在野外,这种反模式通常不会出现在这么简单的代码上)

function showLoginError(){
    let msg = "Login Error";
    logAtLevel(WARNING, msg);
    displayInPopup(msg);
}

function showDbError(){
    let msg = "Could not access DB";
    logAtLevel(ERROR, msg);
    displayInPopup(msg);
    notify("db-admin@foo.com");
}

function showUnknownError(){
    let msg = "Something has gone wrong";
    logAtLevel(ERROR, msg);
    displayInPopup(msg);
    notify("general-admin@foo.com");
}

一个有经验的程序员可能会重构成这样的东西,现在它可以被普遍重用并且非常容易理解。

function showError(logLevel, msg, notifyEmail){
    logAtLevel(logLevel, msg);
    displayInPopup(msg);
    if(notifyEmail){
        notify(notifyEmail);
    }
}

function showLoginError(){
    showError(WARNING, "Login Error");
}

function showDbError(){
    showError(ERROR, "Could not access DB", "db-admin@foo.com");
}

function showUnknownError(){
    showError(ERROR, "Something has gone wrong", "general-admin@foo.com");
}

但是对于经验较少的程序员,我经常看到类似的东西

function showError(errorType){
    let msg;
    let logLevel = ERROR;
    if(errorType == "LOGIN"){
        msg = "Could not access DB";
        level = WARNING;
    }else if(errorType == "DB"){
        msg = "Could not access DB";
    }else if(errorType == "UNKNOWN"){
        msg = "Something has gone wrong";
    }
    logAtLevel(logLevel, msg);
    displayInPopup(msg);
    if(errorType != "LOGIN"){
        notify(errorType == "DB" ? "db-admin@foo.com" : "general-admin@foo.com")
    }
}

function showLoginError(){
    showError("LOGIN");
}

function showDbError(){
    showError("DB");
}

function showUnknownError(){
    showError("UNKNOWN");
}

他们应该有独立的部分函数来改变并从函数中提取它们,但相反,他们用“模式”(或有时是布尔标志)创建了一个函数。

函数的模式通常在整个函数的多个位置进行检查,以隐式设置变量和/或确定函数的哪些部分执行。虽然他们已经摆脱了复制粘贴的代码,但他们在其位置添加了一种特殊的意大利面条代码。

我已经看过很多次了,现在我认为它必须有一个名字。

附:如果还没有,我会考虑“Rotini Code”,因为它就像意大利面条,但它有 3 种不同的颜色混合在一起。

【问题讨论】:

    标签: anti-patterns


    【解决方案1】:

    是的,这是 RTTI = 运行时类型信息。通常是代码异味,有时不是。

    通常这是一种代码异味,应该用多态性代替,例如Do polymorphism or conditionals promote better design?

    顺便说一句,Java 枚举的功能更像枚举类的子类,因此您可以避免编写大量打开枚举的函数。但这并不总是可以避免的(例如,当一个不能向枚举添加方法的类必须向枚举添加自己的方法时)。

    【讨论】:

    • 这不是我真正想要的。 RTTI 是 C++ 特定的语言功能,允许在运行时嗅探类型信息。在一般计算机科学术语中,这称为反射。我的例子根本不涉及类型,只是独立的函数。类型信息真的没有。
    • @PsyWolf 您可以将其称为 DIY-RTTI,因为您只是在编写自己的与语言无关的样板来实现 C++ 提供的功能。取自这里的术语stackoverflow.com/questions/234458/…,这是一个专门关于这种(经常)反模式的问题。
    猜你喜欢
    • 2010-09-09
    • 1970-01-01
    • 2010-11-21
    • 2012-04-19
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多