Geeks With Blogs
Snowflake Design Because in Architecture the Answer is Usually "It Depends"

Its is very typical for companies to have a set of common components. These are typically in one or more assemblies and shared by more than one system.In this post, I'll walk you through my through process on how I  divide out projects and enable sharing of these common components between different project roots.

In a previous post I mentioned how I typically structure my source code repository no matter whether I use TFS/Subversion/etc. The structure is really about being able to check out everything you need to build the project, including dependencies to dlls, build scripts, build tools, etc. At the very top of the structure is what I labeled as <Root>. Underneath this root are different folders where you can place different branches (Depending on your needs, but that's a future post) with the Main folder being synonymous to the trunk.
 
This <Root> typically is a system but could be an application. The way I see it, your repository structure can be affected by how you're going to deploy your code, meaning what gets deployed at the same time. So if you have a web application made up of multiple projects all shipped at the same time, I would setup the project as:
 
<Root>
  - Main
     - Source
        - Code
           - ProjectX
           - ProjectY
 
This makes sure that when you branch you take all projects along with you that you deploy, ensuring that your branch reflects what you have deployed. So given this, lets say you have multiple roots (whether they represent applications or systems is up to you) and a suite of common components that both roots need to share. What do you do? Put all three under one <Root> so that you can do project references?? Like so:
 
<RootA>
  - Main
     - Source
        - Code
           - ProjectX
           - ProjectY
           - ProjectS
           - ProjectT
           - CommonX
           - CommonY

 

I do not like this since it means that you'd be branching all three things at the same time even if you don't release all three at the same time, making for branches that do not match what you have deployed. Here's how I tend to do it:
 
<RootA>
  - Main
     - Source
        - Code
           - ProjectX
           - ProjectY
        - SharedBinaries
           - Common
                 CommonX.dll
                 CommonX.pdb
                 CommonY.dll
                 CommonY.pdb
 
<RootB>
  - Main
     - Source
        - Code
           - ProjectS
           - ProjectT
        - SharedBinaries
           - Common
                 CommonX.dll
                 CommonX.pdb
                 CommonY.dll
                 CommonY.pdb
 
<CommonComponentsRoot>
  - Main
     - Source
        - Code
           - CommonX
           - CommonY
 

Notice how in the above structure, RootA and RootB use CommonX.dll and CommonY.dll and do not use project references. What this means is that you have a binary refence to these assemblies instead of project references. This does complicate things since it means that somehow these assemblies need to get copied over to these projects. I typically have the continuous integration build deploy the assemblies to projects that need them. This means that after a successful build of Common then RootA and RootB will have their continuous integration build kickoff since they got a drop of the new common assembiles. If you have good test coverage, the likelyhood of knowing if any of these changes to common broke either RootA/RootB should be increased and hopefully lets you know that you've made breaking changes. If you have made breaking changes and aren't ready to compensate for those in either RootA/RootB, you can stop the Common continous integration build from dropping new versions of the dlls into the SharedBinaries folder and rollback to the previous version of the Common dll in question. Once you've made the changes needed to support the new version of common, you can turn the droppping of new dlls back on.

One other thing to note is that I show also dropping the pdbs in the SharedBinaries folder. This will enable you to step through the Common libraries source code from RootA/RootB even if you CommonX.dll or CommonY.dll are release builds. The only drawback is that you have to open the source file for the common components you want to put a breakpoint on using File | Open instead of being able to use Solution Explorer...

Hope this helps...

Posted on Wednesday, December 23, 2009 10:38 PM | Back to top

Copyright © Carlos Santos | Powered by: GeeksWithBlogs.net