关于语言不可知:成语与模式

Idiom vs. pattern

在编程环境中,习语与模式有何不同?

我可以互换使用这些术语,并且通常遵循我听到过的最流行的方式,或者在当前对话中最新的方式,例如"复制交换习语"和"单件模式"。

我能想到的最好的区别是代码,这意味着要复制几乎字面上更经常被称为模式,而代码意味着要采取较少字面上更经常被称为习语,但这并不总是真的。这似乎只是一个风格或流行词的差异。这是否符合你对如何使用这些术语的理解?语义上有区别吗?


习语是语言特有的。

模式是独立于语言的设计原则,通常用"模式语言"(统一模板)编写,描述诸如激励环境、利弊和相关模式等内容。


当人们从高处观察程序开发时(分析师、顾问、学者、方法论专家等),看到开发人员在不同的情况和环境中一遍又一遍地做同样的事情,那么从观察中获得的智能就可以被提炼成一种模式。模式是一种使用手边的软件工具"做事情"的方式,它表示一个公共的抽象。

一些例子:

  • OO编程从开发人员那里带走了全局变量。对于那些仍然需要全局变量,但需要一种使其使用看起来干净和面向对象的方法的情况,这里有singleton模式。

  • 有时,根据某些情况,您需要创建一个新对象,该对象具有多种可能的不同类型之一。一个丑陋的方式可能涉及一个不断扩大的case声明。通过"工厂"或"工厂方法"模式,以OO清洁方式实现这一点的公认"优雅"方式。

有时,很多开发人员以某种方式做事情,但这是一种不好的方式,应该受到不尊重。这可以在反模式中形式化。

模式是一种高级的做事方式,大多数模式是独立于语言的。无论是使用new Object还是Object.new创建对象,都与模式无关。

因为模式有点理论化和形式化,所以通常会有一个形式化的模式(heh-words overload!)让我们说"模板")来描述它们。此类模板可包括:

  • 名字
  • 效果达到
  • 理论基础
  • 限制和限制
  • 如何做到这一点

习语是一个较低层次的东西,通常在语言层次上操作。例子:

1
*dst++ = *src++

在C语言中,将数据元素从src复制到dst,同时增加指向两者的指针;通常在循环中完成。显然,你不会在Java或对象Pascal中看到这个习语。

1
while <INFILE> { print chomp; }

是(从内存中大致引用的)Perl习惯用法,用于循环输入文件并打印出文件中的所有行。在那个语句中有很多隐式变量的用法。同样,除了在Perl中,您不会在任何地方看到这种特殊的语法;但是一个老的Perl黑客会快速查看语句并立即识别您正在做的事情。


与模式是语言不可知论的观点相反,PaulGraham和PeterNorvig都认为需要使用模式是您的语言缺少特性的一个标志。(访客模式通常被选为最明显的例子。)

我一般认为"模式"和"习语"的主要区别是大小不同。习惯用法是一些小的东西,比如"为保存集合的变量类型使用接口",而模式往往更大。我认为成语的小意味着它们更具体的语言(我刚才给出的例子是一个Java习语),但我不认为这是它们的定义特征。


因为如果你把5个程序员放在一个房间里,他们可能甚至不会就什么是模式达成一致,所以没有真正的"正确答案"。

有一种观点,我听过一次,并且非常喜欢(尽管我一辈子都记不起来它的来源),那就是成语可能是你的语言中的东西,或者是某种语言中的东西。相反,它们是我们使用的技巧,因为我们的语言没有为它们提供直接的原语。例如,Java中没有单子,但是我们可以通过隐藏构造函数并提供GETSimulink方法来模仿它。

另一方面,模式更像是语言不可知论者(尽管它们通常指的是特定的模式)。您可能有一些基础设施来支持它们(例如,MVC的Spring),但它们不是也不会是语言构造,而且您可能需要它们使用该范式中的任何语言。