程序员经常注意到他在一些地方有一些非常相似的代码。可以说这里有类似代码的实例。 (这是一个明确的玩具示例。在野外,这种反模式通常不会在代码上发生这么简单)
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");
}
它们应该具有隔离的部件功能,可以改变它们并将它们从功能中提取出来,但相反,它们使用"模式" (或者有时是布尔标志)。
通常在整个函数的几个位置检查函数模式以隐式设置变量和/或确定函数的哪些部分执行。虽然他们已经摆脱了复制粘贴的代码,但他们已经添加了一种特殊的意大利面条代码。
我已经看够了这么多次,因为我认为必须有一个名字。
P.S。如果一个人不存在,我会思考" Rotini Code"因为它像意大利面,但它有3种不同的颜色混合在一起。
答案 0 :(得分:0)
是的,这是RTTI =运行时类型信息。通常是代码味道,有时不是。
通常它是代码味道,应该用多态性替换,参见例如Do polymorphism or conditionals promote better design?
另外,Java枚举功能更像是枚举类的子类,因此您可以避免编写许多打开枚举的函数。但它并不总是可以避免的(例如,当一个不能向枚举添加方法的类必须将自己的方法添加到枚举时)。