我一直在工作中严格遵循DRY原则;每次我懒惰地重复代码时,它都会在以后需要在两个地方进行维护时再次出现。

但是我经常写一些需要可以在无法相互引用的两个项目中重用。该方法可能与联网/字符串/ MVVM等有关,并且是一种通用的有用方法,并不特定于它最初所在的项目。

重用此代码的标准方法是创建可重用代码的独立项目,并在需要时引用该项目。问题在于,我们最终遇到了两种不理想的情况之一:


我们最终得到了数十个/数百个小型项目-每个项目都容纳了小类/方法我们需要重用。仅需少量代码就可以创建一个全新的.DLL吗?
我们最终完成了一个项目,其中包含越来越多的不相关方法和类。这种方法是我曾经工作过的公司所做的。他们有一个名为base.common的项目,该项目包含用于我上面提到的事情的文件夹:网络,字符串处理,MVVM等。它非常方便,但是不必要地将它与所有不需要的无关代码一起拖动即可。
所以我的问题是:

软件团队如何最好地在项目之间重用少量代码?

我特别感兴趣,如果有人工作过在一家在这方面有政策的公司,或者像我本人亲自遇到过这个难题的公司。参考”来自Visual Studio .NET开发中的背景知识。但我确定此问题与语言和平台无关。

评论

+1,尽管我认为使用.NET的人中有些幽默的元素,它担心通过DLL引用拖动无关的代码。

@ColeJohnson .NET本身就是一个巨大的参考!可能比我自己制作的dll大得多。

我明白了。但是,.NET的JIT编译器仅将所需的方法加载到RAM中(当它们被调用时)

真正。尽管您仍然必须将整个.NET框架分发给想要使用您的产品的任何人,但是大型项目和复杂的解决方案更难以管理。

相关:什么时候“核心”库是个坏主意?

#1 楼

如果它们确实是可重用的方法/类,则可以将它们编写到少量的“瑞士军刀”库中。我们在公司经常这样做;我们称它们为框架库:



Framework.Data-用于处理数据库查询的实用工具。

Framework.ESB-与我们的企业服务总线交互的标准方法

Framework.Logging-统一日志系统

Framework.Services-与Web服务交互的实用工具

Framework.Strings-用于高级字符串处理/模糊字符串搜索的实用工具
...

总共大约有十二个库。您可以按自己认为合适的方式分发代码,因此不必最终花费数百美元或将所有内容都转储到一个大型程序集中。我发现这种方法很合适,因为只有我们的某些项目需要Framework.Data,而只有少数项目需要Framework.Strings,因此消费者只能选择与特定项目相关的框架部分。它们实际上只是片段,而不是可以轻松地重用的实际方法/类,您可以尝试将它们作为代码片段分发到IDE中(例如,Visual Studio代码片段)。我过去与之合作的团队拥有一个通用的代码段库,这使每个人也更容易遵循我们的标准编码实践以及内部代码。

评论


+1这也是我的方法。有兴趣知道您如何决定从两个或多个方面决定将处理内容的代码放置在何处。例如IPAddressToString。以及是否允许这些库互相使用。例如,服务和数据可能会从日志中受益匪浅...

– Marjan Venema
13年3月30日在16:38

@MarjanVenema对于跨领域代码,取决于哪些消费者会发现该方法更有用。对于IPAddressToString,处理网络协议的使用者可能必须使用它,但是对字符串进行大量摆弄的使用者可能根本不关心IP地址。那可能最终会出现在网络包中,而不是Framework.Strings中。

– p.s.w.g
2013年3月30日16:50



@MarjanVenema我们尝试避免相互依赖。我们的服务和数据框架以这样的方式编写:它们自己不进行任何日志记录,但是使消费者更容易编写适当的日志记录代码。允许框架库相互引用,但只能通过扩展名进行引用-例如Framework.Logging.Gibraltar是日志记录系统的特定附加组件。

