什么时候devise模式而不是解决scheme?

我从来没有在需要使用devise模式的软件上工作。 根据Paul Graham的“书呆子的复仇 ”,devise模式是没有足够抽象的标志。

直接引用他的话:“例如,在面向对象的世界里,你听到很多关于”模式“的事情。 我不知道这些模式是否有时不是案例(c),人类编译器,在工作中的证据。 当我在程序中看到模式时,我认为这是麻烦的迹象。 程序的forms应该只反映需要解决的问题。 代码中的任何其他规则对我来说都是一个标志,至less我使用的是不够强大的抽象 – 通常我手工生成了一些我需要编写的macros的扩展。

我只是想知道如果每个人都认为devise模式是过度使用,并没有足够的抽象在您的代码的症状。

我不认为模式本身就是问题,而是开发者可以学习模式,然后使用它们,或者以非常不合适的方式应用它们。

模式的使用是有经验的程序员自然学习的东西。 你已经多次解决了一些问题,你知道什么方法有效,你使用这种方法,因为你的技能和经验告诉你这是适当的。 这是一个模式,没关系。

但是,对于一个不太熟练的程序员来说,find一种办法去做事情,并且试图将每一个他们遇到的问题都塞进这个模子里,因为他们不知道任何其他的方式。 这也是一种模式,它是邪恶的。

来吧,请阅读整个报价,仔细阅读。 或者更好,阅读这篇文章。

除此之外,Paul Graham批评C语言没有提供足够的抽象手段。 在文章的范围内,他对模式的批评是事后的,或者说是他主要论点的一个切入点。 他的推理是这样的:

使用常用策略来解决经常性问题是合乎逻辑的。 在真正的抽象语言中,可以将这些策略forms化,并将它们放到一个库中。 每当你需要使用它们时,你只需#包括它们,实例化它们,扩展它们,或者其他任何东西。 相比之下,类C语言不提供必要的抽象手段。 这是由“模式”存在的事实所见证的。 模式是一种常用的策略,不能用库代码来表示,因此每次应用时都必须明确地写出模式。

保罗·格雷厄姆并不认为这些模式本身就是邪恶的。 它们是提供抽象手段的语言的一个症状。 在这方面,他几乎肯定是对的。 因此,我们是否应该使用不同的语言,当然是另一个讨论。

另一方面,这个问题的原始海报是错误的:模式不是“代码中没有足够抽象的症状”,而是语言中没有足够抽象手段的症状。

模式实际上只是描述事情如何运作的一种方式。 这是一个分类的方法。 有一些过度使用它们的程序吗? 当然。 具有模式的最大优点是,通过将事物分类为这样或那样,每个人都在同一个页面上(假设他们具有知识水平以知道正在讨论的内容)。 当你有一个有10,000行代码的系统时,有必要能够快速确定事情将如何工作。

这是否意味着你应该总是使用模式,不。 这将导致问题,迫使事物分类,但你也不应该回避他们。

程序的forms应该只反映需要解决的问题。

当需求发生变化,你的模块不是用Facade或潜在的Mediator抽象出来的时候,会发生什么情况?

devise模式是没有足够抽象的标志

很有可能,如果你把所有的东西都抽象出来,那么你就有一个devise模式。

如果有一个非常“沉重”的对象,不需要加载? 代理模式可以使用户永远不会等待。

我可以继续,但我想我已经说得够了。 devise模式是正确使用的好工具。 问题出现在他们使用不当时,但我想这就是为什么误用模式被称为反模式。

我对模式的一个问题是,这个概念的核心似乎存在一个核心谎言:如果你能以某种方式对专家编写的代码进行分类,那么任何人都可以通过识别和机械地应用类别来编写专家代码。 这对pipe理者来说听起来很棒,因为专家级软件devise师相对来说比较less

问题是这不是真的。 你不能只用“devise模式”来编写专业品质的代码,而只能使用缝纫模式来devise你自己的专业时装devise师品质的服装。

我相信Paul Graham的这段话很重要:

[…]我使用的是不够强大的抽象 – 我常常手动生成一些我需要编写的macros的扩展[…]

它表明,如果你可以用你的语言来build立这些抽象(你可以用Lisp来做几乎所有的事情,这也许正是他想要的),但是你不需要用模式对它们进行build模。

但是并不是每个人都使用Lisp,所以你只能在可能的地方build立抽象,并在不能使用的地方使用模式。 作为一个例子,在没有高阶函数的语言中,这些语言通常使用战略模式进行build模。

