几年前,媒体充斥着各种文章,内容涉及代码重用的想法是一种提高生产率和代码质量的简单方法。

从我定期检查的博客和网站上,似乎“代码重用”的想法已经过时了。也许“代码重用”的拥护者都加入了SOA人群?:-)

有趣的是,当您在Google中搜索“代码重复使用”时,第二个结果标题为:

“内部代码重用被认为是危险的”!

对我来说,代码重复使用的想法只是常识,毕竟看了Apache Commons项目的成功!

我想知道的是:

  • 您或您的公司是否尝试重用代码?
  • 如果是这样,如何以及在什么级别,即低级API,组件或共享业务逻辑?您或您的公司如何重用代码?
  • 有效吗?

讨论?


我完全意识到有许多可用的开源库,并且任何使用过 .NET 或 Java 的人都以某种形式重用了代码。这是常识!

我更多地指的是组织内的代码重用,而不是通过共享库等跨社区的代码重用。

我最初问的是;

  • 您或您的公司是否尝试重用代码?
  • 如果是这样,如何以及在什么级别,即低级 API、组件或共享业务逻辑?您或您的公司如何重用代码?

从我的角度来看,我很少看到公司试图在内部重用代码的例子?

如果您有一段代码可以在中型组织中共享,您将如何通知公司的其他成员该 lib/api/etc 存在并且可能有用?

有帮助吗?

解决方案

您所引用的文章标题具有误导性,但实际上非常值得一读。代码重用非常有益,但凡事都有缺点。基本上,如果我没记错的话,这篇文章的要点是,您将代码密封在黑匣子中,而不是重新访问它,这样当原始开发人员离开时,您就会失去知识。虽然我明白这一点,但我不一定同意它——至少不同意“天塌下来”的观点。

实际上,我们将代码重用分组为不仅仅是可重用的类,我们还着眼于整个企业。更像是框架增强或解决横切问题的东西被放入我们所有应用程序使用的开发框架中(想想诸如预验证和后验证、日志记录等)。我们还拥有适用于多个应用程序的业务逻辑,因此这些事情被转移到可在任何地方访问的 BAL 核心。

我认为重要的是如果东西不会真正被重用,就不要提倡重用。它们应该有完整的文档记录,以便新开发人员也可以拥有资源来帮助他们加快速度。如果知识不共享,代码最终可能会在其他地方重新发明,并且如果您在文档和知识共享方面不严格,则会导致重复。

其他提示

我们重用代码——事实上,我们的开发人员专门编写了可以在其他项目中重用的代码。这得到了很好的回报——我们能够快速启动新项目,并且迭代地强化我们的核心库。

但我们不能只编写代码并期望它被重用;还需要编写代码。 代码重用需要团队成员之间的沟通 和其他用户,以便人们知道哪些代码可用以及如何使用它。

为了使代码重用有效地发挥作用,需要满足以下条件:

  • 代码或库本身
  • 跨多个项目或工作的代码需求
  • 传达代码的特性/功能
  • 有关如何使用代码的说明
  • 致力于随着时间的推移维护和改进代码

代码重用至关重要。我发现这也迫使我尽可能地概括,也使代码更能适应不同的情况。理想情况下,您编写的几乎每个较低级别的库都应该能够适应不同应用程序的一组新要求。

我认为代码重用大部分是通过开源项目完成的。任何可以重用或扩展的东西都是通过库来完成的。Java 拥有数量惊人的开源库,可用于执行大量操作。与 C++ 相比,一切都必须使用 MFC 或 Win32 API 从头开始​​实现。

我们重用代码。

在小范围内,我们尝试尽可能避免代码重复。我们有一个完整的库,里面有很多常用的代码。

通常,代码是为一个应用程序开发的。如果它足够通用,它就会被提升到图书馆。这效果很好。

代码重用的想法不再是一个新想法......因此显然缺乏兴趣。但这仍然是一个好主意。整个 .NET 框架和 Java API 都是代码重用的好例子。

我们已经习惯于为我们的项目开发面向对象的代码库并在其他项目中重用它们。它是想法自然生命周期的一部分。热议了一段时间,然后大家都接受了,就没有再讨论的理由了。

