颠覆外部是反模式吗?
通过Subversion,您可以使用外部工具来嵌入其他存储库的工作副本,从而可以轻松地对项目中的第三方库软件进行版本控制。
尽管这些对于库的重用和供应商软件的版本控制来说似乎是理想的,但他们并非没有批评他们:
请不要使用Subversion外部程序(或其他工具中的类似程序),它们是反模式的,因此是不必要的
使用外部存在隐藏的风险吗? 请解释他们为什么会被视为反模式。
我是这个问题中引用的作者,这个问题来自以前的回答。
贾森对我的简短陈述持怀疑态度,并要求解释。 当然,如果我完全解释了答案中的所有内容,我就需要写一本书。
Mike也正确地指出svn:external
like特性的一个问题是,目标源中的更改可能会破坏自己的源代码,尤其是当目标源位于不属于您的存储库时。
在进一步解释我的评论时,首先让我说,与其他任何工具或功能一样,使用svn:external
like特性有“安全”的方法。 但是,我将其称为反模式,因为该功能更可能被滥用。 根据我的经验,它一直被滥用,我发现自己不太可能以安全的方式使用它,也不会推荐使用它。 请进一步注意我的意思是不要贬低Subversion团队 - 我喜欢Subversion,尽管我打算前往Bazaar。
这个特性的主要问题是鼓励它,它通常用于直接将一个构建源(“project”)与另一个构建源相链接,或将项目链接到二进制文件(DLL,JAR等)它依赖于它。 这些用途都不是明智的,它们构成反模式。
正如我在其他答案中所说的那样,我认为软件构建的一个基本原则是每个项目只能构建一个二进制或主要可交付成果。 这可以被认为是关注点分离到构建过程的原则的应用。 在一个项目中直接引用另一个项目的来源尤其如此,这也违反了封装原则。 这种违规的另一种形式是试图创建一个构建层次结构,通过递归调用子构建来构建整个系统或子系统。 Maven强烈鼓励/实施这种行为,这是我不推荐它的许多原因之一。
最后,我发现存在各种实际问题,导致此功能不可取。 首先, svn:external
具有一些有趣的行为特征(但目前的细节让我不知所措)。 另一方面,我总是发现我需要这样的依赖关系对我的项目(构建过程)是明确可见的,而不是作为一些源控制元数据而被隐藏。
那么,什么是使用此功能的“安全”方式? 我认为只有当一个人临时使用它时,比如“配置”工作环境的方式。 我可以看到程序员可以在存储库中创建自己的文件夹(或者每个程序员都可以创建一个文件夹),在那里他们将配置svn:external
链接到他们目前正在处理的存储库的其他各个部分。 然后,结帐该文件夹将创建所有当前项目的工作副本。 当添加或完成一个项目时,可以调整svn:external
定义并适当更新工作副本。 但是,我更喜欢一种不与特定源代码管理系统绑定的方法,例如使用调用签出的脚本执行此操作。
对于这个记录,我最近接触到这个问题是在2008年夏天发生在一个大规模使用svn:external
的咨询客户端 - 所有事物都被交叉链接以产生一个主工作副本。 他们的基于Ant和Jython(用于WebLogic)的构建脚本是建立在这个主工作副本之上的。 最终的结果是:没有任何东西可以单独建造,实际上有几十个子项目,但是没有一个可以安全地自行结账/工作。 因此,在这个系统上的任何工作首先需要超过2GB的文件的检出/更新(它们也将二进制文件放入存储库中)。 做任何事情都是徒劳的,我试了三个月后就离开了(还有很多其他的反模式)。
编辑:阐释递归构建 -
多年来(尤其是过去十年),我为财富500强公司和大型政府机构建立了庞大的系统,涉及许多子目录,这些子项目安排在许多级别的目录层次结构中。 我已经使用Microsoft Visual Studio项目/解决方案来组织基于.NET的系统,Ant或Maven 2用于基于Java的系统,并且我已经开始为基于Python的系统使用distutils和setuptools(easyinstall)。 这些系统通常还包括Oracle或Microsoft SQL Server中的大型数据库。
为了易用性和可重复性,我在设计这些大规模构建方面取得了巨大成功。 我的设计标准是,新开发人员可以在第一天出现,获得新的工作站(可能直接来自戴尔,只需安装一个典型的操作系统),可以获得一个简单的安装文档(通常只有一页安装说明),并且能够完全设置工作站并从源代码,无人监督,无辅助以及半天或更短时间内构建完整系统。 调用构建本身涉及到打开命令shell,切换到源代码树的根目录,并发出一行命令来构建一切。
尽管取得了这样的成功,但构建这样一个庞大的构建系统需要非常谨慎和密切遵守坚实的设计原则,就像构建一个大规模的关键业务应用程序/系统一样。 我发现一个关键的部分是每个项目(产生一个工件/可交付物)必须有一个构建脚本,它必须有一个定义良好的界面(调用构建过程的一部分的命令),它必须单独来自所有其他(子)项目。 从历史上看,建立整个系统很容易,但是很难/不可能只建立一块。 直到最近我才学会了认真确保每个项目真正独立。
实际上,这意味着必须至少有两层构建脚本。 最底层是产生每个可交付物/工件的项目构建脚本。 每个这样的脚本都驻留在其项目源代码树的根目录中(实际上,这个脚本定义了它的项目源代码树),这些脚本对源代码控制一无所知,他们期望从命令行运行,它们引用项目中的所有相关到构建脚本,并且它们基于几个可配置的设置(环境变量,配置文件等)引用它们的外部依赖关系(工具或二进制工件,没有其他源项目)。
第二层构建脚本也可以从命令行调用,但是这些知道源代码控制。 事实上,第二层通常是一个用项目名称和版本调用的单个脚本,然后将指定项目的源检出到新的临时目录(可能在命令行中指定)并调用其构建脚本。
可能需要更多变体以适应持续集成服务器,多平台和各种发布方案。
有时需要第三层脚本来调用第二层脚本(调用第一层),以便构建整个项目集的特定子集。 例如,每个开发人员都可以有自己的脚本来构建他们今天正在开发的项目。 可能有一个脚本来构建一切,以便生成主文档或计算指标。
无论如何,我发现试图将该系统视为项目层次结构是适得其反的。 它将项目彼此联系在一起,以便它们不能单独自由地构建,也不能在任意位置(持续集成服务器上的临时目录)或任意顺序(假定依赖性得到满足)自由构建。 通常,试图强制一个层次结构会破坏可能尝试的任何IDE集成。
最后,构建一个庞大的项目层次结构可能会过于耗费性能。 例如,在2007年的春天,我尝试使用Ant构建的适中的源层次结构(Java和Oracle),最终因为构建始终因Java OutOfMemoryException异常终止而失败。 这是在一个2 GB的RAM工作站上,我已经调整了JVM能够使用所有可用内存的3.5 GB交换空间。 就代码量而言,应用程序/系统是相对微不足道的,但递归构建调用最终会耗尽内存,无论我给了多少内存。 当然,它也需要永久执行(30-60分钟是常见的,在它中止之前)。 我知道如何调优,但最终我只是超越了工具的限制(在这种情况下是Java / Ant)。
因此,请帮助自己,将构建作为独立项目构建,然后将其构建为完整系统。 保持轻盈灵活。 请享用。
编辑:更多关于反模式
严格地说,反模式是一种常见的解决方案,它看起来像解决问题但不是,因为它留下了重要的差距,或者因为它引入了额外的问题(通常比原始问题更糟糕)。 一个解决方案必然涉及一个或多个工具以及将它们应用于手头问题的技术。 因此,将工具或工具的特定功能称为反模式是一种延伸,而且似乎人们正在检测这种情况并对其做出反应 - 这足够公平。
另一方面,由于在我们这个行业中似乎常见的做法是专注于工具而不是技术,所以它是引起注意的工具/特征(对StackOverflow中的问题的一个偶然调查似乎很容易说明)。 我的评论和这个问题本身反映了这种做法。
然而,有时似乎特别有理由进行这种拉伸,例如在这种情况下。 有些工具似乎“引导”用户使用特定的技术,以至于有些人认为工具塑造了思想(稍微改写了一下)。 我主要以这种精神建议svn:external
是一个反模式。
为了更严格地说明问题,反模式将设计一个构建解决方案,其中包括在源代码级将项目捆绑在一起,或者隐式地版本化项目之间的依赖关系,或者允许这些依赖项隐式更改,因为这些调用都非常负面后果。 svn:external
的性质svn:external
特征使得避免这些负面后果非常困难。
正确处理项目之间的依赖关系涉及解决这些动态问题以及基本问题,并且这些工具和技术会导致不同的途径。 应该考虑的一个例子是常春藤,它以类似于Maven的方式提供帮助,但没有很多缺点。 我正在研究Ivy与Ant结合,作为我对Java构建问题的短期解决方案。 长期来看,我期待将核心概念和功能整合到一个开源工具中,以促进多平台解决方案。
我不认为这是一种反模式。 我在谷歌上做了一些快速搜索,基本上没有发现任何东西......没有人抱怨说使用svn:externals是坏的或有害的。 当然,你必须注意一些注意事项...并且这不是你应该只是大量地投入到所有仓库中的东西......但对于原始报价,这只是他个人(和主观)的观点。 他从来没有真正讨论svn:externals,除了谴责他们是一种反模式。 这种全面的陈述没有任何支持,或者至少没有理由说明这个人是如何发表陈述的,这总是令人怀疑。
这就是说,使用外部存在一些问题。 就像Mike回答的那样,他们可以非常有用地指向已发布软件的稳定分支,尤其是已经控制的软件。 我们在许多实用程序库等项目的内部使用它们。 我们有一个小组可以增强并在实用程序库基础上工作,但该基本代码将在多个项目中共享。 我们不希望各种团队只检查公用事业项目代码,我们也不想处理100万个分支机构,所以对我们来说svn:externals工作得很好。 对于一些人来说,他们可能不是答案。 但是,我强烈反对“请不要使用...”这种说法,并且这些工具代表了反模式。
使用svn:externals的主要风险是引用的存储库将以破坏代码或引入安全漏洞的方式进行更改。 如果外部存储库也在您的控制之下,那么这可能是可以接受的。
就我个人而言,我只使用svn:externals指向我拥有的存储库的“稳定”分支。
链接地址: http://www.djcxy.com/p/6397.html