Anmelden
Google-Apps
Hauptmenü
Post a Comment On:
the urban canuk, eh
"Twelve Days of Code - Solution Setup"
No comments yet. -
1 – 0 of 0
As part of the Twelve Days of Code Challenge, I’m developing a Pomodoro style application and sharing the progress here on my blog. This post tackles day one: setting up your project. The initial stage of a project where you are figuring out layers and packaging is a critical part of the process and one that I’ve always found interesting. From past experience, the small details at this stage can become massive technical debt later if the wrong approach is used, so it’s best to take your time and make sure you’ve crossed all the T’s and dotted the I’s. Creating the Solution For this project I’ve chosen to use Visual Studio 2010 Beta 2 and so far the experience has been great. Visual Studio 2010 is going to reset the standard and bring new levels of developer productivity (assuming they solve some of the stability issues): it’s faster and much more responsive, eats less memory and adds subtle UX refinements that improve developer flow. To get a better sense and to recreate this feeling, I urge you to load up Visual Studio 2003 and look at the Start page – we’ve come a long way. The
New Project
window has a nice overhaul, and we can specify the target framework in the dialog. Here I’m creating a WPF Application
Pomodoro.Shell
. Note that I’m specifying to create a directory for the solution and that the Solution Name and Project Name are different.
[Image]
Normally at this point I would consider renaming the output of the application from “Pomodoro.Shell.exe” to some other simpler name like “pomodoro.exe”. This is an optional step which I won’t bother with for this application. Adding Projects When laying out the solution, the first challenge is determining how many Visual Studio Projects we’ll need, and there are many factors to consider including dependencies, security, versioning, deployment, reuse, etc. There appears to be a school of thought that believes every component or module should be its own assembly, and I strongly disagree. Assemblies should be thought of as
deployment-units
– if the components version and deploy together, its very likely that they should be a single assembly. As Visual Studio does not handle large number of projects well, it’s always better to start with larger assemblies and separate them later if needed. For my pomodoro app, I’ve decided to structure the project into two primary pieces, “core” and “shell”, where “core” provides the model of the application and “shell” provides the user-interface specific plumbing. Add Test Projects Right from the start of the project, I’m gearing towards how it will be tested. As such, I’ve created two test projects, one for each assembly. This allow me to keep the logical division between assemblies.
[Image]
As soon as the projects are created, the first thing I’ll do is adjust the namespaces of the test libraries to match their counterparts. By extension, the tests are features of the same namespace but they are packaged in a separate assembly because I do not want to deploy them with the application. I’ve written about this before.
[Image]
Configure common Assembly Properties Once we’ve settled into a project structure, the next easy win is to configure the projects to share the same the assembly details such as version number, manufacture, copyright, etc. This is easily accomplished by creating a single file to represent this data, and then linking each project to this file. At a later step, this file can be auto-generated as part of the build process. using System.Reflection; [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyCompany("Bryan Cook")] [assembly: AssemblyCopyright("Copyright © Bryan Cook 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] Tip: Link the AssemblyVersion.cs file to the root of each project, then drag it into the Properties folder. Give the Assemblies a Strong-Name If your code will ultimately end up on a end-user desktop, it is imperative to give the assembly a strong-name. We can take advantage of Visual Studio’s built in features to create our strong-name-key (snk) but we’ll also take a few extra steps to ensure that each project has the same key. Open the project properties. Click on the Signing tab Check the “Sign the assembly” checkbox Choose “<New…>” Create a key with no password. Open Windows Explorer and copy the
snk
file to the root of the solution. Then for each project: Check the “Sign the assembly” checkbox Choose “<Browse…">” Navigate to the root of the solution and select the
snk
key. Note that Visual Studio will copy the
snk
file to each project folder, though each project will have the same public key. Designate Friend Assemblies In order to aid testing, we can configure our Shell and Core assemblies to implicitly trust our test assemblies. I’ve written about the benefits before, but the main advantage is that I don’t have to alter type visibility for testing purposes. Since the assemblies have a strong name, the
InternalsVisibleTo
attribute requires the fully public key.
[Image]
Since all the projects share the same key file, this public token will work for all the projects. The following shows the
InternalsVisibleTo
attribute for the
Pomodoro.Core
project: [assembly: InternalsVisibleTo("Pomodoro.Core.Tests, PublicKey=" + "0024000004800000940000000602000000240000525341310004000001000" + "1003be2b1a7e08d5e14167209fc318c9c16fa5d448fb48fe1f3e22a075787" + "55b4b1cf4059185d2bd80cc5735142927fbbd3ab6eeebe6ac6af774d5fe65" + "0a226b87ee9778cb2f6517382102894dc6d62d5a0aaa84e4403828112167a" + "1012d5b905a37352290e4aa23f987ff2be3ccda3e27a7f7105cf5b05c0baf" + "3ecbfd2371c0fa0")] Setup External References I like to put all the third-party assemblies that are referenced into the project into a “lib” folder at the root of the solution. At the moment, I’m only referencing Moq for testing purposes. A note on external references and source control: Team Foundation Server typically only pulls dependencies that are listed directly in the solution file. While there are a few hacks for this (add each assembly as an existing item in a Solution Folder; or create a class library that contains the assemblies as content), I like to have all my dependencies in a separate folder with no direct association to the Visual Studio solution. As a result, these references must be manually updated by performing a “
Get Latest
” from the TFS Source Control Explorer. If you’ve got a solution for this – spill it, let’s hear your thoughts. Setup Third-Party Tools For all third-party tools that are used as part of the build, I like to include these in a “tools” or “etc” folder at the root of the solution. This approach allows me to bundle all the necessary tools for other developers to allow faster ramp-up. It adds a bit of overhead when checking things out, but certainly simplifies the build script. Setup Build Script There’s a few extra steps I had to take to get my .NET 4.0 project to compile using NAnt. Download the nightly build of the nant 0.86 beta1. The nightly build solves the missing SdkInstallRoot build error. Paige Cook (no relation) has a comprehensive configuration change that needs to be applied to
nant.exe.config
. Modify Paige’s version numbers from .NET 4.0 beta 1 to beta 2. (Replace all references of “
v4.0.20506”
to “
v4.0.21006”
) Here's a few points of interest for the build file listed below: I’ve defined a default target “main”. This allows me to simply execute “nant” in the root solution of the folder and it’ll take care of the rest. The “main” target is solely empty because the real work is the order of the dependencies. Currently, I’m only specifying “build”, but normally I would specify “clean, build, test”. <project default="main"> <!-- VERSION NUMBER (increment before release) --> <property name="version" value="1.0.0.0" /> <!-- SOLUTION SETTINGS --> <property name="framework.dir" value="${framework::get-framework-directory(framework::get-target-framework())}" /> <property name="msbuild" value="${framework.dir}\msbuild.exe" /> <property name="vs.sln" value="TwelveDays.sln" /> <property name="vs.config" value="Debug" /> <!-- FOLDERS AND TOOLS --> <!-- Add aliases for tools here --> <!-- main --> <target name="main" depends="build"> </target> <!-- build solution --> <target name="build" depends="version"> <!-- compile using msbuild --> <exec program="${msbuild}" commandline="${vs.sln} /m /t:Clean;Rebuild /p:Configuration=${vs.config}" workingdir="." /> </target> <!-- generate version number --> <target name="version"> <attrib file="AssemblyVersion.cs" readonly="false" if="${file::exists('AssemblyVersion.cs')}" /> <asminfo output="AssemblyVersion.cs" language="CSharp"> <imports> <import namespace="System" /> <import namespace="System.Reflection" /> </imports> <attributes> <attribute type="AssemblyVersionAttribute" value="${version}" /> <attribute type="AssemblyFileVersionAttribute" value="${version}" /> </attributes> </asminfo> </target> </project> Next Steps… In the next post, we’ll look at the object model for our Pomodoro application.
posted by bryan at
3:43 PM
on Dec 24, 2009
Leave your comment
You can use some HTML tags, such as
<b>, <i>, <a>
This blog does not allow anonymous comments.
Comment moderation has been enabled. All comments must be approved by the blog author.
Google Account
You will be asked to sign in after submitting your comment.
Please prove you're not a robot
"Twelve Days of Code - Solution Setup"
No comments yet. -