当然,我们重用代码。

有几乎无限数量的包、库和共享对象可用于所有语言,整个开发人员社区都在支持和更新它们。

我认为缺乏“媒体关注”是因为每个人都在这样做,所以它不再值得写。我没有像以前那样听到那么多人提高对面向对象编程和单元测试的认识。每个人都已经知道这些概念(无论他们是否使用它们)。

媒体对某个问题的关注程度与其重要性无关,无论我们谈论的是软件开发还是政治!重要的是要避免通过重新发明(或重新维护!)轮子来浪费开发精力,但这现在已经众所周知,编辑可能不会对有关该主题的另一篇文章感到兴奋。

不要将当前文章和博客文章的数量作为重要性(或紧迫性)的衡量标准,而要关注已成为经典或进入行话的概念和流行语(另一种形式的重用!)例如,Google for use DRY 缩写对软件和开发过程中可以消除的多种形式的冗余进行了很好的讨论。

关于重用成本与现有成本的成熟判断也发挥着作用。效益实现的地方。一些作者主张等到第二次或第三次使用真正出现时再担心重用,而不是在第一次编写代码时花精力去概括它。

根据我公司的实践,我个人的看法:

  • 您或您的公司是否尝试重用代码?

显然,如果我们有另一段代码已经满足我们的需求,我们将重用它。不过,我们不会特意在圆孔中使用方钉。

  • 如果是这样,如何以及在什么级别,即低级 API、组件或共享业务逻辑?您或您的公司如何重用代码?

在各个层面。我们的编码标准中写入了这样的规定:开发人员应始终假设他们的代码将被重用 - 即使实际上这种情况极不可能发生。 见下文

如果您的 OO 模型很好,您的 API 可能反映您的业务领域,因此可重用的类可能等同于可重用的业务逻辑,而无需额外的工作。

对于实际的重用,一个关键点是了解哪些代码已经可用。我们通过将所有内容记录在一个中心位置来解决这个问题。我们只需要一点纪律来确保文档是最新的并且可以以有意义的方式进行搜索。

  • 有效吗?

是的,但不是因为潜在或实际的重用!事实上,除了一些核心库和 UI 组件之外,并没有大量的重用。

就我个人而言, 真正的价值在于使代码可重用. 。这样做时,除了有望提供更干净的 API 之外,代码将 (a) 被充分记录以供其他开发人员使用它 无需搜寻源代码, ,并且(b)它也将是 可更换的. 。这些点对于持续的软件维护有很大的好处。

虽然我认为代码重用很有价值,但我可以看到这种情绪的根源。我参与过很多项目,在这些项目中,我们非常小心地创建可重用的代码,但这些代码从未被重用过。当然,重用比重复代码要好得多,但我见过许多非常广泛的对象模型,其目标是在多个项目中跨企业使用对象(类似于 SOA 中的相同服务可以在不同的项目中使用)。应用程序),但从未见过实际使用过多次的对象。也许我只是没有成为充分利用重用原则的组织的一部分。

我参与的两个软件项目都是长期开发的。一个已有 10 年左右的历史,另一个已经存在了 30 多年,并在此过程中用几个版本的 Fortran 进行了重写。两者都广泛重用代码,但都很少依赖外部工具或代码库。DRY 是新项目的一个重要口头禅,它是用 C++ 编写的,并且更容易在实践中做到这一点。

也许更好的问题是我们现在什么时候不重用代码?我们要么处于使用别人观察到的“最佳实践”或预先发现的“设计模式”进行构建的状态,要么只是实际上基于遗留代码、库或复制进行构建。

代码 A 被重用来生成代码 B 的程度似乎通常取决于代码 A 中用于代码 B 的想法被抽象为设计模式/惯用语/书籍/转瞬即逝的想法/实际代码/库的程度。困难的部分是将所有这些好的想法应用到您的实际代码中。

非技术人员对重用事物过于热心。他们不明白为什么所有东西都不能复制粘贴。他们不明白为什么 greemelfarm 需要一个特殊的适配器来将旧系统的相同信息传递到新系统,不幸的是,由于无数其他原因,我们也无法更改。

我认为技术人员从第一天起就开始重复使用,就像音乐家从第一天开始重复使用一样。这是一个持续的有机进化和合成,并将持续下去。