这似乎是你如何看待它的问题:模式可以被看作是一个问题的症状(例如缺乏高阶函数),或者作为问题的一个解决scheme(例如,使得像高阶function可能通过战略模式)。

[叹气]在人们开始使用自己的判断之前,我们有多less次反对良好的做法呢?

简单的回答:如果你用面向对象的语言做了真正的工作,那么很有可能你已经实现了一些GoFdevise模式来完成工作。 无论你是否意识到你做了这件事,都是一个教育,观点和内省的问题。 否认你曾经做过这样的事情,或者这种模式不存在或者不是“必要的”或者“过度使用”是荒谬的 – 除非你从来没有写过比'hello world'更复杂的东西;-)

为什么呢,就在那一天,我不得不为一个单身人士实现一个访问者门面,只是为了让适配器策略正常工作:-P

“devise模式”这个术语超载和混乱。

有一个狭义的思考方式:基本上作为GoF书中列出的面向对象概念的集体名称,例如Singleton,Facade,Strategy。 如果您将“devise模式”作为您的简历上的权限,则可能使用此定义。

一个项目可以很容易地包含数十个单例对象。 这种模式相当明显地受益于被编码为可实例化的抽象,例如作为macros或抽象类。 对于GoF书中的许多其他模式也是如此。

在我看来,保罗·格雷厄姆的论点是:devise模式作为重复自己的标准方法,应该被编码为可实例化的抽象,并且推论你应该使用一种具有非常灵活的方式来定义可实例化的抽象的语言。

但是这个概念更普遍 – 我认为他误导了devise模式。 克里斯托弗·亚历山大(Christopher Alexander)发明了这个概念,以便将其应用于国家,城市,城镇和房屋的devise。 游戏devise师有模糊的语言,如战争的雾,不对称的能力,等等​​。

从这个一般意义上来说,devise模式应该都被编码为可实例化的抽象变得不太明显。

如果您还没有阅读“模式语言”,请在此处查看其范围。 想象一下这样的软件世界。 GoF模式将会在ToC的最底层:它们是实现细节。

你可以在上面find其他什么样的模式?

我想一个章节会有游戏相关的模式。 它可以同时包含游戏devise模式和实现技术,并且我认为这不是一个明确的区别 – 就像游戏循环,世界实体,空间哈希,高程地图等等。 这些都是devise模式。

现在,在一个游戏项目的范围内,你可能只有一个世界实体的实现。 任何使用任何语言工作的人都有理由把这个世界实体作为一个基类实例化的抽象。

但是这个模式描述的是这个抽象是如何形成的:它包含了一些位置的概念,它是可以渲染的,等等。 这种devise模式本身是否会从被编码为macros或抽象类中受益尚不明确 – 该模式已经描述了一种抽象! 你会为世界实体实现一个元类吗? 用于定义世界实体类的macros,以及各种不敬虔的参数?

进一步看想象的目录,我们看到这些模式从属于一个更一般的模式,即游戏的模式。 这是值得作为macros观或抽象类编码? 也许。 但不是很明显。 我们正在讨论一个游戏框架,在这个框架中,通过传递参数来定义一个电脑游戏,填补空白等等。这可能是有效的和有趣的,但它不是唯一的方法去做事情。

Erlang平台像服务器一样具有可实例化的模式抽象,这很酷。 我猜Erlang项目有一个Java项目有单身人士的服务器。

但是为了你的特定目的,如果你正在使用Lisp或者Haskell,或者其他的东西,并且写一个服务器,有时候只要遵循Server模式就足够了,把它作为老的函数和对象来实现,而不需要尝试实例化整个事物的抽象。

所有devise模式都不是源代码中的低级文本模式。

我认为保罗·格雷厄姆在这一场比赛中错过了大好时光。 使用模式不是拿起一本列出它们的书,而是将它们应用到你的代码中。 我会同意这将是一个糟糕的select,但这不是什么模式。

devise模式只是一种识别“嗨,我认识到这与我以前解决的另一个问题类似”的方法,并且正在学习如何创build抽象的解决scheme,以便适用于适当的情况。

事实上,如果你已经编程了任何合理大小的任何东西,你可能已经使用了众所周知的devise模式,只是不知道它的名字。 比如,在我有任何线索的时候,我就使用了“工厂”模式很久了,那是一个“工厂”。 知道它所谓的正式只是防止我再次重新发明轮子。

