views:

722

answers:

10

Hi all,

We currently have a rapidly growing C# codebase. Currently we have about 10 projects, split up in the usual categories, common/util stuff, network layer, database, ui components/controls etc.

We run into the occasional circular dependency where project x depends on something in y and vice-versa. We are looking at maybe collapsing the projects down to one and just managing using structure folders/namespaces. We have a Java project which of course organises just using folders/packages so we're not sure what, if any, benefit having multiple projects brings. None of our projects require special project properties, except the main run project, which we may kept separate (and very thin).

Does anyone have any prior experience in why one project is better/worse than multiple projects and could suggest the best approach? And also any issues with circular dependencies would be useful in either approach would be useful.

Any input appreciated.

+20  A: 

If you've got projects with circular dependencies, that indicates a problem with the design of the code, not with the solution/project model.

Jon Seigel
Why so many up-votes. This isn't really helpful, except to say "you don't know what your doing" to someone asking a genuine question.
Owen
So many upvotes because it's right. Classes by themselves should provide a layer of abstraction of it's components. If two classes have a circular dependence, it makes very little sense to have the two in separate projects. Usually the component that both are dependent on needs to be extracted and placed on it's own.
Will Eddins
I'm also surprised about the upvotes. @Will: You are right, of course, but that doesn't make Jon's answer more useful...
Heinzi
There is also circular dependency between System.Xml.dll and System.Configuration.dll
lubos hasko
This wasn't intended to be hostile. Merely that in this situation, it seemed that switching the solution/product structure was going to be done for the wrong reasons. As for all the upvotes, I dunno, that's up to the community. <shrug>
Jon Seigel
The point is that merging projects just to keep circular dependencies from bothering the build system is hiding your problems, not resolving them. The proper resolution is to refactor the code into a sensible acyclic project structure; this will always improve understandability, testability and hence maintainability in the long run.
reinierpost
A: 

Multiple projects allows better reuse of specific types within multiple applications. It can also improve build time, since certain projects will not need to be rebuilt for all code changes.

A single project makes life easier, since you don't have to worry about dependencies. Just realize that the ease comes at a cost - it also makes it easier to let poor design decisions creep into the code base. Circular dependencies, whether in one project or multiple, are typically a design flaw, not a requirement.

Reed Copsey
+8  A: 

When making dependencies between projects, it helps to always think of one as "Lower" and the other as "Higher"

A higher level project (such as a web interface) should only depend on lower projects. A lower project (such as a utility) should never depend on something higher, such as a web interface. If this happens, it either means your higher level project has something that really should be in the lower project, or vice versa.

Neil N
A: 

Start with single project. The only benefit in splitting your codebase into more projects is simply to improve build time.

When I have some reusable functionality that I really want to isolate from main project, I'll just start brand new solution for it.

lubos hasko
-1 While there is truth to what you say it's not the entire picture.
Chuck Conway
I don't find concept of projects within solution useful, putting individual layers into separate folders is equally working for me and for millions of others who are using happily other programming languages.
lubos hasko
+1  A: 

In my experience, separating code which creates a single executable in multiple projects can be useful if you want to

  • use different programming languages in different parts,
  • develop libraries that are also used by other applications, or
  • conceptually separate multiple layers (i.e., let Visual Studio ensure that there are no direct references from project Lib to project App).

Personally, I base most of my decisions on the second point. Do I think that part of the application can be a more general library that I am likely to need in other application? Put it in a separate project. Otherwise, as you point out, having a single project usually makes development easier.

About the circular dependencies: The recommended way to solve this is to put interfaces of the referenced stuff into a third project. For example, if you have two applications both sharing some objects through remoting, you put interfaces of the shared objects in a library project to ensure that they are available to both applications.

Without knowing the exact design of your application, it's difficult to give more concrete advise.

Heinzi
Thanks for the feedback. Especially the interfaces idea to solve circular dependencies sounds like a good solution to my issues.
Mike Q
+2  A: 

We've noticed that Visual Studio's performance degrades significantly as the number of projects grows. Something as simple as switching from 'Debug' to 'Release' configurations can takes upwards of 15 seconds for solutions with around a dozen C# projects in them.

Also, as a counter point to Reed's comment about build times, I've seen build times grow because Visual Studio seems to be spending a lot of time on the project overhead. The actual compile times seem fast, but the total time from hitting build to being able to run is significant.

My advice would be keep the number of projects to the minimum you can get away with. If you need multiple projects for good reasons then use them as necessary, but prefer to keep things together. You can also refactor to split a project into two if necessary.

Rob Walker
Interesting point on the build time. While not super important, waiting for builds does tend to stall development at the most critical time, when I'm in the groove :) So that is useful to know thanks.
Mike Q
+1  A: 

There are several reasons for separating a solution into different projects (and thus assemblies), and it mainly comes down to re-usability and separation of responsibilities.

Now your goal should be to make an assembly (aka project) has the minimum amount of dependencies on other assemblies in your solution, otherwise you may as well have everything in fewer assemblies. If for example your UI components have a strong dependency on your data access code then there is probably something wrong.

Really, this comes down to programming against common interfaces.

Note However:

When I say "otherwise you may as well have everything in fewer assemblies", I wasn't necessarily suggesting this is the wrong thing to do. In order to achieve true separation of concerns your going to be writing a lot more code and having to think about your design a lot more. All this extra work may not be very beneficial to you, so think about it carefully.

Owen
+3  A: 

Generally speaking, having multiple VS projects (within a VS solution) does just make sense in these cases

  • You can potentially reuse the produced DLL in another project (a class library)
  • You want to separate things like in a layered architecture where you may drop the DAO dll and exchange it with another
  • There are just different front-end projects (i.e. ASP.net MVC apps) which need to be deployed in different physical locations but use the same BL, DAL.

If your saying you're having the problem of circular dependencies, then you're having a problem in your code design. Probably you may put that logic which is used by multiple projects inside a class library designed to be reused in many projects.

Generally I'd say you shouldn't add more projects if you don't really need it. Splitting up into projects means adding more complexity, so when you're doing so, you should gain a reasonable benefit from it.

Juri
Layers are also good for testing.
reinierpost
Indeed, if they're structured properly: http://goo.gl/TMDd
Juri
A: 

You might find the following Martin article worthwhile: Design Principles and Design Patterns (PDF)(Java).

A revised version in C# specifically is available in Agile Principles, Patterns, and Practices in C# also by Martin.

Both express different guidelines that will help you decide what belongs where. As pointed out, however, cyclic dependencies indicate that there are either problems with design or that something is in a component that belongs in a different one.

Stacy Vicknair
This is unrelated to agility though.
reinierpost
A: 

Hello,

Where I work, we opted for an approach where the aim is to have a single project per solution. All code library projects also have a test harness application and/or a unit test app.

As long as the code libraries pass testing, the release versions (with Xml Documentation file of course) get transferred into a “Live” folder.

Any projects that requires functionality from these other projects have to reference them from the “Live” folder.

The advantages are pretty clear. Any project always accesses known working code. There is never a chance of referencing a work in progress assembly. Code gets tested per assembly, making it far easier to understand where a bug originates. Smaller solutions are easier to manage.

Hope this helps!

Shad

Shad
Consider moving to the use of a version control system for this purpose.
reinierpost