关于术语:什么是反模式?

What is an anti-pattern?

我正在研究模式和反模式。我对模式有一个清晰的概念,但我没有反模式。网络和维基百科的定义让我很困惑。

有人能用简单的话向我解释什么是反模式吗?目的是什么?他们做什么?是坏事还是好事?


反模式是软件开发中被认为是坏编程实践的某些模式。

与设计模式不同的是,设计模式是解决常见问题的常用方法,这些常见问题已经正式化,通常被认为是一种良好的开发实践,而反模式则是相反的,是不可取的。

例如,在面向对象编程中,其思想是将软件分成称为对象的小部分。面向对象编程中的反模式是一个执行许多功能的上帝对象,这些功能可以更好地分为不同的对象。

例如:

1
2
3
4
5
6
7
8
9
class GodObject {
    function PerformInitialization() {}
    function ReadFromFile() {}
    function WriteToFile() {}
    function DisplayToScreen() {}
    function PerformCalculation() {}
    function ValidateInput() {}
    // and so on... //
}

上面的示例有一个执行所有操作的对象。在面向对象编程中,最好对不同的对象有明确的职责,以使代码更少地耦合,最终更易于维护:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class FileInputOutput {
    function ReadFromFile() {}
    function WriteToFile() {}
}

class UserInputOutput {
    function DisplayToScreen() {}
    function ValidateInput() {}
}

class Logic {
    function PerformInitialization() {}
    function PerformCalculation() {}
}

归根结底,开发具有常用模式(设计模式)的软件有很好的方法,但也有开发和实现软件的方法,这些方法会导致问题。被认为是不好的软件开发实践的模式是反模式。


每当我听说反模式,我就会想起另一个术语,即。设计气味。好的。

"设计气味是指设计中的某些结构违反了基本设计原则,对设计质量产生负面影响"。(摘自《软件设计重构气味:管理技术债务》)好的。

有许多设计气味是根据违反设计原则分类的:好的。

提取气味好的。

缺少抽象:当使用数据块或编码字符串而不是创建类或接口时,就会产生这种气味。好的。

命令抽象:当一个操作变成一个类时,就会产生这种气味。好的。

不完全抽象:当抽象不完全支持互补或相互关联的方法时,就会产生这种气味。好的。

多面抽象:当一个抽象有多个职责分配给它时,就会产生这种气味。好的。

不必要的抽象:当在软件设计中引入一个实际上不需要的抽象(因此可以避免)时,就会产生这种味道。好的。

未使用的抽象:当抽象未被使用(不是直接使用,就是不可到达)时,就会产生这种气味。好的。

重复抽象:当两个或多个抽象具有相同的名称、相同的实现或两者都有时,就会产生这种气味。好的。

封装气味好的。

封装不足:当一个抽象的一个或多个成员声明的可访问性比实际需要的更为允许时,就会出现这种气味。好的。

泄漏封装:当抽象通过其公共接口"公开"或"泄漏"实现细节时,就会产生这种气味。好的。

缺少封装:当实现变化没有封装在抽象或层次结构中时,就会出现这种味道。好的。

未利用的封装:当客户端代码使用显式类型检查(使用检查对象类型的链接if else或switch语句)而不是利用已经封装在层次结构中的类型的变化时,就会产生这种气味。好的。

模块化气味好的。

打破模块化:当数据和/或方法(理想情况下应该被本地化为单个抽象)被分离并分布在多个抽象中时,就会产生这种味道。好的。

模块化不足:当存在尚未完全分解的抽象时,就会产生这种味道,进一步的分解可能会减小其大小、实现复杂性,或者两者兼而有之。好的。

循环依赖的模块化:当两个或多个抽象直接或间接地相互依赖(在抽象之间创建紧密耦合)时,就会产生这种气味。好的。

类似于中心的模块化:当一个抽象与大量其他抽象有依赖关系(传入和传出)时,就会产生这种味道。好的。型

