it-swarm.cn

重新发明轮子真的那么糟糕吗?

它在编程中的常识是重新发明轮子是不好的,或者邪恶

但是为什么呢?

我并不是说这很好。我相信这是错误的。但是,我曾经读过一篇文章,说如果有人做错了(明智的编程),请向他们解释为什么错了,如果不能,那么也许您应该问自己是否真的错了。

这使我想到了这个问题:

如果我看到有人通过构建自己的方法(已经内置到语言/框架中)来明显地在重塑车轮。首先,为了论证,让我们假设他们的方法和内置方法一样有效。同样,了解内置方法的开发人员也更喜欢自己的方法。

为什么他应该自己使用内置的?

104
JD Isaacks

正如我曾经在StackOverflow上发布的,重新发明轮子是 通常是一个很好的选择,与普遍看法相反。主要优点是您拥有 完全控制 在软件上,这通常是必不可少的。要进行全面讨论,请 请参阅我的原始帖子

73
Dimitri C.

依靠..

与所有内容一样,它与上下文有关:

什么时候好:

  • 框架或库太重,您只需要有限的功能。滚动适合自己需求的超轻量级版本是一种更好的方法。
  • 当您想了解和学习复杂的东西时,自己动手就很有意义。
  • 您可以提供不同的东西,而其他人的实现则没有。可能是新变化,新功能等。

这很糟糕:

  • 功能已经存在,并且已知是稳定且众所周知的(受欢迎的)。
  • 您的版本没有添加任何新内容。
  • 您的版本引入了错误或约束(例如,您的版本不是线程安全的)。
  • 您的版本缺少功能。
  • 您的版本的文档质量较差。
  • 与要替换的版本相比,您的版本缺少单元测试。
83
Darknight

我认为开发人员有意“因为他喜欢自己的方法”而重新发明轮子的情况很少见。大多数情况下是出于无知,有时是出于固执。

这一切都不好吗?是。为什么?因为现有的轮很可能随着时间的流逝而制作,并且已经在许多情况下针对大量不同种类的数据进行了测试。现有车轮的开发人员已经遇到了重创者甚至无法想象的Edge案例和难题。

56
Dan Ray

方轮必须重新发明。吸吮的努力必须重复。也许缺少该方法的文档,并且另一个程序员觉得只编写自己的方法而不是尝试解决问题要容易得多。也许该方法的调用方式很尴尬,不适合编程语言的习惯用法。

只是问他缺点是什么。

22
user8865

通常,如果我想要的功能或与其近似的功能存在于我使用的语言的standard库中,则避免重新发明轮子。

但是,如果我必须合并第三方库,则需要根据库的使用和尊重程度来做出判断。我的意思是,我们是在谈论 Boost 还是Bob的Kick-ass字符串解析工具1.0?

即使该库在整个行业中通常是众所周知的和备受推崇的,它仍然是第三方dependency。程序员通常将重点放在代码重用的优点上,同时常常掩盖依赖的危险。从长远来看,具有太多第三方依赖项的项目很可能会崩溃,因为它慢慢演变为维护的噩梦。

因此,利用现有代码是good-但依赖项是bad。不幸的是,这两个语句彼此矛盾,所以诀窍是试图找到适当的平衡。这就是为什么您需要识别acceptable依赖关系的原因。就像我说的那样,该语言的标准库中的任何内容很可能都是可接受的依赖关系。从那里继续前进,在整个行业中广受好评的库通常也可以接受(例如Boost for C++或jQuery for Javascript)-但它们仍然比标准库less更受欢迎,因为它们do往往不如标准化库稳定。

至于相对不为人所知的库(例如SourceForge上的最新上传文件),这些库具有极大的风险,因此我通常建议在生产代码中避免使用这些库,除非您对源代码足够熟悉以自己维护它们。

因此,这实际上是一种平衡行为。但问题是,只是盲目地说“代码重用好!重塑轮子不好!”是一种危险的态度。利用第三方代码must的好处与引入依赖项的缺点权衡。

17
Charles Salvia

如果人们不重新发明轮子,那么世界将充满这些轮子。 enter image description here

这是我工作场所的对话:

- I would like to add some colors to the output of this program.
- Oh, there is this library called Colorama ..

有两个选项:或者重新发明轮子OR使用Colorama。这是每个选项会导致的结果:

使用Colorama

  • 也许更快一点开始运行
  • 为一些琐碎的事情添加第三方依赖
  • 您仍然像使用Colorama之前一样愚蠢

