我正在研究模式和反模式。我对模式有一个清晰的认识,但我没有反模式。网络和维基百科的定义让我很困惑。
有人能用简单的话向我解释一下反模式是什么吗?什么目的?他们在做什么?这是坏事还是好事?
答案 0 :(得分:196)
Anti-patterns是软件开发中被认为是错误的编程实践的某些模式。
与design patterns相反,God object是常见问题的常见方法,这些问题已经形式化并且通常被认为是一种良好的发展实践,反模式则相反,是不可取的。
例如,在面向对象的编程中,我们的想法是将软件分成称为对象的小块。面向对象编程中的反模式是design patterns,它执行许多功能,可以更好地分成不同的对象。
例如:
class GodObject {
function PerformInitialization() {}
function ReadFromFile() {}
function WriteToFile() {}
function DisplayToScreen() {}
function PerformCalculation() {}
function ValidateInput() {}
// and so on... //
}
上面的示例有一个对象所有。在面向对象的编程中,最好为不同的对象定义明确的职责,以使代码保持较少的耦合并最终更易于维护:
class FileInputOutput {
function ReadFromFile() {}
function WriteToFile() {}
}
class UserInputOutput {
function DisplayToScreen() {}
function ValidateInput() {}
}
class Logic {
function PerformInitialization() {}
function PerformCalculation() {}
}
最重要的是,有很好的方法来开发具有常用模式的软件({{3}}),但也有开发和实施软件的方法可能会导致问题。被认为是不良软件开发实践的模式是反模式。
答案 1 :(得分:46)
每当我听到反模式时,我都会回忆起另一个词。设计气味。
“设计气味是设计中的某些结构,表明违反基本设计原则并对设计质量产生负面影响”。(摘自“重构软件设计嗅觉:管理技术债务”)
根据违反设计原则分类的设计气味很多:
抽象气味
缺少抽象:当使用数据块或编码字符串而不是创建类或接口时会出现这种气味。
势在必行的抽象:当一个操作变成一个类时会出现这种气味。
不完全抽象:当抽象不完全支持互补或相互关联的方法时,会产生这种气味。
多方抽象:当一个抽象分配了多个职责时,会产生这种气味。
不必要的抽象:当在软件设计中引入实际不需要(因此可以避免)的抽象时,就会出现这种气味。
未使用的抽象:当抽象未被使用(未直接使用或无法访问)时会出现这种气味。
重复抽象:当两个或多个抽象具有相同的名称或相同的实现或两者兼而有之时,会出现这种气味。
封装气味
缺陷封装:当一个或多个抽象成员的声明可访问性比实际需要更宽松时,就会出现这种气味。
漏洞封装:当抽象通过其公共接口“暴露”或“泄露”实现细节时,会产生这种气味。
缺少封装:当实现变体没有封装在抽象或层次结构中时,就会出现这种气味。
Unexploited Encapsulation:当客户端代码使用显式类型检查(使用链式if-else或switch语句检查对象的类型)而不是利用已封装类型的变化时,会出现这种气味在层次结构中。
模块化气味
破碎的模块化:当理想情况下应该已经本地化为单个抽象的数据和/或方法被分离并分散在多个抽象中时,会产生这种气味。
模块化不足:当存在尚未完全分解的抽象时,会出现这种气味,进一步的分解可能会减小其大小,实现复杂性或两者兼而有之。
循环相关的模块化:当两个或多个抽象直接或间接相互依赖时(在抽象之间建立紧密耦合),就会出现这种气味。
Hub-like Modularization:当抽象具有大量其他抽象的依赖关系(传入和传出)时,就会出现这种气味。
层次结构气味
缺少层次结构:当代码段使用条件逻辑(通常与“标记类型”结合使用)来显式管理可以创建层次结构并用于封装的行为变化时,会出现这种气味那些变化。
不必要的层次结构:当整个继承层次结构不必要时会出现这种气味,表明继承已经不必要地应用于特定的设计上下文。
Unfactored Hierarchy:当层次结构中的类型之间存在不必要的重复时,会出现这种气味。
宽层次结构:当继承层次结构“太宽”时,会出现这种气味,表明可能缺少中间类型。
推测层次结构:当推测性地提供层次结构中的一种或多种类型时(即基于想象的需求而非实际需求),就会产生这种气味。
深层次结构:当继承层次结构“过度”深时会出现这种气味。
叛逆的层次结构:当子类型拒绝其超类型提供的方法时会出现这种气味。
破碎的层次结构:当超类型及其子类型在概念上不共享“IS-A”关系导致可替代性被破坏时,会产生这种气味。
多路径层次结构:当子类型直接或间接地从超类型继承而导致层次结构中不必要的继承路径时,会出现这种气味。
循环层次结构:当层次结构中的超类型依赖于其任何子类型时,会出现这种气味。
"Refactoring for software design smells: Managing technical debt“中描述了上述定义和分类。可以找到一些更相关的资源here。
答案 2 :(得分:33)
模式是如何解决某个类问题的想法。反模式是如何不解决它的想法,因为实现这个想法会导致糟糕的设计。
一个例子:“模式”将使用函数进行代码重用,“反模式”将使用复制粘贴。两者都解决了同样的问题,但使用函数通常会导致代码比复制粘贴更易读和可维护。
答案 3 :(得分:16)
反模式是一种不解决问题的方法。但还有更多内容:它也是一种在尝试解决问题时经常被看到的方式。
答案 4 :(得分:10)
如果您真的想学习AntiPatterns,请阅读 AntiPatterns 一书(ISBN-13:978-0471197133)。
在其中,他们定义“AntiPattern是一种文学形式,描述了一个常见的问题解决方案,产生明显的负面后果。”
因此,如果这是一个糟糕的编程习惯,但不是一个常见的 - 仅限于一个应用程序,一个公司或一个程序员,它不符合AntiPattern定义的“模式”部分。
答案 5 :(得分:9)
制造混乱的常见方法。例如,像god / kitchensink类(做所有事情)。
答案 6 :(得分:6)
就像使用设计模式一样,反模式也是一种模板和解决某个问题的可重复方式,但是在非最优和无效的情况下方式。
答案 7 :(得分:6)
反模式是设计模式的补充。反模式是在特定情况下不应使用的模板解决方案。
答案 8 :(得分:5)
有趣的是,解决问题的一种方法既可以是模式,也可以是反模式。 Singleton就是最好的例子。它将出现在两组文献中。
答案 9 :(得分:3)
今天,软件工程研究人员和从业者经常互换使用“反模式”和“嗅觉”这两个术语。但是,它们在概念上并不相同。维基百科的反模式条目表明反模式至少有两个因素与不良做法或坏主意不同。反模式是
"尽管如此,一种常用的过程,结构或行动模式 最初看起来是一个适当和有效的回应 问题,通常会产生比有益结果更糟糕的后果。“
它清楚地表明,选择反模式是因为它认为它是一个很好的解决方案(作为一种模式)来解决所提出的问题;然而,它带来的负债多于利益。另一方面,气味只是一种不良做法,会对软件系统的质量产生负面影响。例如,Singleton是一种反模式,而God class(或Insufficient Modularization)则是一种设计气味。
答案 10 :(得分:2)
反模式是人们倾向于以错误方式编程的常见方式,或者至少是不太好的方式。
答案 11 :(得分:0)
任何对给定软件开发环境造成弊大于利的设计模式都将被视为反模式。
一些反模式是显而易见的,但有些不是。例如Singleton,即使很多人认为它是旧的设计模式,但还有其他人不喜欢。
您可以查看问题What is so bad about singletons?,以便更好地了解问题的不同意见。
答案 12 :(得分:0)
就像在算法中一样,您可以使用蛮力实现解决方案,但是如果情况变得复杂,则必须付出很多代价。
答案 13 :(得分:0)
当您以非法方式滥用设计模式,或者您不知道其实际用法时,有时会使用它。例如,具有用于简单类的构建器模式,或为您在代码中使用的每个Active类过分地定义一个单例实例。 也可能超出设计模式。例如,在Java中将局部变量定义为最终变量,或者当您可以简单地检查输入是否为null时对NullPointerException使用try / catch,或者在不使用对象后将它们清空(例如,使用其他语言)请注意有关垃圾收集机制的信息,或调用system.gc()来使内存为空,以及许多其他误解,这些误解很可能被认为是“货邪教”现象。
答案 14 :(得分:0)
在基于微服务的区域:
除数据外,所有内容都是微细的是反模式。 这意味着,如果一切都分解合理且完全基于DevOps和CI / CD。也许某些分布式设计模式已经到位,甚至可以完全复制,但是所有服务背后都有一个巨型数据存储,因此它仍然是一个整体的数据结构。