Snowflake Design

Because in Architecture the Answer is Usually "It Depends"


News

 

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...


 

Unless you've developed a one-off application, you're more than likely going to need to need to branch. In this post, I'll point you to some great documentation on how to decide on what your branching strategy should be. I will leave it to you to decide what meets your needs. In my last post I mentioned how I typically structure my source code repository no matter whether I use TFS/Subversion/etc and I'll assume you're using a structure similar to that one.

My one recommendation is to branch judiciously, meaning branch only when needed. Branching provides isolation at the cost of maintenance and merging. Depending on how long you go between merges, this can become a dreadful experience. I would suggest to merge at least once a week so that you feel the pain little by little instead of at the very end.

The VSTS Rangers team has some good advice in CodePlex http://tfsbranchingguideii.codeplex.com/ that has been divided into Basic, Standard, and Advanced branching plans. Here's a quick rundown, but I will not cover everything the guide goes through, so I highly recommend the various guides available at codeplex.

Basic Plan

Gives you the ability to support concurrent development (whether its by team/feature) having a stable main branch and a release branch for shipping bug fixes. Useful if you only do version releases.

Standard Plan

Adds to the basic plan the ability to also support for service packs.

- These service pack branches would go in the maintenance folder from the structure I use and older releases would go in the safekeeping folder.

Advanced Plan

Adds to the basic and standard plan by adding support for having hot fixes as a formal type of release.

- These hot fix branches would also go in the maintenance folder and older releases would go in the safekeeping folder.

When you check out the CodePlex project, make sure you download the drawings zip file it has a great poster that provides some walkthroughs.


 

The below repository structure is taken from a couple of sources and personal experience.  Part of it is from the TFS Guide. Now don't dismiss it just because it comes from the TFS guide. It has great advice which applies to other source code repositories not just TFS. I am actually not a fan of TFS, prefering either Subversion or Git. Some of the structure also comes from Visual Studio Team System: Better Software Development for Agile Teams.

<Root>
    /Development
        /FeatureBranchXName
            /<Branched From Main>
        /FeatureBranchYName
            /<Branched From Main>
    /Main
        /Builds
            /Certificates
            /Scripts (Contains build scripts)
            /Tools (A dir for each tool)
                /XMLPreprocess
                /etc.
        /Docs (Contains product docs etc Shipped to customer)
        /Source solution (.sln files)
            /Code (Contain folder for all source)
                /ClassLibrary1 (Contains ClassLibrary1.csproj)
                /MyApp1Web (Contains MyApp1Web.csproj)
            /Database (Depending on whether or not db is shared with other applications you may not want this here)
            /UnitTests (Container folder for unit tests)
                /ClassLibrary1.UnitTests (Contains test project and code)
                /MyApp1Web.UnitTests (Contains test project and code)
            /SharedBinaries (Shared binaries e.g. libraries)
            /SharedSource (Shared source code)
                SolutionInfo.cs (Shared file used to contain assembly attributes like copyright, NeutralResourcesLanguageAttribute, etc)
        /Tests (Container for tests Testcases - Only needed if not using a tool like Quality Center)
            /FunctionalTests
            /PerformanceTests
            /SecurityTests
    /Maintenance
        /Release1
            /<Branched From Main>
        /Release2
            /<Branched From Main>
    /Safekeeping
        /Release1
            /<Branched From Main>
        /Release2
            /<Branched From Main>
    /Spikes
        /...
    /Tags
        /v1_0_0_0
 

Most of the folders are self explanatory, but let me give a quick synopsis but you can get details from the TFS Guide.

  • Root

Now the location of this will depend on what repository you use, for example for Subversion, I typically use one repo per system.

  • Development

Typically used for team/features branches which you may or may not use depending on your branching strategy. I'll be covering that in an upcoming post.

  • Main

As the name implies, this is synonymous to Trunk but I used Main to keep Subversion terminology from leaking into the structure

  • Builds

Root folder for all things related to the build process.

  • Certificates

Contains thinks like your snk file or authenticode cert

  • Scripts

