C# 为什么 Visual Studio 中的循环引用是不好的做法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/308915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why are circular references in Visual Studio a bad practice?
提问by pian0
Why are circular references in Visual Studio a bad practice?
为什么 Visual Studio 中的循环引用是不好的做法?
First, I will describe an example of how this can happen using C# in Visual Studio, since VS will typically inform you if you have a circular reference and prevent it.
首先,我将描述一个如何在 Visual Studio 中使用 C# 发生这种情况的示例,因为 VS 通常会通知您是否有循环引用并阻止它。
First, a Utilitiesclass is created relying only on the code given to you by Visual Studio and .Net. Then, an E-mailclass is created that depends on Utilities. Instead of adding both projects to a single solution, a new solution is created and a reference to Utilities.dllis added. Then, some time later, someone decides that they want the Utilitiesclass to send an e-mail and adds a reference to Email.dll. Visual Studio is perfectly happy to let you do this, but now the source won't compile as-is without one of the binaries.
首先,仅依赖于 Visual Studio 和 .Net 提供给您的代码创建了一个Utilities类。然后,创建一个依赖于Utilities的E-mail类。不是将两个项目添加到单个解决方案,而是创建一个新解决方案并添加对Utilities.dll的引用。然后,一段时间后,有人决定让Utilities类发送电子邮件并添加对Email.dll的引用。Visual Studio 非常乐意让您这样做,但现在如果没有二进制文件之一,源代码将无法按原样编译。
At my place of work it is standard procedure to copy-and-paste binaries when doing development and then only building the projects you're working on. This has led to at least one circular reference in the codebase that has gone unnoticed for over 3 years.
在我的工作场所,在进行开发时复制和粘贴二进制文件是标准程序,然后只构建您正在处理的项目。这导致代码库中至少有一个循环引用被忽视了 3 年多。
This seems like a very bad practice to me because there is no way to build either project from source without having the DLLs first. That argument falls a little flat to the "practical" people I work with since it seems highly unlikely that we will lose all copies of our binaries simultaneously. The binaries aren't stored in version control at any point, which only makes me more worried.
这对我来说似乎是一个非常糟糕的做法,因为如果不先拥有 DLL,就无法从源代码构建任何一个项目。对于与我一起工作的“实际”人员来说,这个论点有点平淡,因为我们同时丢失所有二进制文件的副本似乎不太可能。二进制文件在任何时候都不会存储在版本控制中,这只会让我更加担心。
This seems like a situation that should be avoided, but not a situation that poses any appreciable threat. Are circular references between projects really a big deal or am I blowing it out of proportion?
这似乎是应该避免的情况,但不是构成任何明显威胁的情况。项目之间的循环引用真的很重要还是我夸大其词?
采纳答案by Peter T. LaComb Jr.
Yes, this is a bad practice for precisely the reason you've stated - you cannot rebuild from the source.
是的,正是出于您所说的原因,这是一种不好的做法 - 您无法从源代码重建。
回答by Vinko Vrsalovic
The question I would pose to your coworkers is:
我要向你的同事提出的问题是:
Okay, it is very unlikely we'll lose all our binaries at the same time. But, tell me, what's the benefit of this approach?
好的,我们不太可能同时丢失所有二进制文件。但是,告诉我,这种方法有什么好处?
If they come with anything different than "We've always done it this way", I'd like to hear it. And, as everybody knows "we've always done it this way" is NOT a good reason and they shouldn't defend it.
如果他们有什么不同于“我们一直这样做”的东西,我想听听。而且,众所周知,“我们一直都是这样做的”不是一个很好的理由,他们不应该为它辩护。
回答by Alex Lim
Hm, I think in terms of the OP question, about buildingprojects from scratch, it is bad practices, due to:
嗯,我认为就 OP 问题而言,关于 从头开始构建项目,这是不好的做法,因为:
- Inability to build from source / scratch - What if I maintain several versions of code. Between each version, a few changes to each of the libs have been made.. The only way I can feasabily maintain these concurrent versions, is to now store the compiled binaries in my version control. This also means comparisons between each library version is that much harder. (I need to find out, what version is being used, then go look at the actual source code for the lib, rather than just a direct diff on the source itself.
- Possibly harder to push out patches to customers which have incrementally patched versions.. Where and what to patch?
- 无法从源代码/从头构建 - 如果我维护多个版本的代码怎么办。在每个版本之间,对每个库进行了一些更改。我可以切实维护这些并发版本的唯一方法是现在将编译后的二进制文件存储在我的版本控制中。这也意味着每个库版本之间的比较要困难得多。(我需要找出正在使用的版本,然后查看 lib 的实际源代码,而不仅仅是源本身的直接差异。
- 可能更难将补丁推送给具有增量补丁版本的客户。在哪里打补丁,打什么补丁?
回答by Corbin March
Aside from build issues, circular references always indicate a design flaw. In .NET, a circular relationship makes two assemblies effectively one assembly. If neither one can live on its own without the other, building them separately is just an exercise - it doesn't change the fact that together they represent a monolithic assembly.
除了构建问题之外,循环引用始终表示设计缺陷。在 .NET 中,循环关系使两个程序集有效地成为一个程序集。如果没有另一个人都不能独立生活,那么单独构建它们只是一种练习 - 它不会改变它们一起代表一个整体组件的事实。
I've noticed this a lot with utility assemblies. Must be an anti-pattern.
我在实用程序集上注意到了很多。必须是反模式。
回答by Steven A. Lowe
circular dependencies are bad because:
循环依赖是不好的,因为:
- project A references project B
- when project B changes, project A needs to be rebuilt
- now if project B also references project A
- then when one of them changes, the other one needs to be rebuilt
- which causes the other one to need to be rebuilt
- which causes the other one to need to be rebuilt
- etc.
- 项目 A 引用项目 B
- 当项目B发生变化时,需要重新构建项目A
- 现在如果项目 B 也引用了项目 A
- 那么当其中一个发生变化时,另一个需要重建
- 这导致另一个需要重建
- 这导致另一个需要重建
- 等等。
this is potentially an infinite-loop in the build process
这可能是构建过程中的无限循环
回答by benjismith
This is one of the symptoms of over-modularization.
这是过度模块化的症状之一。
I worked at a company once with about twenty developers and more than sixty different active projects in the SVN repository. Every project had its own build script and produced a JAR file that was a dependency of at least a half-dozen or so other projects. Managing all those dependencies was so complicated that we wasted a ton of time trying (unsuccessfully, I might add) to set maven projects to automatically fetch all the correct libraries (and the correct versions) for all those little micro-projects.
我曾经在一家公司工作,有大约 20 名开发人员和 SVN 存储库中的 60 多个不同的活动项目。每个项目都有自己的构建脚本,并生成一个 JAR 文件,该文件是至少六个左右其他项目的依赖项。管理所有这些依赖关系非常复杂,以至于我们浪费了大量时间尝试(不成功,我可能会补充)设置 maven 项目以自动获取所有这些小微项目的所有正确库(和正确版本)。
The funny thing (to me) was that it was really only one project, and it wasn't even something we distributed to the outside world. It was a hosted application, with a web front-end, running on a single server cluster.
有趣的是(对我来说)它实际上只是一个项目,它甚至不是我们分发给外界的东西。它是一个托管应用程序,具有 Web 前端,运行在单个服务器集群上。
Sheesh.
嘘。
Another side-effect of the architecture was that the same kinds of functionality got duplicated over and over again (not always with the same algorithms, or results, for that matter) in several different projects. I think part of the reason was because people didn't want to introduce a new dependency on an entire sub-project just to get access to a few of its classes. But I think another reason was the people just didn't know what code existed where, and rather than go to the trouble of finding the code they wanted to reuse, they'd just rewrite it in their own project.
该架构的另一个副作用是相同类型的功能在几个不同的项目中被一遍又一遍地复制(并不总是使用相同的算法或结果)。我认为部分原因是因为人们不想仅仅为了访问它的一些类而引入对整个子项目的新依赖。但我认为另一个原因是人们只是不知道哪些代码存在于何处,与其费心寻找他们想要重用的代码,他们只是在自己的项目中重写它。
Of course, modularity is generally a good thing.
当然,模块化通常是一件好事。
But like all good things, it can be taken to ridiculous extremes.
但就像所有美好的事物一样,它也可以被带到荒谬的极端。
My advice is to find those circular dependencies and merge the projects into bigger chunks, since the current project breakdown probably represents a false modularity. Better to divide your big project into a few well-separated modules than to have a zillion pseudo-modules creating artificial boundaries between logically-coupled classes.
我的建议是找到那些循环依赖并将项目合并成更大的块,因为当前的项目分解可能代表了错误的模块化。将你的大项目分成几个分离良好的模块比让无数伪模块在逻辑耦合的类之间创建人工边界更好。
回答by EnocNRoll - AnandaGopal Pardue
Yes, it's a big deal, because it leads to unmanageable component compositions, and most likely some form of build errors and very likely some deployment errors, at some point in the project life cycle.
是的,这是一个大问题,因为它会导致无法管理的组件组合,并且很可能在项目生命周期的某个时刻出现某种形式的构建错误和一些部署错误。
Visual Studio 2008 explicitly prevents circular references between projects (not binaries) in solutions. As you have stated, that is not the case for binaries. I believe that is because VS2008 expects that binary references are managed independently and it expects that you are building those projects independently. Generally speaking, that means all binary references should be viewed as third-party components that represent a distinct one-way relationship (between your code and the binary).
Visual Studio 2008 明确防止解决方案中的项目(而非二进制文件)之间的循环引用。正如您所说,二进制文件并非如此。我相信这是因为 VS2008 期望二进制引用是独立管理的,它期望您独立构建这些项目。一般来说,这意味着所有二进制引用都应该被视为第三方组件,它们代表了一种独特的单向关系(在您的代码和二进制文件之间)。
Furthermore, MSBuild allows you to use the SLN file to build everything, if all your projects use VB or C#. This allows for the creation of an uber-solution file, which is ideal for an automated build process. The catch is that in order for such a master solution file to work, all of the projects in the SLN must utilize project references. Therefore, in order to take advantage of this, by definition, Microsoft expects that you are not employing circular references, since they are explicitly forbidden by the Visual Studio IDE (for project references).
此外,如果您的所有项目都使用 VB 或 C#,MSBuild 允许您使用 SLN 文件来构建所有内容。这允许创建 uber-solution 文件,这是自动构建过程的理想选择。问题在于,为了使这样的主解决方案文件起作用,SLN 中的所有项目都必须利用项目引用。因此,为了利用这一点,根据定义,Microsoft 希望您不要使用循环引用,因为它们被 Visual Studio IDE(用于项目引用)明确禁止。
Scott Hanselman makes reference to an uber-solution file in the following post:
Hack: Parallel MSBuilds from within the Visual Studio IDE
http://www.hanselman.com/blog/CategoryView.aspx?category=MSBuild
Scott Hanselman 在以下帖子中引用了一个 uber-solution 文件:
Hack: Parallel MSBuilds from the Visual Studio IDE
http://www.hanselman.com/blog/CategoryView.aspx?category=MSBuild
回答by Robert Jeppesen
If you're having trouble convincing your "pragmatic" colleagues that this is a bad practice, offer a pragmatic solution: Remove these circular references and build times will go down since loads of unnecessary rebuilding will be avoided.
如果您无法说服“务实”的同事这是一种不好的做法,请提供一个务实的解决方案:删除这些循环引用,构建时间将减少,因为将避免大量不必要的重建。