代码重用是一个极其重要的问题 - 如果代码不被重用,项目就会花费更长的时间,并且新团队成员更难进入。
然而,编写可重用的代码需要更长的时间。

就我个人而言,我尝试以可重用的方式编写所有代码,这需要更长的时间,但它导致我的大部分代码已成为我的组织中的官方基础设施,并且基于这些基础设施的新项目花费的时间显着减少。

重用代码的危险在于,如果重用的代码不是作为基础设施编写的 - 以通用和封装的方式编写,并使用尽可能少的假设和尽可能多的文档和单元测试,那么代码最终可能会做出意想不到的事情。
此外,如果发现并修复了错误,或者添加了功能,这些更改很少会返回到源代码,从而导致重用代码出现不同版本,而没有人知道或理解。

解决办法是:
1.设计和编写代码时不仅要考虑一个项目,还要考虑未来的需求,并尝试使设计足够灵活,以最少的代码更改来覆盖它们。
2.将代码包含在按原样使用的库中,而不是在使用项目中进行修改。
3.允许用户查看和修改库的代码 它是 解决方案(不在使用项目的解决方案内)。
4.根据现有基础设施设计未来的项目,并根据需要对基础设施进行更改。
5.向所有项目收取基础设施维护费用,从而保持基础设施的资金支持。

您或您的公司是否尝试重用代码?如果是这样,如何以及在哪个级别,即低级 API、组件或共享业务逻辑?您或您的公司重复使用代码如何?

我曾经在一个具有 uber 代码重用的代码库中工作,但由于重用的代码不稳定,因此很难维护。它很容易发生设计变更和弃用,从而级联到使用它的所有东西。在此之前,我在一个没有代码重用的代码库中工作,前辈们实际上鼓励复制和粘贴作为重用甚至是特定于应用程序的代码的一种方式,所以我看到了两个极端,我不得不说一个不一定太多当采取极端时,比另一个更好。

我曾经是一个超级自下而上的程序员。你要求我构建一些特定的东西,而我最终构建了通用的工具。然后使用这些工具,我构建更复杂的通用工具,然后开始构建 DIP 抽象来表达较低级别工具的设计要求,然后我构建更复杂的工具并重复,在某个时候我开始编写实际执行的代码你要我做什么。尽管这听起来适得其反,但我的速度相当快,并且可以以真正令人惊讶的方式交付复杂的产品。

问题是几个月、几年的维护!在我一层又一层地构建这些通用库并重用它们之后,每个库都想服务于比您要求我做的更伟大的目的。每一层都想解决世界的饥饿需求。所以每个人都非常雄心勃勃:一个想要变得令人惊叹并解决世界饥饿需求的数学图书馆。然后是建立在数学库之上的东西,比如几何库,它想要变得惊人并解决世界的饥饿需求。当您尝试交付产品时,您知道出了问题,但是当您应该处理动画时,您的思绪却在思考您的超级通用几何库在渲染和建模方面的表现如何,因为您正在处理的动画代码需要一些新的几何函数。

平衡每个人的需求

我发现在设计这些超通用库时,我必须痴迷于每个团队成员的需求,并且我必须学习光线追踪如何工作,流体动力学如何工作,网格引擎如何工作,逆运动学如何工作,角色动画工作等等。ETC。ETC。我必须学习如何完成团队中几乎每个人的工作,因为我在设计这些超级通用库时平衡了他们的所有特定需求,而我在走钢丝时平衡了所有代码重用的设计妥协行为(尝试让鲍勃的工作变得更好,鲍勃正在使用其中一个库,但又不会对正在研究物理的约翰造成太大伤害,约翰也在使用它,但又不会使库的设计过于复杂化,让他们都高兴)。

到了这样的地步,我试图用策略类参数化边界框,以便它们可以存储为一个人想要的中心和半尺寸,或者其他人想要的最小/最大范围,并且实现真的变得很复杂快速尝试疯狂地满足每个人的需求。

委员会设计