– p.s.w.g
13年3月30日在16:52

+1您可以使用这些框架库并将它们部署到内部的NuGet存储库(就像网络文件夹一样简单),并且您有很好的管理方式。

–史蒂文·埃弗斯(Steven Evers)
13年3月30日在17:22

@SteveEvers我现在正在实际进行设置。 :P

– p.s.w.g
13年3月30日在17:28

#2 楼

我出于很多原因不同意接受的答案。

根据我的经验,当我看到像“接受的答案”这样的“杂类”库时,它们是重新发明轮子的借口(或者不是在这里发明的(NIH) ))-比违反“不要重蹈覆辙”(DRY)更大的罪过。与良好的面向对象设计相比,重用是次要问题。一点重复(我的意思是小数目,应用三则规则)比意大利面条式的代码库更容易理解。

众多通用库的方法树立了一个不好的榜样。这会导致程序集的粒度太细,并且太多的程序集是不好的。我最近将内部图书馆从24个减少到6个。它将编译时间从几分钟缩短到了约20秒。 Visual Studio的加载速度也较慢,并且对更多程序集的响应速度较慢。库太多会导致代码应存放在哪里。偏好更少,更简单的规则。

为什么.Net Framework中的内容不够好?该框架很大。很多次,我都看到了代码可以重新实现已经存在的代码。确实要确保您的框架填补了.Net框架中的空白,并且出于美观原因而没有存在(例如,“这里我不喜欢.Net框架”或某些过早的优化)。

在体系结构中引入另一层会花费大量的复杂性。为什么该层存在?我已经看到了错误的重用,这意味着代码是建立在内部框架之上的。直接在标准库之上实现它会更加有效。

使用标准化技术(例如.Net框架和流行的第三方/开放源代码库)所带来的好处通常超过了自己构建它的相对技术收益。更容易找到了解这些技术的人才,您现有的开发人员将在学习它方面投入更多。 。
如果有凝聚力,请创建一个新库,不要使用泥泞的设计模式。
请尽可能重用现有的第3方库。
请使用较少的程序集,并在哪里使用更简单的规则代码应该有效。


评论


使用开源库(如果有)的附带好处-如果您提出了一些改进,可以将其共享给社区!例如,.Net MS发行了一个EnterpriseLibrary(现在为Open Source),其中提供了一套非常好的用于常见方案的工具,在那儿找到可以改进的地方,嘿!大家受益!

–旋转加速器
2013年9月18日15:58

在这里,我并没有真正不同意接受的答案:-)。 “更少的程序集,关于代码应该存放在哪里的规则更简单”与公认的答案并不矛盾。答案还主张只使用看起来合理的尽可能多的不同程序集。

–sleske
13年10月2日,12:31

#3 楼

对于少量代码(例如,一个没有依赖性的类),我们倾向于将代码复制并粘贴到项目中。这听起来像是违反了DRY,但我承认有时可能如此。但是从长远来看,由于一些原因,它比拥有某种大规模的,多头的公地项目要好得多。

首先,使代码更方便使用,尤其是在构建和调试东西时。

其次,您总是需要对通用代码进行一些调整该项目的代码。如果您拥有源的本地副本,则可以进行调整并每天进行调整。如果有一个共享库,那么您可能要对该库进行调整,然后确保您不会破坏所有其他应用程序或造成版本控制噩梦。

因此,如果它不够强大因为它是自己的名称空间,所以我们倾向于将其放入项目中的相应位,并称之为一天。

评论


我不同意这种方法。我感谢管理小段代码时遇到的维护问题,但我认为可以使用@ p.s.w之类的东西来创建一些通用库。在暗示。在代码中进行细微调整的重复副本会带来麻烦。将进行假设,错误修复将丢失。

– Andrew T Finnell
2013年6月23日13:05

