“如果您必须为现代软件开发提供一些原则,您会选择哪个?”
在最近的一个极端星期二俱乐部(XTC)虚拟会议上,我们正在讨论固体原则是否过时。一段时间我给了一个关于这个话题的舌头谈话,所以在会议之前,其中一个组织者询问我会替换哪些原则,因为我不同意他们。一段时间我一直在考虑这个,我提出了五个自己的五个,形成了缩略词丘比特。
本文不是关于这些原则,这将是我的下一篇文章。这是关于为什么我认为我们需要它们。我想分享背面的故事,解释为什么我从未真正买入坚实。要做到这一点,让我们谈谈谈话。
PUBCONF被发明为NDC会议的一种追踪。顾名思义,它发生在酒吧中。几位扬声器给出了点燃式谈话 - 20款,每张幻灯片15秒,自动推进 - 以及观众咆哮,邮票,拍拍和危机相应的批准。胜利者得到了一些东西,每个人都有美好时光。
几年前,我被邀请在伦敦的一场公民汇集活动中发言。我喜欢受限制谈话的挑战。这个必须是醉酒的搞笑和点燃形状。我一直在思考罗伯特C.Martin的坚实原则,本着“这取决于”的精神,我认为看看我是否可以用直面反驳每个原理是有趣的。我也想提出每种情况的替代方案。
现在有些会谈自己写作:我想我可以使用一个幻灯片来介绍每个原则,一个挑战它,一个是一个促销替代品,五次。这是15个幻灯片,每个原则45秒。顶部和尾巴,还有我的20个幻灯片!
正如我写的那样,我注意到了两件事。首先,更容易拒绝每个原则,而不是我想(除了利斯科夫的替代原理外,所以我不得不解决这种不同的方式)。其次,替代方案始终变成相同的东西:写简单的代码。很容易挑战“简单”甚至意味着什么?“但我对此有一个良好的工作定义,所以我不太担心。
在会议之后,我把幻灯片放在扬声器点上,我从未见过的全部负荷开始攻击首先是谈话的前提,那么从谈话中幻灯片的细节他们从未听过我给我,然后我个人。
由于我从未写起来,这里大致谈话了。请记住,对于每个原则,我有15秒才能介绍它,15秒钟挑战它,以及15秒钟提出替代品。准备好?去!
单一责任原则表示代码应该只做一件事。另一个框架是它应该有“改变的一个原因”。我叫这个“毫无意义的模糊的原则”。无论如何是什么? ETL - 提取 - 变换 - 负载 - 有一件事(Dataprocessor)或三件事?任何非琐碎的代码都可以有任何数量的改变原因,这可能是也可能不包括你所遇到的那个,所以这对我来说并不大。
相反,我建议使用它“适合我的脑海”的启发式来编写简单的代码。那是什么意思?如果它适合你的头,你只能推理一些东西。相反,如果某些东西不适合你的头,你就无法理解它。代码应符合任何级别的粒度,无论是在方法/函数级别,类/模块级别,类组成的组件中,还是整个分布式应用程序。
你可能会问“谁的头?”出于启发式的目的,我假设头部的所有者可以读取和编写惯例代码,无论何种语言都在播放中,它们熟悉问题域。如果他们需要比这更疏散的知识,例如知道我们需要与完成任何工作所需的许多未记录的内部系统中哪一个,那么应该在代码中显式明确,以便它将适合其头部。
在每种规模上,应该有足够的概念完整性,你可以在那个级别掌握“整个”。如果你不能,那么这是一个启发式,在你的重组活动中努力。有时你可以一起捆绑几件事,他们仍然适合你的脑袋。捆绑甚至让他们更容易理解,而不是如果有人坚持单一责任。在其他情况下,将单一责任人工分解成几个步骤是有意义的,只是为了使每个步骤更容易理解。
这是代码应该打开的想法,即扩展,即,在不改变的情况下易于扩展,并关闭修改,即您可以相信它所做的,这样您就不需要进入和修补它。
昂贵的变化:尝试在20世纪90年代编制和链接几百万行C ++。我会等。
危险变化,因为我们还没有弄清楚重构,从不介意重构IDES(在小型托盘之外)或示例引导的编程。
大多数添加剂:您会写一些代码,检查它(如果您与孩子们一起使用并使用RCS或SCC等版本控制系统),然后继续到下一个文件。您将详细的功能规范转化为代码,一次一个块。重命名的东西罕见;重命名文件双倍。变成普遍存器源控制系统的CVS将忘记文件的整个历史,如果您重命名,则这是一种罕见的活动。这很容易忽略自动重构的时代,以及基于混乱的版本控制。
如今,如果您需要代码做代码的等价建议是:更改代码以使其做其他事情!它听起来很陈然,但我们认为代码现在像粘土一样,在古老的日子里,隐喻更像是构建块。规格之间没有反馈循环,以及我们具有自动示例的代码。
在这种情况下,我锁定了“Cruft Accretion原则”。代码不是“资产”要仔细收缩和保存,但成本,债务。所有代码都是成本。因此,如果我可以采取大量现有成本并用更小的更具体的成本替换它,那么我正在赢得代码!编写易于更改的简单代码,您可以打开和关闭代码,但您需要它。
这只是应用于代码替代的原则,因此非常明智。如果我告诉你一些有效的亚型,那么你应该能够假设你关心的任何感觉都相同。
然而,LSP的语言使用“亚型”,与大多数开发人员混淆了与子类的子类别的方式,以及“理想属性”的变幻堂,意味着它倾向于唤起“IS-A”的基于类的继承语言。 “具有”,及其相应的20世纪80年代实体建模。
本着使用黄油刀作为螺丝刀的精神,许多物体可以“类似于a”或“有时使用的”或“偏离的 - a-a-if-umint” 。在这种情况下,我们真正想要的是小型,简单的类型,我们可以撰写进入我们需要的更复杂的结构,并使我们的和平与之相关的任何细微差别。我的建议,Quelle惊喜,是“写简单的代码”,很容易理解。
这真的是鱼类桶,因为原则去了。出于某种原因,这是争议最争议的,而是对我来说是最容易揭穿的。在研究这次谈话时,我发现这种模式是关于罗伯特C.马丁在Xerox的一些印刷软件中间争夺神对象时。一切都在一个名为工作的课程中发生。他简化它的方法是找到所用的每个地方,弄清楚哪种方法“走到一起”并将那些放在中间界面中。这有几个直接的福利:
将相关方法收集到不同的接口中显示了作业类正在执行的所有不同职责。
给每个界面都有意图揭示的名称使得代码更容易理解,而不是刚刚通过作业对象。
它创建了将作业类分解为每个接口前面的较小类的选项。 (同样,他们现在不再需要界面。)
所有这一切都是有道理的,这只是它不是原则,它是一种模式。一个原则是在任何背景下都是良好建议的东西:首先寻求理解,然后被理解;彼此很好。
一种模式是在给定的上下文(上帝类)中有效的策略,它有利益(较小的组件)和权衡(更为单独的事情)。原则将在第一个地方没有进入那件事!
因此,我认为,如果这是一个原则,这是“稳定的门原则”。如果您首先拥有小型,基于角色的课程,那么您不会在尝试分解巨大纠结的混乱的位置。
当然,我们可能会发现自己在这方面不时,当我们这样做时,界面隔离是一种完全叫做理智的方式,以及建造一套特征测试以及迈克羽毛中的所有其他建议'辉煌工作有效地与遗留码。
虽然DIP没有任何根本的错误,但我认为这不容夸张,说我们对依赖反演的痴迷在过去几十年中,我们对依赖反演的痴迷造成了数十亿美元。
这里的实际原则是选项反转。当可能提供多种方式时,依赖性只是有趣的,并且当您相信布线足够重要时,您只需要反转这种关系以使其成为一个单独的问题。这是一个非常高的酒吧,大多数是你所需要的一切都是一种主要方法。
如果您订阅了所有依赖关系的想法,请一直反转,您最终结束J2EE,OSGI,Spring或任何其他“声明组合装配”框架,其中组件的结构本身是Config的Twisty Maze。 J2EE值得提及决定每种类型的依赖性反转 - EJB,Servlet,Web域,远程服务位置,即使是配置配置 - 应该由不同的角色拥有。
在野外,存在完整的暗影码条,其中每个类被恰好互联,它只存在于满足布线框架或为自动测试剧院注入模拟或存根。 “您只需交换数据库”的承诺,就会在您尝试时立即迁移,交换数据库。
大多数依赖关系都不需要反转,因为大多数依赖性不是选项,他们就是我们这次要这样做的方式。所以我的 - 现在完全没有出售 - 建议是通过专注于使用而不是重用来编写简单的代码。
当我看起来很坚实时,我看到一系列曾经很好的建议的混合,适用于上下文的模式,以及易于误用的建议。 我不会将任何一种作为新程序员提供无论如何的建议。 那么我会做什么? 我认为每个坚实的原则和模式都可能是一对一的对应关系,因为他们中的任何一个都没有任何自然的坏事或错误,而是俗话说,“如果我要去都柏林,我会 't从这里开始。“ 所以,鉴于过去30年来我在软件开发中学到了什么,我是否会提供任何原则? 他们可以形成一个简洁的首字母缩写吗? 答案在是的,我将在下一篇文章中概述它们。 编辑:我保留审查任何我不认为的任何评论的权利是建设性的或向前移动对话。