Questions tagged «design-patterns»

设计模式是解决软件设计中常见问题的通用可重用解决方案。



8
依赖注入的批评和弊端
依赖注入(DI)是一种众所周知的流行模式。大多数工程师都知道它的优点,例如: 使单元测试中的隔离变得可能/容易 明确定义一个类的依赖 促进良好的设计(例如,单一职责原则(SRP)) 启用快速(开关实现DbLogger的,而不是ConsoleLogger例如) 我认为业界普遍认为DI是一种很好的有用模式。目前没有太多批评。社区中提到的缺点通常很小。他们中的几个: 增加班数 创建不必要的接口 目前,我们与同事讨论建筑设计。他相当保守,但思想开放。他喜欢质疑一些我认为很好的事情,因为IT领域中的许多人只是复制最新趋势,重复优势,而且通常不会考虑太多-不要分析得太深。 我想问的是: 只有一个实现时,应该使用依赖注入吗? 我们应该禁止创建除语言/框架对象之外的新对象吗? 如果我们不打算对特定的类进行单元测试,那么注入单个实现是个坏主意(假设我们只有一个实现,因此我们不想创建“空”接口)吗?

10
如今,设计模式真的必不可少吗?
我正在阅读“编码员在工作”,并且面对这样一个事实,书中接受采访的一些专业人员对设计模式并不那么热心。 我认为有两个主要原因: 设计模式迫使我们以其术语进行思考。换句话说,几乎不可能发明新的东西(也许更好)。 设计模式不会永远持续下去。语言和技术日新月异;因此,设计模式最终将变得无关紧要。 因此,也许更重要的是学习如何在没有任何特定模式的情况下正确编程,而不要学习它们。 重点还在于,通常当人们遇到问题并且没有太多时间时,他们会尝试使用一种模式。这意味着只需稍作更改即可将现有代码复制并粘贴到您的项目中,以使其正常工作。当需要更改或添加某些内容时,开发人员不知道从哪里开始,因为这不是他的代码,而且他对代码也不是很熟悉。



22
因为不自然,OOP难吗?
人们常常可以听到,OOP自然对应于人们对世界的思考方式。但是我强烈不同意这种说法:我们(或者至少我)根据我们遇到的事物之间的关系来概念化世界,但是OOP的重点是设计各个类及其层次结构。 注意,在日常生活中,关系和动作主要存在于对象之间,这些对象本来是OOP中无关类的实例。这样的关系的示例是:“我的屏幕在桌子的顶部”;“我(一个人)坐在椅子上”;“道路上有汽车”;“我正在键盘上打字”;“咖啡机煮水”,“文本显示在终端窗口中”。 我们以二价(有时是三价,例如“我给你送花”一词)动词来思考,其中动词是对两个对象进行操作以产生某种结果/动作的动作(关系)。的焦点是关于动作,两个(或三个)[语法]对象具有同等的重要性。 与OOP相反,在OOP中,您首先必须找到一个对象(名词),并告诉它对另一个对象执行某些操作。思维方式从对名词进行操作的动作/动词转变为对名词进行操作的名词-好像一切都是被动或反身的声音所说的,例如,“文本正在终端窗口中显示”。或者也许是“文本在终端窗口上绘制自身”。 不仅焦点转移到了名词上,而且一个名词(我们称其为语法主语)比另一个名词(语法对象)具有更高的“重要性”。因此,必须决定是说terminalWindow.show(someText)还是someText.show(terminalWindow)。但是,当一个人真正表示show(terminalWindow,someText)时,为什么要给这些琐碎的决定加重负担却又没有任何操作后果呢?[结果在操作上无关紧要-在两种情况下,文本都显示在终端窗口上-但是在类层次结构的设计中可能非常严重,并且“错误”的选择可能导致复杂的代码和难以维护的代码。] 因此,我要指出,进行OOP(基于类,单派遣)的主流方法很困难,因为它是不自然的,并且与人类对世界的看法不符。CLOS的通用方法更接近于我的思维方式,但是,可惜,这不是普遍的方法。 鉴于这些问题,为什么/为什么发生当前流行的OOP方式如此流行?可以采取什么行动来废除王位呢?