而且因为每一层都试图满足如此广泛的需求(比我们实际需要的要广泛得多),所以他们发现了很多需要更改设计的原因,有时是委员会要求的设计(这通常有点恶心)。然后这些设计更改将向上级联并影响使用它的所有更高级别的代码,并且此类代码的维护开始成为真正的 PITA。

我认为您可以在志同道合的团队中共享更多代码。我们的志趣根本不一样。这些都不是真实姓名,但我这里有 Bill,他是一位高级 GUI 程序员和脚本编写者,他创建了漂亮的用户端设计,但有很多 hack 的问题代码,但对于这种类型的代码来说通常是没问题的。我找到了鲍勃,他是一位老前辈,从打孔卡时代就开始编程,喜欢编写 10,000 行带有 goto 的函数,但仍然不明白面向对象编程的要点。我找到了乔,他就像一个数学奇才,但编写的代码没有其他人可以理解,并且总是提出数学上一致的建议,但从计算的角度来看不一定那么有效。然后我找到了迈克,他在外太空,希望我们将软件移植到 iPhone 上,并认为我们都应该遵循苹果的惯例和工程标准。

回想起来,试图满足这里每个人的需求,同时提出一个像样的设计可能是不可能的。当每个人都试图共享彼此的代码时,我认为我们变得适得其反。每个人在一个领域都有能力,但试图提出每个人都满意的设计和标准只会导致各种不稳定并减慢每个人的速度。

权衡

所以这些天我发现平衡是避免最低级别的代码重用。我可能会从中层使用自上而下的方法(这不是 与你要求我做的事情相去甚远),并在那里建立一些独立的图书馆,我仍然可以在短时间内完成,但该图书馆并不打算建立试图解决世界饥饿需求的迷你图书馆。通常,此类库的用途比较低级别的库要窄一些(例如:物理库,而不是广义几何交集库)。

YMMV,但如果说这些年来我以最艰难的方式学到了什么,那就是可能存在一种平衡行为,以及我们可能希望在团队环境中在某种粒度级别上刻意避免代码重用,放弃一些代码。有利于解耦的最低级代码的通用性,我们可以更好地塑造可延展的代码来满足更具体而不是普遍的需求,等等——甚至可能只是让每个人有更多的自由来按照自己的方式做事。当然,所有这一切的目的仍然是生成一个非常可重用的通用库,但不同之处在于该库可能不会分解为最小的通用库,因为我发现跨越某个阈值并试图制作太多从长远来看,小型、通用的图书馆实际上开始成为一种极其适得其反的努力——不是在短期内,而是在长期和广泛的计划中。

如果您有一件代码,可以在中型组织中共享,您将如何通知公司其他成员,该lib/api/etc存在并且可能有益?

实际上,这些天我更加不情愿,并且发现如果同事做一些多余的工作更可以原谅,因为我想确保代码做了一些相当有用且不平凡的事情,并且在我尝试分享之前也经过了充分的测试和设计与人相处,积累一堆依赖。如果我与团队的其他成员共享该设计,那么从那时起,该设计应该没有什么理由要求进行任何更改。

否则,它可能会造成比实际拯救的更多的悲伤。

我曾经非常不能容忍冗余(在代码或工作中),因为它似乎会转化为一个在内存使用方面非常有缺陷和爆炸性的产品。但我过多地将冗余视为关键问题,而实际上真正的问题是质量差、仓促编写的代码以及缺乏可靠的测试。即使有些人到处复制某些数学函数,经过良好测试、可靠、高效的代码也不会在很大程度上遇到这个问题。

需要注意并记住但我当时没有考虑的常识性问题之一是,当我们使用非常可靠的第三方库时,我们不介意一些冗余。你们很可能使用一两个第三方库,这些库与您的团队正在做的事情有一些多余的工作。但我们不介意这些情况,因为第三方库很棒并且经过了充分测试。我建议将同样的心态应用到您自己的内部代码中。我们的目标应该是创造一些很棒的、经过充分测试的东西,而不是像我很久以前错误地做的那样,为这里那里的一点点冗余而大惊小怪。

所以这些天我已经将我的不容忍转向缺乏测试。我发现,与其为多余的工作而感到沮丧,不如为其他人缺乏单元和集成测试而感到沮丧,这样更有成效!:-D

Maven解决了代码重用问题。我是认真的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top