重新发明轮子

  • 您了解某些程序如何显示颜色
  • 您了解到可以在任何终端上使用特殊字符进行着色
  • 您可以使用将来可能使用的任何编程语言进行着色
  • 您的项目不太可能中断

如您所见,这完全取决于上下文。重塑方向盘是我经常做的事情,因为我希望自己能够自己思考,而不依赖其他人为我思考。但是,如果您正在按时完成任务,或者您尝试实施的内容非常庞大并且已经存在,那么最好使用那里的内容。

14
Pithikos

重新发明轮子的一个有用原因是出于学习目的-但我建议您自己动手做。随着更多的罐头解决方案可用,并提供了更多的抽象级别,我们的工作效率将大大提高。我们可以专注于业务问题,而不是一遍又一遍地调整的通用内容。但是,由于这个原因,您可以尝试自己重新实施解决方案,从而提高自己的技能并学到很多东西。只是不一定用于生产。

另一件事-如果担心的是可能会消失的公司对第三方库的依赖,请确保有一个获取源代码的选项,或者在那里至少有两个其他选择可以依靠。

顺便说一句,如果您确实选择实现自己的实现,请避免对密码或其他与安全性相关的功能执行此操作。为此,可以使用已建立(并经过充分测试)的工具,在当今时代,这种方式太冒险了,以至于无法自己动手。这永远都不值得,而且我仍然听说有团队这样做,这令人感到恐惧。

13
Mark Freedman

有两种效率可以匹配,即处理/速度(即执行速度)和几乎可以肯定的效率。这是第一个原因对于存在现有解决方案的合理复杂性问题,几乎可以肯定的是,研究和实现现有库要比编写自己的库快得多

第二个原因是现有的库(假设它已经成熟)已经过测试并且被证明可以正常工作-可能在比开发人员和测试团队能够放置新的场景更广泛的场景中通过书面例行程序,这是零工作。

第三,更容易获得支持。 其他人支持和改进它(谁编写了库/组件),而且其他开发人员很可能会熟悉它并能够理解和维护它)。代码,所有这些都将持续的成本降到最低。

所有这些都假定功能对等,而通常情况并非如此。通常,库会提供您会发现有用但无法证明内置的功能,所有这些功能突然都是免费提供的。

自己动手是有原因的-主要是在您想要执行内置函数无法执行的操作的地方,或者通过这样做可以获得真正的好处的地方,或者在现成的选项还不成熟的地方-但是它们它比许多开发人员所想像的少。

此外,您为什么要花时间解决已经解决的问题?是的,这是一种学习的好方法,但是您不应该以生产代码的正确解决方案为代价来做到这一点,这就是我所假设的。

9
Jon Hopkins

当然,出于无知和傲慢,一时兴起地重新发明轮子可能是一件坏事,但是恕我直言,钟摆已经摆得太远了。拥有一个可以精确地满足您想要且仅需的轮子的巨大优势。

通常,当我看一个现有的车轮时,它的作用超出了我的需要,遭受了 内部平台效应 的困扰,因此变得不必要地复杂,或者缺少了我要做的一些关键功能需求,而在已经存在的基础上很难实现。

