views:

1100

answers:

3

I've got a question about references between projects in a solution. Most of my previous applications have just had one or two projects in the Solution, but this time I want to divide the application further.

I'm starting a new Solution in Visual Studio 2008 now, and have created several underlying projects to divide the separate parts of my application.

But currently I'm just creating the different projects on a whim, and creating references between them when I need to. Sometimes I end up in a situation where two projects need to reference eachother, but that is not allowed since it would cause a circular dependency.

Are there any rules/tips/patterns I should keep in mind when I create the different projects, and linking them together?

Should I start from the inside, and go out? Having the "core" projects refrence all the outerlying projects, or perhaps go from the outside and in where the independent projects all reference the "core"? Or the third option where I have business in two projects, and they both reference a third project?

+5  A: 

Hi,

Indeed you can't have circular references, but to be honest what would be the benefit of splitting the solution into small project if you had interdependencies between all of them?

Usually before I even open Visual Studio I take a piece of paper and split my problem into logical functional areas. You can draw a Utilities assembly at the top and all the GUI's, web services and other end projects at the bottom. The Utilities project is not going to reference any other project, and the ones at the bottom will not be referenced by anything. Then you think what functionality is common for these, e.g. all GUI's can share a common UI project with common user controls and dialogs, and this UI project will reference the "object model" project, etc. The project at the bottom can only reference what is above them.

Often when it appears that you need a circular reference, you can nicely get round it by defining an interface in the lower level assembly, and providing implementation in the upper level.

Without knowing what are you exactly doing I am afraid that's the only advice I can give you.

Grzenio
Thanks, that visual tip was the hint I needed. Now I can also draw the references on a sheet of paper, and its easier to determine who should reference who.
Frode Lillerud
+1  A: 

It's a bit old-fashioned, but for help in deciding how to split into projects, you could look up "Coupling" and "Cohesion" in wikipedia.

Also, while we sometimes think of these decisions as "style" rather than "substance", we should remember that assembly boundaries do have meaning, both to the compiler and to the runtime. A couple of examples of that...

  1. The C# compiler understands a keyword called "internal". To make the best decisions about factoring into separate projects, you should really understand the power of this.

  2. The JIT compiler in the runtime will never inline a function call that crosses an assembly boundary, which has a performance implication. (The reason is to do with Code Access Security).

There are many more examples, so the decision really does make a difference.

Martin
+1  A: 

I'll use a Winforms applications as an example. The pattern I have started getting into is this. The solution is called Example.

Example.Entities - This project will contain my business objects and the related heirachy of classes

Example.Dal - I put all business logic and data access logic in this project (namespace) This is the code that loads your business objects and then passes them to another layer.

Example.Gui - I put all my Winforms and GUI utility code here and my 'main' starting entry method. You could also just choose to call this project Example. I still like using the namespace Example.Gui for code separation.

Example.Test - You can put all your test code in this project.

I try to drive code into the Entities if it belongs to one of the business objects or a business object collection.

Gui will reference the Entities and the Dal (Data Access Layer). Depending on how you write your Dal it may reference your Entities. Test should reference Entities, Dal, and maybe Gui.

The Entities is its own Assembly dll so that you could use it in other projects. Or return them from a .NET SOAP Service.

The GUI layer should view the internals of the DAL as a blackbox. Your main app should not care how the business objects get loaded or persisted. But you should use your Test project to test your DAL thoroughly.

tyndall
I should add... if you watch some of the .NET Rocks video podcasts, some of Carl's guests use very good solution layouts too.
tyndall