层次结构气味好的。型

缺少层次结构:当代码段使用条件逻辑(通常与"标记类型"结合使用)显式地管理行为的变化时,就会产生这种味道,在这种情况下,可以创建层次结构并用于封装这些变化。好的。型

不必要的层次结构:当整个继承层次结构是不必要的时,就会产生这种味道,这表明继承已经不必要地应用于特定的设计上下文。好的。型

无系数层次:当层次中的类型之间存在不必要的重复时,就会产生这种气味。好的。型

宽层次结构:当继承层次结构"太宽"时会出现这种味道,表示可能缺少中间类型。好的。型

推测层次:当一个层次中的一个或多个类型被推测地提供时(即基于想象的需求而不是真实的需求),就会产生这种气味。好的。型

深层次层次:当继承层次"过度"深层次时,就会产生这种味道。好的。型

叛逆层次:当子类型拒绝其父类型提供的方法时,就会产生这种气味。好的。型

破坏的层次结构:当一个超类型及其子类型在概念上不共享一个"is-a"关系时,就会产生这种味道,从而导致破坏的可替换性。好的。型

多路径层次结构:当一个子类型直接继承或者间接继承一个超类型,从而导致层次结构中不必要的继承路径时,就会产生这种味道。好的。型

循环层次:当层次中的父类型依赖于它的任何子类型时,就会产生这种气味。好的。型

上述定义和分类在"软件设计重构气味:管理技术债务"中进行了描述。这里可以找到一些更相关的资源。好的。型好啊。


模式是如何解决某个类的问题的概念。反模式是一个如何不解决它的想法,因为实现这个想法会导致糟糕的设计。

例如:"模式"将使用一个函数来重用代码,"反模式"将使用复制粘贴来重用代码。两者都解决了相同的问题,但是使用一个函数通常会导致比复制粘贴更易于阅读和维护的代码。


反模式是解决问题的一种方法。但它还有更多的意义:它也是一种在尝试解决问题时经常看到的方法。


如果您真的想学习反模式,请阅读《反模式》(ISBN-13:978-0471197133)。

在这本书中,他们定义了"反模式是一种文学形式,它描述了一个常见的问题的解决方案,该问题会产生明显的负面后果。"

因此,如果这是一个糟糕的编程实践,但不限于一个应用程序、一个公司或一个程序员,那么它不符合反模式定义的"模式"部分。


一种常见的制造混乱的方法。例如,像上帝/厨房用品类(什么都做)。


反模式是设计模式的补充。反模式是在特定情况下不应该使用的模板解决方案。


就像设计模式一样,反模式也是解决某个问题的模板和可重复的方法,但不是最优和无效的方法。


有趣的是,给定的解决问题的方法既可以是模式,也可以是反模式。单例是这方面的主要例子。它将出现在两套文献中。


如今,软件工程研究人员和实践者经常交替使用"反模式"和"气味"这两个术语。然而,它们在概念上并不相同。维基百科的反模式条目指出,反模式至少有两个因素不同于坏的实践或坏的想法。反模式是

"A commonly used process, structure or pattern of action that despite
initially appearing to be an appropriate and effective response to a
problem, typically has more bad consequences than beneficial results."

它清楚地表明,反模式的选择是基于这样一种信念,即它是对所提出问题的一个很好的解决方案(作为模式);然而,它带来的负债多于收益。另一方面,气味只是一种不好的做法,会对软件系统的质量产生负面影响。例如,singleton是一种反模式,而god类(或模块化不足)是一种设计风格。


反模式是人们通常采用的错误编程方式,或者至少是不太好的编程方式。


任何对给定的软件开发环境有害的设计模式都将被视为反模式。

有些反模式是明显的,但有些不是。例如单例,尽管许多人认为它是好的旧设计模式,但也有其他人不这么认为。

你可以检查一下这个问题单件的坏处是什么?更好地理解对它的不同意见。