此外,使用现有的轮子经常给我的项目增加我不想要的约束。例如:

  • 现有的轮子需要与我不愿使用的语言和/或编程风格不同的语言。
  • 现有的转轮仅适用于语言的旧版本(例如,Python 2而不是Python 3))。
  • 在效率,灵活性和简单性之间需要权衡取舍的情况下,现有的轮子做出的选择对于我的用例而言是次优的。 (众所周知,在这种情况下,我甚至从我最初编写的库中重新发明了功能。通常是因为当我目前需要特定功能非常快速的某些功能时,我编写了该函数的库版本是通用且相当有效的。案件。)
  • 现有的轮子有大量的遗留废料,在新代码的情况下完全没有用,但仍然给生活带来困难(例如,我使用的Java库迫使我使用其垃圾容器类,因为它是在泛型之前写的,等等。
  • 现有车轮对问题建模的方式与我的用例方便的方式完全不同。 (例如,对于我来说,用节点对象和引用表示有向图可能很方便,但是现有的轮子使用邻接矩阵,反之亦然。也许对我来说,按列主顺序排列数据很方便,但是现有的车轮坚持使用专业级,反之​​亦然。)
  • 当我需要的只是其功能的一小部分时,该库会添加大量的,脆弱的依赖关系,这将是在我想部署代码的任何地方启动和运行的主要麻烦。另一方面,在这种情况下,有时我只是将想要的功能提取到一个新的较小的库中,或者如果该库是开源的并且代码库使此操作非常简单,则仅复制/粘贴。 (我什至使用我自己编写的相对较大的库,而不仅仅是别人的库。)
  • 现有的轮子试图在脚步上符合某些标准,这对于我的用例而言既不方便也不相关。
9
dsimcha

我经常使用自己的,因为我在发现现有实例之前就已经构建了它,而且我懒得去查找和替换每个实例。另外,我可能会完全理解我自己的方法,而我可能不了解现有的方法。最后,由于我不完全了解先前的版本,因此无法验证它确实可以完成当前版本的所有操作。

有很多要编写的代码,除非没有影响生产,否则我没有太多时间回头重新编码。

实际上,今天仍在使用的一个ASP Web应用程序具有功能齐全的图表,该图表以表格格式显示数据并允许排序/编辑,但是它不是数据网格。它是几年前我第一次学习asp.net时就建立的,它并不了解数据网格。我有点害怕代码,因为我当时不知道我在做什么,但是它有效,准确,易于修改,不会崩溃,并且用户喜欢它

5
Rachel

是否重新发明轮子是一项成本/收益的事情。成本相当明显...

  • 重塑需要很多时间。
  • 记录您的发明所花费的时间甚至更多。
  • 您不能雇用已经了解您所发明的人。
  • 彻底改头换面太容易了,导致设计不当所造成的问题的持续成本。
  • 新代码意味着新错误。旧代码通常已经删除了大多数错误,对于您不知道的问题可能会有一些细微的变通办法,因此在新设计中无法解决。

最后一点很重要-在某个地方有一篇博客文章警告说,有一种趋势是“扔掉旧代码并从头开始”,原因是您不了解的许多旧内容实际上是必不可少的错误修正。关于Iscape Netscape,有一个警示故事。

优点是...

  • 能够添加现有库所没有的功能。例如,我有一些容器可以“维护”其迭代器/游标实例。插入和删除不会使迭代器无效。指向向量的迭代器将继续指向相同的项(而不是相同的索引),而与向量中较早的插入和删除无关。您根本无法使用标准C++容器来做到这一点。
  • 针对您的特定要求并尊重您的优先级的更专业的设计(但请注意内部平台效应的趋势)。
  • 完全控制-某些第三方无法决定以必须重写一半应用程序的方式重新设计API。
  • 完全理解-您已经按照这种方式进行了设计,因此希望您完全理解这样做的方式和原因。
  • [〜#〜] edit [〜#〜]您可以选择性地模仿它们,从而可以从其他库中学习课程而不会陷入同样的​​陷阱。

一件事-使用第三方库可以算是重新发明轮子了。如果您已经拥有自己的古老的,使用良好的,经过良好测试的库,则在丢弃它以使用第三方库之前,请仔细考虑。从长远来看,这可能是个好主意-但是在您到达那里之前,可能会有大量的工作和很多令人讨厌的惊喜(由于库之间的细微语义差异)。例如,考虑一下我从自己的容器切换到标准库的影响。幼稚的调用代码转换不会考虑标准库容器不维护其迭代器的事实。我根本无法通过简单的翻译来实现将迭代器保存为“书签”以备后用的情况-我需要一些非平凡的替代方法来指示书签位置。

4
Steve314

重塑车轮是学习车轮工作原理的好方法,但并不是制造汽车的好方法。

4
Dima

我目前为一堆cheapskates工作。

当在“建造还是购买”之间做出决定时,管理者选择了“建造”,而不是根据经济学做出理性的决定。这意味着我们不用花几千美元来购买组件或工具,而是花了我们数月的时间来构建自己的组件。从另一家公司购买车轮会花费预算中的钱-这算是管理不善的年终奖金。程序员的时间是免费的,因此不计入年终奖金(还有让程序员因无法按时完成所有事情而叮叮当当的额外好处),因此飞轮

在一家理性的公司中,成本与他人购买轮子的收益与自己发明轮子的收益之比将取决于短期和长期成本,以及由于一个人无法制作新的小部件而损失的机会成本。重塑车轮。每天花在重塑轮子上的每一天都是您无法写出新东西的日子。

关于构建与购买的介绍
关于构建与购买的文章

如果我看到有人通过构建他们自己的已在语言/框架中内置的方法来明确地重塑轮子。首先,为了论证,让我们假设他们的方法和内置方法一样有效。同样,知道内置方法的开发人员也更喜欢自己的方法。

为什么他应该自己使用内置的?

内置版本将吸引更多的人参与其中-因此查找和修复的错误数量超过了自制代码所能提供的数量。

最后,当您的本地开发人员离开时,其他人必须维护他编写的代码,它将完全重构并替换为在框架中。我知道会发生这种情况,因为我的当前雇主的代码已经迁移到了VB)的较新版本中,多年来(最古老的产品已投放市场约20年)),这就是事实。我办公室里受雇时间最长的开发商来这里已有17年了。