-1(答案)。让每个人都拥有自己的程序版本的副本当然更容易。这就是80年代开发软件的方式。从那以后,我了解到,长期来看,这会导致混乱。做正确的事并拥有一个公共图书馆比较困难,因为人们将不得不就他们的工作进行更多的交流。好吧,他们应该。

–迈克尔·杜兰特(Michael Durrant)
2013年6月23日15:09



+1-我认为值得一提的是,即使您不想经常使用这种方法。一些代码片段更像是设计模式-您将重用em,但是在各处(可能以不同的语言)都稍有不同,并且可能需要更改它们。而且,广泛复用的库是不灵活的,因为对其API的更改存在很大风险。最后,采用这种方法作为后备方法,可以通过将实验性内容保留较长时间来提高共享库的质量。

–Eamon Nerbonne
13年6月24日在21:58

#4 楼

您描述的第二种解决方案还不错。在.NET中,即使您只使用一个单一类,也要引用GAC中的程序集。 “拖动无关的代码”并不是您可能认为的问题。在这种情况下,至关重要的是,至少要在不同的名称空间中将相关的方法和类保持整洁的组织。此外,还应采用API设计的良好做法,以防止此解决方案变得一团糟。在不同的解决方案中重复。像最佳做法一样对待它们:记录并与团队沟通。

评论


除了对于非标准库而言,这意味着仅由于一次(或很少)使用就必须装运大型程序集。对于标准的东西来说这不是一个问题,因为无论如何都可以使用,但是如果可以很好地拆分它,我绝对会避免运送大型但大部分未使用的程序集。

–戳
13年3月31日在4:40

#5 楼

我只曾在“企业”环境中工作过,在这种情况下,这种事情一直是一个问题,并且每次它都成为被采用的第二种选择。在大多数情况下,它都可以正常工作,因为应用程序占用空间没有任何限制。建议将其作为可行的替代方案。当然,我期望出现的问题将与发现能力有关。

如果项目适当地精细且名称空间合理,那么我可以看到这已成为流行的方法。

评论


在什么意义上,您期望它们不会被发现?我们以这种方式使用大量且不断增长的nuget包。我们面临的最大问题是管理版本控制和依赖关系。

– pdr
2013年3月30日16:09

是的。那些也一样。关于可发现性的问题,我的意思是,给定足够数量的具有特定功能的小包装,可能很难对每个小包装进行分类(查找)。例如,您的团队如何得知哪些软件包包含各种功能? (此处显示nuget搜索的无知)

–科菲·萨尔夫(Kofi Sarfo)
13年3月30日在18:16

哦,我懂了。是的,您绝对可以在说明中放入您喜欢的任何内容,并且可以进行搜索,但是我认为我们已经对软件包进行了很好的分组,这似乎没有问题。

– pdr
13年3月30日在18:24

@sarfeast如果您可以共享一个指向任何Nuget服务器的链接,并对其进行一些介绍,那就太好了。

–汉斯·彼得·斯托尔
13-4-2在11:02



#6 楼

最近我想到了这一点,我想到的是一个庞大的通用方法库,到目前为止已经提到过,但有一点曲折。该库项目将允许您在编译时配置其中包含的部分,类似于BusyBox项目。通过这种方法,您可以拥有一个厨房水槽样式的库回购,但是只能抓住编译时所需的工具。

#7 楼

GitHub有一个非常有用的工具来保存代码段https://gist.github.com/

它将您的代码段存储为git存储库,您可以将其保存为私有,或用于与他人共享代码段。

#8 楼

我遇到了很多问题,我更喜欢的解决方案是将代码发布到github / pubic基于Web的存储库中。它解决了很多问题-