确定一些众所周知的模式是有点蹩脚的; 单身是绝对可疑的。 但那是一个明智的解决scheme,一个过于聪明的解决scheme寻找一个问题来解决,而不是做得很好。 但是,这就是为什么你可以find许多赞成和反对的文献 – 因为人们认识到这可能不是一个好的解决scheme。

但是整体模式是一件非常好的事情,如果他们鼓励抽象的话。

我相信保罗·格雷厄姆的主张是devise模式应该用语言来expression。 如果有一个X模式,那就意味着人们被迫重写代码序列来完成它,并且应该有一种语言特定的expression方式。 这可以被构build到语言中(尽pipe这很笨拙,并且可以创build新的devise模式),或者它可以在语言中自动化(例如Common Lispmacros; C ++模板,特别是当以奇怪方式使用时,可以做同样的事情有时)。

例如,让我们考虑一个更简单的模式:递增循环。 不得不在一个序列中的每个元素上做一些事情是相当普遍的,如果我们没有对应于for语句的东西,我们无疑会采用一些通用的编码惯例来expression它,而有人(或者一些人)会把它们打包在一起与其他类似的基本构念,并写一本关于它的书。

同样,如果使用工厂模式,一种语言可能包含一个工厂function,或者可能在该语言中自动执行它。 具体来说,Paul希望能够编写一个Lispmacros来实现它,而不是一次又一次地写出工厂本身。

使用devise模式的危险在于它是我们不断input的熟悉的代码框架,因此我们有大量的代码,我们倾向于不仔细阅读和编写代码。 不便的是,他们是我们必须一次又一次地input的代码,以及重写真的应该被自动化的感觉。

无论模式是使用语言的基本部分,就像GoF所说,或者可以被抽象出来,就像PG所说的那样,基本上是一个经验问题,可能通过寻找语言模式本身是不必要的,并观察它们是否是最好的真的需要新的模式。

devise模式的定义如下(从维基百科,但我也读过一些相同的书)

在软件工程中,devise模式是软件devise中常见问题的通用可重用解决scheme。 devise模式不是可以直接转换成代码的完成devise。 这是如何解决可以在许多不同情况下使用的问题的描述或模板。

如果考虑从偏移量直接应用模式而不进入问题领域,可能会导致问题。 使用devise模式作为指导或更多,作为提示/提示来解决问题。 有效应用的devise模式肯定不会给出足够抽象的解决scheme。 通常可以看到,在企业软件中,使用了一些变种或几种devise模式的组合。混合种类。 如果你说你从来没有使用过devise模式,那么你会很高兴知道像foreach循环是一个interator模式,你可以在你附近寻找更明显的实现!

简而言之,模式只是解决各种语言中常见任务的forms化方式。 因此,甚至在有人提出这个术语之前就有“devise模式”。 每种语言都有“最佳实践”,而devise模式就是这样 – 一套定期发生的问题的最佳实践。

标注模式的主要好处之一是共享术语允许我们谈论抽象的概念。

很明显,devise模式在任何给定的环境中都可能被误用或过度使用,但是我真的不明白devise模式作为一个概念是如何成为问题的。

有一个时间和地点的一切。 我曾经看过有太多模式的代码,这些模式会同意你的观点,但也没有足够的模式,使得代码在进行更改时很难维护和容易出错。

把这样的概念推广到逻辑上是有缺陷的,但是如果把你的问题改为“可以有太多的代码模式,这是一个更大的问题的症状,也就是抽象层次不够”的话,那么答案是肯定的。 情况总是如此吗? 没有。

当我在LISP中编程时,我根本没有使用GoF的devise模式,只是不适用于我正在编写的程序。 现在我正在用C#编程,并且在devise模式实际上简化了正在编写的程序的情况下运行。

我们使用了很多格言(以及其中常见的格言),如果将它们追溯到源头,最初是有保留的; 如“…当你正在开发使用…”这是其中的一种情况。 当你在做OOP时,模式很好。 YMMV当你在另一个范例。

“重构”是另一个类似的情况。

当我编写SQL时,我的大脑的“模式”部分closures。

请注意你的引用:“我手工生成了一些我需要写的macros的扩展”。 所以他认识到模式,并将它们抽象成一个macros观 – 他不会以另一种方式重新编码。 只是好醇“干。 这不是模式,它没有做我们发现的正确的事情。 我会说他的评论可以进入任何维基条目,扩大DRY的美德,以及如何拥有它们。 GoF会完全同意 – 识别devise模式,然后使用你所知道的来适当地实现(或重构)它们。