4
Tangurena

重新发明轮子的问题是,有时没有标准的现成轮子可以满足您的需求。有很多尺寸,颜色,材料和构造方式不错的轮子。但是有些日子,您只需要拥有一个非常轻便的车轮即可,它是绿色的阳极氧化铝,却没人能做到。在这种情况下,您必须自己做。

现在,这并不是说您应该为每个项目制造自己的轮子-大多数事情都可以使用标准零件,并且对此做得更好。但是有时候,您会发现标准零件无法正常工作,因此您需要自己制造。

最重要的是知道什么时候可以自己制造。在开始设计自己的零件之前,您必须对标准零件可以做什么以及它们不能做什么有一个很好的了解。

4
Michael Kohne

“坏”甚至“邪恶”是很强烈的话。

与往常一样,有很多原因需要选择内置实现而不是内置实现。在过去,C程序可能会在运行时库中遇到错误,因此只需提供其自己的实现。

这不适用于Java程序,因为JVM的定义非常严格,但是某些算法仍然很难解决。例如,Joshua Bloch描述了如何在程序中使用简单的二进制搜索算法Java运行时库包含一个错误,但花了九年的时间才浮出水面:

http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html

它被发现,固定并在将来Java发行。

如果使用内置的二进制搜索,那么Sun会通过艰苦的工作来查找,修复和分发此错误修复程序,从而节省了时间和金钱。您可以通过说“您至少需要Java 6更新10”)来利用他们的工作。

如果您使用自己的实现(很可能也包含此错误),则首先需要该bug来表明自己。鉴于这一特定问题仅在LARGE数据集上显示,它一定会在某处的生产中发生,这意味着您至少有一个客户会受到影响,并且最有可能在您找到,修复和分发错误修复程序时浪费了真金白银。

因此,偏爱您自己的实现是完全正确的,但是最好是真正做到这一点,因为与利用他人的工作相比,这样做必然会更加昂贵。

3
user1249

如果有一个工作组件满足您的需要,那么为什么要花时间编写和调试自己的版本?同样,如果您之前已经编写了实现类似功能的代码,为什么还要重新编写呢?

乔尔(Joel)在未发明上写了 一篇文章 ,在这里谈论了什么时候重写代码和软件是无效的还是无效的。

3
Dave

重新发明轮子可能是学习事物工作原理的好方法-我建议您根据自己的时间为此目的重新发明-但是在编写应用程序时,为什么要重新发明是否有完善的解决方案已经在做同样的事情?

例如,我永远不会从头开始编写JavaScript代码。相反,我将从jQuery开始,并在该框架之上构建我的应用程序。

3
Justin Ethier

我个人的经验法则:

仅在学习时重新发明轮子是件好事。如果有最后期限,则可能要使用现有的轮子。

3
John

我最近在这个主题上 发表了我的想法 。总结一下:

  1. 建立自己的东西几乎总是邪恶,如果在语言中内置了该函数,则尤其如此。但是,如果您要评估的是一个在互联网上发现的不成熟/可维护性很差/文档不良的框架,而不是编写自己的框架的可能性,那可能就很容易了。

  2. 我认为重塑方向盘非常类似于软件反模式。这意味着原始解决方案永远无法改进。废话所谓的轮子可能会在一夜之间过时,或者其所有者可能会停止维护它。车轮在使用该车轮的每个系统上都有不同的值。因此,通常有可能发明更好的车轮。

  3. 建立自己的框架的主要好处是您不必对别人的错误负责。 (这是 Amazon的哲学 。)以这种方式思考:哪种更好地告诉客户? --

    “我们的网站坏了。这是别人的错,我们已经在其创建者那里记录了一个错误。除了等待,我们对此无能为力。我们会及时通知您。”

    “我们的网站损坏了,我们能够立即对其进行修复。”

3
realworldcoder

也许它同样有效,但是是否强大?我认为使用库来滚动自己的库的最有说服力的理由是,框架有太多人在使用它,因此他们可以快速找到并修复错误。内部开发的库虽然可以提供同样(或更多)的功能,但无法与拥有数百万用户的库竞争以在几乎每个用例中提供测试。您只是无法在内部进行这种测试。