易于访问且易于共享。 cvs / svn / enterprise-repos的意思是将项目检出到多个IDE工作区中,有时甚至不得不切换工作区或计算机以仅引用一个小的代码段。并且是可公开获得的知识的变体,将它们发布在github之类的公共仓库中意味着其他人会关注它,甚至可能会做出贡献。
以您的名字在公共领域发布内容会增加声誉压力。您将仔细检查并更新内容,因为它反映出您作为程序员的能力。
更新。关于在仓库中维护代码段的事情是,如果很长时间未使用代码段,它可能会过时(包含过时的api / lib)。示例-读取文件的Java代码段。您可能已经在2009年找到了实现此目的的最佳方法,但是在2014年,出现了一个新的文件api,它会改变一切。您的摘要?仍然停留在2009年。在公共存储库中,您(由于项目符号3),您的队友或普通程序员中的某些成员会更新所有内容,在此过程中,您甚至可能会得到建议以解决某些问题您可能已经做错了很长时间了。事情总是在变化。节省了代码片段,既节省了时间,又滋生了自满。

#9 楼

视团队/项目/公司的规模而定,这将是一件相当困难的事情,除非它已经以某种方式内置到您的环境中,并且您发现的每个解决方案(如果实施)都会花费一些钱。 (这可能会使您更加安全,但将无法轻松进行测量)。您必须检查它是否值得。同样要记住,可重用的解决方案往往会变得抽象,并且通常会适合许多情况,但并不是最优的。

无论如何,如果您想对多个人生成的代码执行此操作人,首先,您需要每个人的意识和合作。这包括开发人员和管理人员。

然后,您需要确保知道要执行此操作的范围。球队?项目?部门?公司?根据答案的不同,将在此类解决方案中使用的代码类型也将有所不同,调整dll的粒度也会有所不同。一旦您决定了这个人(最好是对这个想法充满热情-您呢?)就应该坐下来,开始对此进行一些调整。

创建此类dll不足以解决问题。为了使它们有用,您需要(向用户和贡献者)进行广告宣传,并像其他任何软件一样对其进行维护,这通常意味着您需要长期负责他们。您还将需要可靠的文档,这也将需要维护。有了一些运气和合作,您可能会得到一些最佳实践,但是根据参与团队的规模和数量,它也可以轻松地发展成为一个自己的项目。因此,您仍然需要管理支持。

#10 楼

我们有一个单独的项目“实用程序”,其中将所有这些小方法与测试存储在一起。

当项目需要一些实用程序时,它只需使用“添加为链接”所需的方法添加源文件。

这意味着没有添加运行时依赖项(除非包含的文件需要一个)。

系统运行良好,但是像其他系统一样,它需要关于实用程序的专业知识。要求高测试覆盖率对我们来说效果很好,测试也是很好的用法文档。发现对我们来说仍然是一个未解决的问题。

该实用程序项目的一个复杂性是确定项目的可见性级别。一条经验法则是方法应该是内部的,数据结构应该是公共的。

#11 楼

我的公司使用Intranet本地Web服务。我们有一些Web服务被设置为常见的内部Web服务,当另一个项目需要访问其中一个服务时,它会通过定义的接口发送一个http请求。由于它位于企业服务器上的Intranet上,因此这些请求非常快。它有一些非常好的优点。

#12 楼

我最近想出了这项服务:Snip2Code(http://www.snip2code.com)。

这是一种有趣的方式,可以与团队仅共享您的代码片段(不完全是库)。这打破了创建应在其他项目中引用的公共库的通常观点,并且我认为这是一个宝贵的愿景。此外,在很多情况下都使用了公共库根本不适用:例如,让我们考虑一些设计模式,例如Singleton,Strategy或Observer。您可以创建库来支持这种模式,但是仍然没有100%的覆盖率。

真正的需求是拥有一个在团队中共享通用实践的工具。我尝试使用Github的要点,但我一直坚持寻找它们(确实很差),而且我不能只在我的团队中共享它们,而不能与其他团队共享...

(免责声明:我是Snip2Code的创始人之一,而我-和我的联合创始人-早在同一时间就曾是同一心态:这就是为什么我们决定开始这个项目的原因!)