我从未使用过需要使用设计模式的软件.根据保罗格雷厄姆的书呆子文章复仇,设计模式是抽象不够的标志.
直接引用他的话,"例如,在OO世界中,你会听到很多关于"模式"的信息.我想知道这些模式是否有时候是人类编译器在案例(c)的证据.当我在程序中看到模式时,我认为这是一个麻烦的迹象.程序的形状应该只反映它需要解决的问题.代码中的任何其他规律性至少对我来说是一个标志,我正在使用不够强大的抽象 - 通常是我手工生成我需要编写的某些宏的扩展."
我只是想知道是否每个人都认为设计模式被过度使用,并且是代码中没有足够抽象的症状.
我不认为模式本身就是问题,而是开发人员可以学习模式然后过度使用它们,或者以非常不合适的方式应用它们.
模式的使用是经验丰富的程序员自然学习的东西.你已经多次解决了一些问题X,你知道什么方法有效,你使用这种方法,因为你的技能和经验告诉你它是合适的.这是一种模式,没关系.
但对于一个技能较低的程序员而言,同样可能找到一种方法来做事并试图将他们遇到的每一个问题都塞进那个模型中,因为他们不知道其他任何方式.这也是一种模式,它是邪恶的.
来吧伙计们,请阅读整篇报价,仔细阅读.或者甚至更好,阅读文章.
除了其他方面,保罗格雷厄姆批评C语言没有提供足够的抽象方法.在文章的范围内,他对模式的批评是事后的想法,或者说是他主要论点的一个案例.他的推理是这样的:
使用通用策略来解决重复出现的问题是合乎逻辑的.在真正抽象的语言中,可以将这些策略形式化并将它们放入库中.每当你需要使用它们时,你只需#include它们,实例化它们,扩展它们,或者其他什么.相反,类C语言不提供必要的抽象方法.事实证明存在类似"模式"的事实.模式是一种常见的策略,不能由库代码表示,因此必须在每次应用时表达性地编写.
保罗格雷厄姆并不认为这些模式本身就是邪恶的.它们是提供抽象手段的语言不足的症状.在这方面,他几乎肯定是对的.我们是否应该因此使用不同的语言,当然是另一种讨论.
另一方面,问题的原始海报是错误的:模式不是"代码中没有足够抽象的症状",而是在您的语言中没有足够的抽象方法的症状.
模式实际上只是描述事物如何运作的一种方式.这是一种对它们进行分类的方法.是否有一些程序过度使用它们?当然.拥有模式的最大优点是,通过将某事物分类为这样或那样,每个人都在同一页面上(假设他们具有了解所谈论内容的知识水平.).如果您的系统具有10,000行代码,则必须能够快速确定某些内容的工作方式.
这是否意味着你应该总是使用模式,不.这将导致问题迫使事情进入分类,但你也不应回避它们.
模式的问题在于,概念的核心似乎是一个核心谎言:如果你能以某种方式对代码专家进行分类,那么任何人都可以通过识别和机制应用类别来编写专家代码.这对管理者来说听起来很棒,因为专业软件设计师相对较少.
问题是事实并非如此.你不能仅仅使用"设计模式"来编写专家级质量的代码,而只能使用缝纫图案设计自己的专业时装设计师品质的服装.
程序的形状应该只反映它需要解决的问题.
当需求发生变化并且您的模块未使用Facade或可能的Mediator进行抽象时会发生什么情况,从而使交换过于困难?
设计模式是抽象不够的标志
如果你已经正确地抽象出一切,那么你可能会在那里有一个设计模式.
如果有一个非常"重"的物体不需要加载怎么办?代理模式使用户无法永远等待.
我可以继续,但我想我已经说够了.正确使用时,设计模式是很好的工具.当问题被错误地使用时会出现问题,但我猜这就是误用模式被称为反模式的原因.
我相信Paul Graham引用的这一部分很重要:
[...]我正在使用不够强大的抽象 - 通常是我手工生成我需要编写的某些宏的扩展[...]
它表明,如果你能用你的语言构建这些抽象(并且你可以用Lisp做任何事情,这可能就是他上面所说的那样),你不需要用模型对它们进行建模.
但并不是每个人都使用Lisp,因此您只能在可能的地方构建抽象,并在不能使用的情况下使用模式.例如,在没有高阶函数的语言中,这些通常使用策略模式建模.
这似乎是你如何看待它的问题:模式可以被视为问题的症状(例如,缺乏高阶函数),或者作为问题的解决方案(例如,制作类似高阶的东西)通过策略模式可能的功能).
[叹气]在人们开始使用自己的判断之前,我们必须揭穿多少次反对良好做法的咆哮?
简短的回答:如果您使用面向对象的语言进行实际工作,那么很有可能您已经实现了一些GoF设计模式来完成工作.无论你是否意识到自己已经做到了这一点,都是教育,观点和内省的问题.否认你曾经做过这种或那些模式不存在或者不是"必要"或"过度使用"是荒谬的 - 除非你永远不会写任何比'hello world'更复杂的东西;-)
为什么,就在前几天我必须为单例实现访问者外观才能使适配器策略起作用:-P
"设计模式"一词过载且令人困惑.
有一种狭隘的方式可以考虑它:基本上作为GoF书中列出的OO概念的集体名称,例如Singleton,Facade,Strategy.如果您将"设计模式"作为简历的权限,则可能会使用此定义.
一个项目可以轻松包含数十个单例对象.这种模式显然受益于被编码为可实例化的抽象,例如,作为宏或抽象类.同样,对于GoF书中的许多其他模式也是如此.
在我看来,Paul Graham的论点是:设计模式,作为重复自己的标准方法,应该被编成可实例化的抽象,并且通过推论,你应该使用一种非常灵活的方法来定义可实例化的抽象.
但这个概念更为笼统 - 我认为他歪曲了设计模式.克里斯托弗亚历山大发明了这一概念,以便将其应用于国家,城市,城镇和房屋的设计.游戏设计师拥有类似Fog-of-War,Asymmetrical-Abilities等模式的语言.
在这个一般意义上,设计模式应该全部被编码为可实例化的抽象变得不那么明显.
如果您还没有阅读A模式语言,请在此处查看其范围.想象一下这个软件世界的东西.GoF模式将在ToC的底部向下:它们是实现细节.
你能在他们上面找到什么其他模式?
我猜一章会有与游戏相关的模式.它可以结合游戏设计模式和实现技术,并且我认为这不是一个明确的区别 - 比如游戏循环,世界实体,空间哈希,高度图景观等等.这些都是设计模式.
现在,在一个游戏项目的范围内,您可能只有一个World Entity实现.任何使用任何语言的人都有理由将这个World Entity作为基类的可实例化抽象.
但是模式描述的是这种抽象是如何形成的:它包含一些位置概念,它是可渲染的,等等.这种设计模式是否会从编码为宏或抽象类本身中获益并不明显 - 模式已经描述了抽象!你会为世界实体实现制作元类吗?用于定义世界实体类的宏,具有各种不正确的参数?
进一步查看虚构的目录,我们看到这些模式从属于更一般的模式,即游戏模式.这值得编码为宏或抽象类吗?也许.但不是很明显.我们谈论的是游戏框架,您可以通过传递参数,填充空白等来定义计算机游戏.这可能既高效又有趣,但它并不是唯一的做事方式.
Erlang平台具有可实例化的模式抽象,与服务器一样通用,这很酷.我猜一个Erlang项目拥有的Java服务器和Singletons一样多.
但是出于特定目的,如果您在Lisp,Haskell或其他任何地方工作,并编写服务器,有时只需遵循服务器模式,将其实现为良好的旧函数和对象,而无需尝试实现可实例化整个事物的抽象.
所有设计模式都不是源代码中的低级文本模式.
我认为保罗格雷厄姆在这个问题上错过了重要的时刻.使用模式不是要拿起一本列出它们并将其中一些应用到代码中的书.我同意这将是一个糟糕的选择,但这不是什么模式.
设计模式只是一种识别"嘿,我认识到这与我之前解决的另一个问题类似"的方式,并且学习如何创建解决方案的良好抽象,以便它适用于适当的情况.
事实上,如果你编写了任何合理尺寸的东西,你可能已经使用了众所周知的设计模式而且不知道它有一个名字.例如,我在使用"工厂"模式很长一段时间才有任何线索它是"工厂".知道它的正式名称只会阻止我再次重新发明轮子.
当然一些众所周知的模式有点蹩脚; 单身人士肯定是怀疑.但那个问题显然是一个过于聪明的解决方案,需要解决一个问题并且做得不好.但这就是为什么你可以找到许多支持和反对它的文献 - 因为人们认识到它可能不是一个好的解决方案.
但是模式作为一个整体是一件非常好的事情,如果他们鼓励抽象的话.