Hopefully self-explanatory

  • Tools

Parent folder used to contain subfolders for each of the tools used during the build process.

  • Docs

Folder for documentation that will be shipped to the client (i.e. help file project files)

  • Maintenance

Folder containing branches which are currently under active maintenance (i.e. code in production)

  • Safekeeping

Folder containing archived branches.

  • Spikes

Folder containing spike projects for the system that root is for. This lets people have version control for spikes and gives and can even give you glimpse as to why certain approches were taken on production code if a spike was used to test out theories.

  • Tags

Typically only used if your repository needs a physical folder to contain tags (i.e. labels)

Here's a picture that I think is a little easier to see than the above ASCII tree.

Some additional things to note. Underneath the code folder I typically name the folder containing the project to match the project name which in turn matches the name of the assembly (The root namespace of the project also matches the assembly name). The unit test project for that project uses the same name as the project the unit tests will be covering but the the ".UnitTests" suffix. This is because you may also have an integration tests assembly. I typically use different projects for unit and integration tests to make it easier to separate when the tests will be run by the build environment.

I've been on the fence about using SharedSource vs. just having the files right in the Source folder (at the same level that the .sln files are put). Still not sure but I've shown the SharedSource folder in this post so that you can make up your own mind.

I like having the tools included (and anything else you need to build) in source control so that when you checkout the project, you have everything you need to build. I don't like having the tools (or other dependencies) in a separate location in the repository and then having to checkout both the project and the tools and needing to put the tools in a well known folder so that your project can reference them...

I'm also a big fan of XMLPreprocess, and the MSBuild Extension Pack projects.

In the upcoming posts I'll talk about how to increment version numbers, get the build going, etc.


 

Now that I provided you with a spreadsheet you can use to track your sprints, in my upcoming posts, I'm going to talk about things that you generally need to think about when starting up a new project on a more technical level. I won't go overly in depth unless warranted and will provide links to materials I used to come to my decisions as well as my rationale and hopefully that will help someone out...Without further ado, here's my list:

  • Repository Structure
  • Branching Strategy
  • Tool Selection (things like unit testing/mocking frameworks/etc)
  • Build Environment Setup
  • Deployment Options
  • Solution Architecture Decisions

Once I finish this up, I'll get in depth on the solution architecture components. Hope this gives you a look at what's coming up.


 

As the title suggest, about the backlog. There are tools out there that let you do agile project management but some times the easiest thing is just to use a spreadsheet. I haven't seen too many examples of those, so I figured that would be an area I could help out in and walk you though a spreadsheet that has evolved over time for me and actually started from a sample that I got from my ScrumMaster certification class.

 

Welcome to my blog. My name is Carlos Santos and have been doing software development since 1996. I've been a solutions architect for various teams, done training classes, been selected from hundreds of MCTs to work at TechEd twice and developed and validated test for BrainBench. My goal here is to talk about the design tradeoffs I've faced during the development of existing and new systems.

I'll be talking about various things, ranging from solution architecture (And the decisions at each of the layers) to agile practices.

The reason I chose Snowflake Design for the name of the blog is because enterprise and solution architecture is so dependent on the environment and the tradeoffs you are willing to make, that like snowflakes, architectures are typically different from one environment to another. As they say, there is no silver bullet.

And now, for the disclaimer

******************DISCLAIMER ****************

This is a personal weblog. The opinions expressed here represent my own and not those of my employer.

All data and information provided on this site is for informational purposes only. blackbeltsolutions.com makes no representations as to accuracy, completeness, currentness, suitability, or validity of any information on this site and will not be liable for any errors, omissions, or delays in this information or any losses, injuries, or damages arising from its display or use. All information is provided on an as-is basis.

In addition, my thoughts and opinions change from time to time…I consider this a necessary consequence of having an open mind. This weblog is intended to provide a semi-permanent point in time snapshot and manifestation of the various memes running around my brain, and as such any thoughts and opinions expressed within out-of-date posts may not the same, nor even similar, to those I may hold today.

*************************************************