2
是否有实际上适用于Java的OO原理?
Javascript是一种基于原型的面向对象语言,但是可以通过以下多种方式变为基于类的语言: 自己编写要用作类的函数 在框架中使用漂亮的类系统(例如mootools Class.Class) 从Coffeescript生成 一开始,我倾向于使用Javascript编写基于类的代码,并高度依赖它。但是最近我一直在使用Javascript框架和NodeJS,它们脱离了类的概念,而更多地依赖于代码的动态特性,例如: 异步编程,使用和编写使用回调/事件的编写代码 使用RequireJS加载模块(以便它们不会泄漏到全局名称空间) 功能编程概念,例如列表推导(映射,过滤器等) 除其他事项外 到目前为止,我所收集的是,我已阅读的大多数OO原理和模式(例如SOLID和GoF模式)都是为基于类的OO语言(例如Smalltalk和C ++)编写的。但是其中有哪些适用于基于原型的语言(例如Javascript)? 是否有特定于Java的原则或模式?避免回调地狱,邪恶的eval或任何其他反模式的原则。

14
应该优先考虑什么:YAGNI或Good Design?
在什么时候,YAGNI应该优先于良好的编码习惯,反之亦然?我正在研究一个正在工作的项目,并希望向我的同事缓慢介绍良好的代码标准(目前还没有,并且一切都只是某种形式而没有韵律或理由),但是在创建了一系列类之后(我们不要做TDD,或者根本不进行任何类型的单元测试。)我退后一步认为这违反了YAGNI,因为我非常确定地知道我们不需要扩展其中的某些类。 这是我意思的一个具体示例:我有一个数据访问层,其中包装了一组存储过程,该过程使用具有基本CRUD功能的基本存储库样式模式。由于所有存储库类都需要几种方法,因此我为存储库创建了一个通用接口,称为IRepository。但是,然后我为每种类型的存储库(例如ICustomerRepository)创建了一个“标记”接口(即,没有添加任何新功能的接口),具体类实现了该接口。我已经通过Factory实现完成了同样的事情,以便从存储过程返回的DataReaders / DataSets中构建业务对象。我的存储库类的签名通常看起来像这样: public class CustomerRepository : ICustomerRepository { ICustomerFactory factory = null; public CustomerRepository() : this(new CustomerFactory() { } public CustomerRepository(ICustomerFactory factory) { this.factory = factory; } public Customer Find(int customerID) { // data access stuff here return factory.Build(ds.Tables[0].Rows[0]); } } 我在这里担心的是,我违反了YAGNI,因为我有99%的确定性知道,除了CustomerFactory向该存储库提供具体内容外,没有其他理由。因为我们没有单元测试,所以我不需要任何MockCustomerFactory类似的东西,并且拥有如此多的界面可能会使我的同事感到困惑。另一方面,使用工厂的具体实现方式似乎具有设计异味。 在适当的软件设计与不过度设计解决方案之间是否有折衷的好方法?我在问我是否需要所有“单一实现接口”,或者是否可以牺牲一些好的设计,而仅拥有例如基本接口和单个具体的接口,而不用担心对该接口进行编程接口(如果实现的话)将被使用。


5
什么是“固定一切”设计模式?
在Stephendevgins在linuxdevcenter.com上的2003年这篇文章中,Bram Cohen的BitTorrent被描述为使用了“修复一切”设计模式。 Cohen使用幂等性是一种较不常见的方法,这两种方法都使BitTorrent较难掌握,但值得研究。多次应用一个过程是幂等的,不会导致任何进一步的更改。科恩说,他使用一种称为“固定一切”的设计模式,该功能可以对许多更改做出反应,而无需真正注意所有更改。他解释说:“您注意到发生的事件,然后调用以这种完全幂等的方式编写的fix all函数,然后清除可能发生的一切并从头开始重新计算。” 幂等使某些困难的计算变得容易,但使事情有些混乱。通话发生什么变化并不总是很清楚,如果有的话。您不需要事先知道。您可以自由调用该函数, 听起来很不错。 但是,在我看来,调用幂等“修复所有问题”功能将以提高效率为代价提高系统的鲁棒性,并有可能搞砸包含系统(可能更喜欢仔细计划和执行的过程)。 不过,我不能说我曾经使用过它。我也无法在线找到他的应用程序的来源(但是我确实找到了一个声称基于它的应用程序。)。在本文之外也找不到参考(我认为我的google-fu很好),但是我确实在SOApatterns.org上找到了“幂等能力”条目。 这个想法被另一个名字更好地了解吗? 什么是“修复一切”设计模式?它的优缺点是什么?

7
为什么要使用MVC模式?
如今,每个使用Web应用程序的人似乎都希望对所有内容使用MVC。但是,我很难说服自己使用这种模式。我了解一般的想法是将代表程序的后端逻辑与前端逻辑分开。通常,视图在一定程度上似乎总是依赖于控制器,最终取决于模型。我看不出添加控制器能给我带来什么好处。我已经读过很多关于“这是应用程序应该被设计的方式”的大肆宣传,但是也许我仍然不明白应该去哪里。每当我与其他人谈论MVC时,似乎每个人对于什么属于什么类别都有不同的想法。 那么,为什么要使用MVC?通过将MVC仅仅从前端逻辑和后端逻辑中分离出来,我可以获得什么?(我看到的这种模式的大多数“优势”都是通过将接口与实现分开来获得的,而无法解释拥有单独的“控制器”的目的)

10
非OOP设计模式?[关闭]
我只听说过“设计模式”一词用于面向对象的代码,而GoF模式仅包括OOP设计模式,但是设​​计模式是解决常见编程问题的绝佳解决方案,对吗?那里没有什么说他们必须限于OOP,是吗? 我想看到一些面向对象编程领域之外的设计模式示例。你有什么?甚至存在吗(没有一本书籍,像GoF书籍一样,必须一定要写出来,才应该使用;就足够了​​)? 它们可能特定于某些编程语言,但是一般的(范例级别)模式是首选的,而其他模式则不是面向对象的。

12
“一切都是地图”,我这样做对吗?
在我制作的这款游戏中,我观看了Stuart Sierra的演讲“ 数据中的思考 ”,并将其中的一种想法作为设计原则。不同之处在于他在Clojure中工作,而我在JavaScript中工作。我发现我们的语言之间存在一些主要差异: Clojure是惯用的函数式编程 大多数状态是不可变的 我从幻灯片“一切都是地图”中汲取了灵感(从11分钟6秒到> 29分钟)。他说的一些话是: 每当您看到一个带有2-3个参数的函数时,就可以将其变成一个映射并仅将一个映射传入。这有很多优点: 您不必担心参数顺序 您不必担心任何其他信息。如果有多余的键,那不是我们真正关心的。它们只是流过而不会干扰。 您不必定义架构 与传递对象相反,没有数据隐藏。但是,他认为数据隐藏可能会导致问题并被高估: 性能 易于实施 通过网络或跨流程进行通信后,无论如何,都必须让双方都同意数据表示。如果仅处理数据,则可以跳过这额外的工作。 与我的问题最相关。这是29分钟的时间: “使您的功能可组合”。这是他用来解释概念的代码示例: ;; Bad (defn complex-process [] (let [a (get-component @global-state) b (subprocess-one a) c (subprocess-two a b) d (subprocess-three a b c)] (reset! global-state d))) ;; Good (defn complex-process [state] (-> state subprocess-one …

7
建立服务层有多重要?
我开始按3层(DAL,BL,UI)构建应用程序[它主要处理CRM,一些销售报告和库存]。 一位同事告诉我,我必须转向服务层模式,开发人员应从他们的经验中学到服务模式,这是设计大多数应用程序的更好方法。他说,将来以这种方式维护应用程序会容易得多。 就个人而言,我觉得它只是使事情变得更加复杂,我看不出有什么好处可以证明这一点。 这个应用程序确实有一个额外的小部分ui,它使用了一些(但只有少数)桌面应用程序功能,因此我确实发现自己在复制一些代码(但不很多)。仅仅由于某些代码重复,我不会将其转换为面向服务的,但是他说我还是应该使用它,因为总的来说,这是一个非常好的架构,为什么程序员如此热衷于服务? 我试图用谷歌搜索它,但是我仍然很困惑,无法决定该怎么做。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.