在我的程序的devise阶段,我经常首先分解这个问题 ,一旦把它分解了,我就可以很容易地开始识别devise中固有的模式。 在这一点上,我可以开始应用知名的devise模式,以便在交stream或实现devise时,我可以使用通用语言进行通信,并希望我可以重用一些通用对象,这些对象是以前在执行类似的模式期间执行。

很多时候,当devise模式被不正确地应用时,这是因为这个过程是相反的。 程序员Joe(我向你们这些名为Joe的道歉)读了一本关于Design Patterns的书,并说:“好吧,我理解Design Pattern X,现在该如何将它应用到我的应用程序中? 这是错误的。

devise模式可能是一个强大的武器,但是与其他任何东西一样,它们应该被恰当地使用,程序员也应该随时准备将一些原创的思想融入到他的devise中。

我认为有时当你学习一个模式时,你不仅仅学习模式。 但是,您对问题领域有了一个新的看法,而您以前可能从来没有这样做过。 也许它正是你想要的。

没有“问题”的背景,我们不能说devise模式是否是解决scheme。

从来没有需要使用devise模式 – 您可以随时编写代码,忽略了编码到目前为止所了解的所有内容,甚至可能工作。 但devise模式可以让事情变得更简单,为您提供讨论devise的共享语言。

Diesign模式并不代表太less的抽象 – 它们是尝试提高抽象级别。 你可以说“这个位是一个访问者”而不是“这里是一些recursion遍历对象树的代码,对它们进行操作”。

如果不是解决scheme,模式就是问题。 我的意思是:如果为模式而引入模式,而不是解决应用程序中真实存在的devise问题,则很可能会导致问题而不是解决或阻止它们。
我一直在工作中告诉人们,“四人帮”(Design Patterns:可重用面向对象软件的元素)是一本参考书,而不是一本好devise的手册。

是的,pg就在那里。 如果您在整个应用程序中看到类似的代码,则意味着您缺less该代码的抽象。 代码越less越好。

这里是关于这个主题的另一篇文章: http : //blog.plover.com/prog/design-patterns.html

我宁愿用太多的模式工作。 这就是说,适当的平衡当然是目标。

这句话没有意义: devise模式是没有足够抽象的标志由于devise模式一个抽象! 在这里的答案我同意,编程语言应该有一种方式来expressiondevise模式。 但是,对于每一种情况来说显然都是不可能的

我记得有一次对GoF的一次采访,有人问到关于devise模式是替代语言中缺less的function的工具的常见说法。 作者认为,A)任何语言都有devise模式(不相同的),因为devise模式是为了解决语言特质而devise的工具,B)通过向语言添加更多function来摆脱他们的需求是不可行的。

devise模式是常见问题的解决scheme。

但首先,你需要知道问题在哪里或哪里。 这就是人们无法正确使用模式的地方。

我还没有在我的代码中findGoF“Design Patterns”的用法。 代码似乎已经locking在GoF的书上,现在大多数公司已经知道他们的应用了。 就在今天我接受了一个采访,被问到我知道和使用了哪些模式,以及我将如何将它们应用于大型银行的企业应用程序。

从我们以前的项目学习的一般想法显然是有道理的。 没有任何意义的是对特定的GoF模式的炒作和崇拜,人们把它们误认为好的编码实践,并期望爱和拥抱他们,以称为有能力的开发者。

所以要回答你的问题,我想说devise模式的GoF理念被大多数人误解和滥用。 我们需要成熟的devise模式的更高层​​次的使用作为一种学习工具,适用于我们学习和改进面向对象的方式,而不仅仅是为了记住和强加于程序。 没有银弹。

编程语言,如口头语言,为您提供所需的词汇。 模式只是描述一种方式来让人们知道你在更高层次上谈论什么。

如果你放纵我一个比喻:写音乐是一个常见的“问题”,音乐经常(显然不总是)松散地组成,作为以下的一些变化:

诗歌合唱诗歌合唱诗歌合唱合唱

这确实是一个“模式”。 你仍然需要写歌,但不是每一首歌都能很好的使用这种模式。

我试图得到的一点是,模式不是一个即插即用完成的编程或音乐解决scheme。 他们是一个准则,让你开始和跳板,你可以做出适合你的需要的东西。