Scott Hanselman

How do you organize your code?

April 01, 2005 Comment on this post [10] Posted in ASP.NET | Corillian | NUnit | NCover | Nant | Tools
Sponsored By

Organizedfolders1How do we organize our code? Well, it all depends on the project and what we're trying to accomplish. We're also always learning. Our big C++ app builds differently than our lightweight C# stuff. However, for the most part we start with some basic first principles.

  • A repeatable build
    • Obvious, maybe, but if you can't build it n times and get the same result, you may have some problems.
  • Continuous Integration
    • When possible and appropriate, have builds automated and build mail sent out.
    • We started with building on every check-in, and for the most part we do that.
    • We added a daily build, so now we will build on every check-in, but there's a 5pm build also.
  • Tools
    • CruiseControl.NET - the goal being a company-wide dashboard.
    • NAnt -building
    • NUnit - testing
    • NCover - code coverage, not formalized yet.
    • FxCop - For the obvious stuff, CLS compliance, etc.
    • NDoc - the shiznit. Use it to automate CHM file creation. That auto-generated CHM is then sucked into a larger 'prose' CHM.
    • libcheck - looking into it. Using it to measure API churn.

As far as layout (picture above), there's no right way. We've got folks who've been doing builds since before Windows, so we have a little *nix-y style in a few things. Again, if it works, use it. I like:

  • source - for source. duh.
  • tools - This CVS module is the source for any tools/utils the project needs. Shared between projects.
  • install - XCopy deployment, it'd be nice. We do versioned MSIs for everything significant.
  • test - Not Unit-tests per se, mostly larger projects for integration and regression testing.

As far as the build directory is concerned:

Organizedfolders3

Everything under build is 'important.' It kind of speaks for itself. Bin for bins, doc for the CHM.

In source, we have:

Organizedfolders2

Every 'subsystem' has a folder, and usally (not always) a Subsystem is a bigger namespace. In this picture there's "Common" and it might have 5 projects under it. There's a peer Common.Test. Under CodeGeneration, for example, there's 14 projects. Seven are sub-projects within the CodeGeneration subsystem, and seven are the NUnit tests for each. The reason that you see Common and Common.Test at this stuff is that they are the 'highest." But the pattern follows as you traverse the depths. Each subsystem has it's own NAnt build file, and these are used by the primary default.build.

In this souce directory we've got things like build.bat and buildpatch.bat. The goal being that folks can get the stuff from source control and type BUILD and be somewhere useful. It's VERY comforting to be able to reliably and simply build an entire system. Recently I had to patch something I'd worked on 18 months ago, but that had used this principal. I did a Fet, did a BUILD and I was cool. We then used reflector and Assembly Diff to confirm that the patch surface area was minimal.

We DO build things in VS.NET, but for the vast majority of projects, we prefer a command-line build to get real repeatabilty. With .user files and per-user reference paths, I just don't trust VS.NET to do the right thing.

Junctions

Another thing we make a lot of use of are what we call Junctions. These are NTFS Reparse Points, also known as symlinks.

Organizedfolders4

In this screenshot of a standard DIR from the command prompt, directories show up as <DIR> while junctions say <JUNCTION>. These junctions point to other directories. But NTFS makes it transparent; you can CD into them, and even Explorer has no clue. Certainly, they can be dangerous, as you can clean out a directory and not realize that it's the authoritative source for something and is being referenced by other projects.

Organizedfolders5

You can download Junction from SysInternals. You can also use LINKD, that shipped with the Windows 2000 Resource Kit. In this screen shot, the relative SDK folder points to an installed version of our SDK. This allows our CSPROJ files to refer to our assemblies with relative paths, gives developers a lot more flexibilty, and makes the NAnt builds simpler.

It also allows us to swap out different versions of things. For example, I could point the SDK folder to a previous (or future!) build of the SDK and build again. This flexibility comes with a cost though - complexity. People have to think a little more. Fortunately, our build guys are pretty savvy and will (shell script-like) go looking for preferred versions of things in standard locations and set up Junctions for folks. 

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
April 01, 2005 18:44
Have you looked at TreeSurgeon? This is a utility of automagically setting up a consistent project directory structure similiar to what you are describing. It even creates a basic Nant build script...

http://confluence.public.thoughtworks.org/display/TREE/Tree+Surgeon
April 01, 2005 20:24
Here is a direct link to the junction app on sysinternals.

http://www.sysinternals.com/ntw2k/source/misc.shtml#junction
April 01, 2005 21:39
Now that I've got junctions working on my machine. How do you get those little cool green check marks to appear?

I'm guessing you didn't otherwise you would have never written your little Checks Junctions util. I kind wish someone could add a util that changed the folder graphic too for junctions.
April 01, 2005 21:41
Sadly, those checkmarks are TortoiseCVS reporting that the folders are under source.

I'll look into making an Explorer Add-in...
April 01, 2005 22:23
I don't know why you have to do things the hard way?
April 02, 2005 2:46
what are the "cheked" arrows on the folders image?
April 03, 2005 22:21
This has nothing to do with this topic, but I just wanted to say that I'll be looking forward to your talk on .NET Rocks tomorrow!
April 04, 2005 11:05
I'd like to suggest a tool of mine :-):
Along the lines of agiledox.sf.net: generate class documentation from declarative unit tests.
You may or may not like the idea: I do.

See it at http://projectdistributor.net/Projects/Project.aspx?projectId=87

I was pointed to such an idea by the following:

http://www.martinfowler.com/bliki/Agiledox.html

Thanks.
April 05, 2005 16:12
Just so no one else has to go look up the link for LibCheck:
http://www.microsoft.com/downloads/details.aspx?FamilyID=4B5B7F29-1939-4E5B-A780-70E887964165&displaylang=en
or http://tinyurl.com/3pp3n
April 06, 2005 23:11
Great Post! I use these products as well but I am confused that you are not using subversion????

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.