如何编写将被重用的代码



专为重用而设计的代码可以解决所有编程难题的灵丹妙药是一个危险的神话。 现在,我将解释原因。

想象一下,您正在编写一个库,突然发现了一个绝妙的主意,从中可以得到适用于多种情况的通用解决方案。 您正在狂热地开创API的要求,这些API会超越任何功能并适应任何情况。 您添加了所有只有您想到的脚本。 代码不断膨胀,但最终,它确实在词义上得到了全面的概括。 他就像热蛋糕,你很高兴。

但是有一天,一种新的API即将出现。 它更加简洁,适用于大量场景,而且在速度和简单性方面都具有优势。 您的API被遗忘了-每个人都立即转换为诱人的新颖性。 但是,过了一段时间,同样的故事也重演了:由于不断增加代码(针对新条件而设计),API变得越来越沉重,直到最终有其他东西取代了它。 等等广告无限。

为什么会这样呢?

在这种情况下,所有问题的根源都在于编写通用解决方案的愿望。 如果可重现代码以标准案例为标准,它将变得ated肿,使用不便,并逐渐变成纯粹的头痛。

某种程度的泛化是重复使用任何代码的前提。 但是,如果对此做得太过严格,功利主义就会开始遭受损失。 因此,如果我简而言之表达我的想法,那么编写可重用的代码并不能使它变得尽可能全面。 一切都更加复杂。
要创建实用的可复制代码,您需要确保没有经常使用该代码,而是在需要时自发使用。 假设在处理产品时,您突然遇到了可用于其需求的代码。 您可以使用此代码段,对其进行一些修改并在应用程序中实现它。 因此,您只需为真正的好处以及在必要时确切地付款。

后来,您发现此修订版可以在另一个应用程序中派上用场。 您再次获取此片段,对其稍加修改,然后在第三个圆圈中使用它。 因此,逐渐提高可重复性,您不仅可以从该片段中获得最大的收益,而且还可以保护您的产品免受对其无能为力并且通常不需要该代码的代码的侵害。

这里的主要内容绝不是试图预测未来。 可复制性应限于当前的可见性限制; 将来,只要有新的应用机会,您都将相应地更正代码。 这不仅可以节省您的时间和精力,而且可以编写出更经济,更酷和更现代的代码,并可以重复使用。

以下是一些有关如何使代码可重用的实用建议。

避免重复


正如莱蒙·辛格(Lemony Sinquet)正确说的:“不要重复。 首先,您重复一遍,其次,您说相同的话,其次,每个人都已经听到了。”

还记得吗,我们谈论过自然发生的重用? 这正是(并且仅此)应限于人机工程学代码的目的。 因此,在此特定时刻编写所需的代码,并以同样的精神继续,直到您发现必须一遍又一遍地解决相同的问题。 然后进行重构,将代码放在可访问的位置并根据需要引用它。 以这种方式执行操作,您不会得到浪费的通用代码,而不会得到重复的代码。

实际上,DRY原则假定了相同的原则(不要重复自己),该原则指出,不应在代码中重复写入相同的逻辑-这会产生技术责任。 毫无意义的重复会阻塞系统,降低代码库的质量,此外,对于那些负责维护产品代码的人来说,它也成为噩梦。 重要的是要记住:DRY原理是一种哲学,要求放弃个人编程的野心,并尽最大的努力来完成项目。 如果某人已经做过某事,请使用它。 无需重新发明轮子。

确保类/方法/函数负责一件事。


在这种情况下,我们可以回想起路易斯·沙利文(Louis Sullivan)的优美言论:“形式来自目的地”。 在翻译中,这意味着以下含义:如果函数,类或方法只做一件事情,那么您将仅出于一个原因进行更改。 是的,使用这种方法,您通常必须创建将使用其他方法的方法,但是它们将保持简单且不太紧密。

每个系统都是通过面向主题的语言构建的,该语言是由程序员创建的,目的是正确描述此类系统。 函数在这些语言中扮演动词的角色,而类则扮演名词的角色。 通常,它们共同构成了任何语言的基本组织层次; 因此,如果您以高质量的方式开出处方,那么您的代码将是高质量的。

创建可多次应用的函数和类有两个黄金法则,只有两个:

  • 他们应该很小
  • 他们应该做一件事,好

这假定该函数的增长不应足以容纳嵌套结构。 因此,嵌套级别不应超过一或两个。 由于有了这项技术,代码变得更易于阅读,解析和同化。

另外,有必要确保单个函数中的所有运算符保持相同的抽象级别。 混合级别总是令人困惑,迟早会导致代码工作困难。 专业程序员将可复制代码视为一种叙述,而不仅仅是一段文本。 他们使用所选编程语言的功能来创建更具表达力,更有意义,更整洁的模块,从而完美地构建叙述。

不要滥用继承


有时,我们(开发人员)会尝试研究项目的遥远未来,并开始考虑“如果需要它会怎样”和“有一天会派上用场”这样的想法,提供其他功能。 不要那样做 到现在为止,这对于您来说并没有派上用场,现在您不再需要它了,在大多数情况下……您将不需要它(用YAGNI的众所周知的原理-您根本不需要它)。 此原则适用于继承。 如果您不确定将多次重复实施,请不要输入。

有了这些,遗传是向类添加功能的好方法。 但是程序员倾向于抢占优势,在六个或更多级别构建类层次结构。 其“设计模式”一书中的“四人帮”简洁地描述了过度继承的风险:

“由于子类可以访问父类的实现细节,因此经常说继承违反了封装。”

遗传会导致组件之间的强大凝聚力,因为超类向子类开放了内部,而这些子类又在与正确操作相关的所有事情中完全依赖于超类。 在这种情况下,超类失去了灵活性-很难更改其功能。 由于这个原因,遗传是实现代码重用的不好方法。

一种更合理的方法是考虑对象结构的范式,而不是遗传。 这将使使用您的代码的人们可以更轻松地准确掌握他们所需的功能,并根据与他们相关的限制创建自己的对象。 您甚至应该考虑创建每个类都可以以自己的方式实现的过程接口。 与具有多层继承的类相比,接口通常更易于理解和实现。

总而言之,只有当一个类是另一类的逻辑延续并且继承类的大多数代码使用超类的代码时,才应诉诸遗传。 在任何其他情况下,您只需为自己签署死刑判决书并重新使用代码即可。

总结


通常,编写代码以供重用并不意味着创建巨大的广义整体块。 编写可复制代码的关键在于针对特定任务的元素,这些元素易于组装,良好焊接且相互之间的连接不太牢固。

最后,不要因重复使用而终结自己-这是不值得的。 最好设定一个避免重复的目标,而不是写空的,不必要的片段,以确保代码易于阅读和维护。 当您对事物有正确的看法时,可复制性将自成一体。

永远记住:重用始于您为特定任务找到成功解决方案的事实。 其他一切都应从此前提出发,您有权选择最合适的方法,以将某些代码带入新的水平。 正如Ralph Johnson正确地指出的那样:“在考虑重用代码之前,您需要确保完全可以使用它。”

Source: https://habr.com/ru/post/zh-CN481296/


All Articles