0
Michael K

好吧,他自己的方法像框架一样高效的情况将很少见,因为大多数框架仍然存在错误,而且没有框架可以为您提供即用型解决方案。大多数无法思考的程序员永远不会尝试在框架级别上编写任何东西。他们只会在Google上搜索现成的解决方案。任何明智的程序员都将首先查看是否有一个免费的框架,该框架具有他所需的功能,然后,如果没有,则自己编写解决方案。有时很难解释当前的项目情况,而开发人员是最好的判断者。

重塑轮子并不坏,这是懒惰的人避免努力工作的说法。即使是框架作家也确实在重塑。整个.Net框架被重新发明以完成COM提供的功能。

0
Akash Kava

尽管对某些人来说是令人反感的,但我经常发现该术语在被任何形式的工程师使用或提及创建或设计事物的主题时都不明智。实际上,当考虑到当今快速发展的世界中进行创新的压力时,我不禁将其视为不诚实的。重复自己(或忽略适当的,已有的解决方案)从来都不是明智的选择,但是,确实有一个原因,就是我们并不都盯着充满绿色字母的黑屏。

我理解“如果还没有解决,那就不要解决”,尽管我想这样的话对某些人来说可能是无知的。然而,随着当前为太空旅行,赛车,运输等需要重新发明轮子的努力,“不要重新发明轮子”也很无知,而且听起来还不那么聪明。

我的背景包括领导许多项目,我不得不与许多实习生和其他形式的绿色开发商合作,而且我不得不处理许多天真问题,有些问题被称为“愚蠢”,还不得不转移人们的注意力去追逐兔子整体超出了他们的任务范围。但是,我会从不阻止创新或创造力,并且看到伟大的事情来自“重新发明轮子”。

我对这个问题的实际回答:只有两种情况使重新发明轮子是一件坏事:

  1. 如果不是真的需要
  2. 如果是其他人这样做的话

编辑:我可以通过开车经过的否决票看到我一定得罪了一些。我想补充的一件事是,这句话一直是我的主要观点。我知道我的两分钱听起来可能有些古怪,但我无意进行古怪,引起火灾或冒犯。

0
JSON

关于“重新发明轮子”的争论通常在选择使用库的错误上下文中使用,但这几乎不是类似的事情。

假设我正在评估一个库“ forms-plus”,该库最近才流行,并且有助于处理表单。它有一个漂亮的登陆页面,现代酷炫的图形以及周围的-cult-(哎呀,我的意思是社区),他们发誓如何使表格再次变得更好。但是“ forms-plus”是“ forms”之上的抽象。 “形式”是可能的,但处理起来很麻烦,因此使其变得更容易的抽象变得流行。

新的抽象一直在发生。很难将它们与车轮进行比较。它更像是新的控制设备和新的手册,适用于您需要运行的任何非常复杂的设备。

根据个人经验,此新设备“ forms-plus”的价值看起来会有所不同。如果我以前从未构建过表单,那么“ forms-plus”将非常引人注目,因为它更容易上手。缺点是,如果“ forms-plus”被证明是泄漏抽象,那么无论如何我仍然需要学习“ forms”。如果构建的表单没有“ forms-plus”,那么我将需要考虑学习新工具的时间。好处是,我已经知道“形式”,因此我不惧怕其上的抽象。对于新手来说,短期利益通常会更大,因为如果没有改进,那么就不会有新图书馆了。长期利益将在抽象质量,采用率和其他答案中已经讨论的其他因素上有很大差异。

在仔细评估了使用新的抽象形式“ forms-plus”与使用裸骨“ forms”的利弊之后,我做出了决定。决定很大程度上取决于我的个人经验,不同的人会做出不同的决定。我可能选择使用准系统“表格”。也许在以后的时间里,表单加上了更多的支持,并成为了事实上的标准。也许随着时间的流逝,我自己的实现变得很繁琐,并且开始涉及很多表单以及现在正在做的事情。这个时候来的人会被批评为我热衷于重新发明轮子,而我应该使用现有的库。但是,当我不得不对“ forms-plus”做出决定时,也有可能是“ forms-plus”的其他多种选择,到现在大多数都是无效的项目,而且可能我没有选择错误就获得了收益。一。

最后,选择合适的工具是一个复杂的决定,“重塑车轮”并不是一个很有帮助的观点。

0
Ski