Introduction
So I’ve decided to write a semi-instructional series on how I’d tackle writing a simple application in C#. I’m going to try to keep it as honest as possible – writing code in exactly the way I write code in the ‘real world’ – I’m going to cut any corners I feel it’s reasonable to.
The application I want to create is a sliding puzzle. To be honest, I shouldn’t find this application difficult to write, but it’s not completely trivial. I know it’ll be easy enough to get something working, but it’s just hard enough so that I don’t know exactly how I’ll implement it.
Anyway, let’s get started…
Creating a Home for the Project
As a developer that’s ‘used stuff before’, I have a set of tools I like to use to write software. For this project I’m using the following:
- Mercurial
- Visual C# Express 2010
- NUnit
- OpenCover
- ReportGenerator
- Powershell with posh-hg
I try other tools all the time, but these are my current favourites.
Because I’m using Mercurial and I want to share everthing I do to this project, I’ll create a repository on bitbucket called slidy. With that done, I’ll point powershell to the home of my local Mercurial repositories and clone it.
NOTE: All the code samples that follow in this article are taken from the powershell window.
-
C:\_hg> hg clone ssh://hg@bitbucket.org/ShyAlex/slidy
-
destination directory: slidy
-
no changes found
-
updating to branch default
-
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-
C:\_hg> cd slidy
-
-
C:\_hg\slidy [default tip]>
Here’s where I’ll put my source. I’ll commit here and push periodically back to bitbucket.
Before We Start Committing
I’m using Mercurial – a very easy to learn version control system. You should get Mercurial too if you don’t already know much about distributed version control.
In any case, if you have Mercurial, you can obtain a copy of this project by cloning https://bitbucket.org/ShyAlex/slidy:
-
hg clone https://bitbucket.org/ShyAlex/slidy
This will give you the project and the entire project’s history. You are free to revert to earlier versions, compare revisions and even commit changes locally. If you are following these articles in a detailed fashion, having a local repository available will help loads.
Commit 0 – A C# Express Project
Before I start writing some real code, I want a few things:
- An initial project for my code.
- Another project containing tests for that initial project.
- A way to easily build, test, and obtain code coverage.
I’ll start by creating the project in C# Express. I’m creating a class library called ShyAlex.Tiles and saving it in a solution called Slidy. Mercurial tells me I have 6 new files:
-
C:\_hg\slidy [default tip]> hg st
-
? Slidy\ShyAlex.Tiles\Properties\AssemblyInfo.cs
-
? Slidy\ShyAlex.Tiles\ShyAlex.Tiles.csproj
-
? Slidy\ShyAlex.Tiles\ShyAlex.Tiles.csproj.user
-
? Slidy\ShyAlex.Tiles\obj\Debug\DesignTimeResolveAssemblyReferencesInput.cache
-
? Slidy\Slidy.sln
-
? Slidy\Slidy.suo
My experience tells me that the only three of these files actually need to be put under source control. To filter out the garbage, I’ll add a .hgignore file. I type ‘notepad’, enter the rules, try to save the file as .hgignore, and get a file named .hgignore.txt. A rename at the command line corrects it.
-
C:\_hg\slidy [default ?6 tip]> notepad
-
-
C:\_hg\slidy [default ?6 tip]> hg st
-
? .hgignore.txt
-
? Slidy\ShyAlex.Tiles\Properties\AssemblyInfo.cs
-
? Slidy\ShyAlex.Tiles\ShyAlex.Tiles.csproj
-
? Slidy\ShyAlex.Tiles\ShyAlex.Tiles.csproj.user
-
? Slidy\ShyAlex.Tiles\obj\Debug\DesignTimeResolveAssemblyR
-
? Slidy\Slidy.sln
-
? Slidy\Slidy.suo
-
-
C:\_hg\slidy [default ?7 tip]> ren .hgignore.txt .hgignore
I do hg status and everything looks fine, so I do hg add and commit using an imaginative commit message.
-
C:\_hg\slidy [default tip]> hg st
-
? .hgignore
-
? Slidy\ShyAlex.Tiles\Properties\AssemblyInfo.cs
-
? Slidy\ShyAlex.Tiles\ShyAlex.Tiles.csproj
-
? Slidy\Slidy.sln
-
-
C:\_hg\slidy [default ?4 tip]> hg add
-
adding .hgignore
-
adding Slidy\ShyAlex.Tiles\Properties\AssemblyInfo.cs
-
adding Slidy\ShyAlex.Tiles\ShyAlex.Tiles.csproj
-
adding Slidy\Slidy.sln
-
-
C:\_hg\slidy [default +4 tip]> hg com -m "Initial commit."
Commit 1 – Not Enough Ignorance
I realise I’ve not actually built anything yet, so I build within C# Express. It builds fine, but checking hg status reveals I need to add some more files (or folders) to .hgignore. I update .hgignore using notepad, check the changes and commit.
-
C:\_hg\slidy [default tip]> hg st
-
? Slidy\ShyAlex.Tiles\bin\Release\ShyAlex.Tiles.dll
-
? Slidy\ShyAlex.Tiles\bin\Release\ShyAlex.Tiles.pdb
-
? Slidy\ShyAlex.Tiles\obj\Release\ShyAlex.Tiles.csproj.FileListAbsolute.txt
-
? Slidy\ShyAlex.Tiles\obj\Release\ShyAlex.Tiles.dll
-
? Slidy\ShyAlex.Tiles\obj\Release\ShyAlex.Tiles.pdb
-
-
C:\_hg\slidy [default tip]> hg st
-
? Slidy\ShyAlex.Tiles\bin\Release\ShyAlex.Tiles.dll
-
? Slidy\ShyAlex.Tiles\bin\Release\ShyAlex.Tiles.pdb
-
? Slidy\ShyAlex.Tiles\obj\Release\ShyAlex.Tiles.csproj.FileListAbsolute.txt
-
? Slidy\ShyAlex.Tiles\obj\Release\ShyAlex.Tiles.dll
-
? Slidy\ShyAlex.Tiles\obj\Release\ShyAlex.Tiles.pdb
-
-
C:\_hg\slidy [default ?5 tip]> notepad .hgignore
-
-
C:\_hg\slidy [default ?5 tip]> hg st
-
M .hgignore
-
-
C:\_hg\slidy [default ~1 tip]> hg com -m "Added build output to ignore in bin and obj folders."
Commit 2 – Bloating the Repository with 3rd Party Tools
Before I code, I’d like to have a project set up containing tests. I’d also like to get code coverage on those tests. The tools I use for testing and code coverage are NUnit, OpenCover and ReportGenerator. These all have open-sourcy licenses and a freely re-distributable. They’re also fairly small in size. This makes them good candidates to go into my repository as dependencies.
I grab all three from previous projects I’ve worked on and put them in a 3rdParty folder. I add and commit all 90 files.
-
C:\_hg\slidy [default +90 tip]> hg com -m "Added 3rd party projects NUnit, OpenCover and ReportGenerator."
Just a quick word here on this. You may think this is a little weird – putting entire programs into a source control repository. However, there are a few benefits.
- Development machines do not have to have those products installed to work on the application.
- The versions of the products are always correct with respect to the source code they’re checked in with.
- The build/test scripts are easier to write.
I have worked on projects where we have multiple branches using different versions of products that don’t install side by side with each other. Reproducing old builds and creating new branches was a nightmare. This approach solves those issues.
Commit 3 – A Test Project
Now I’ll add a project named ShyAlex.Tiles.Tests for my unit tests, build, check hg status and commit. I’ll make sure I add a reference to NUnit.Framework from the 3rdParty directory, not from the GAC. I also will need a reference to the project ShyAlex.Tiles.
-
C:\_hg\slidy [default tip]> hg st
-
M Slidy\Slidy.sln
-
? Slidy\ShyAlex.Tiles.Tests\Properties\AssemblyInfo.cs
-
? Slidy\ShyAlex.Tiles.Tests\ShyAlex.Tiles.Tests.csproj
-
-
C:\_hg\slidy [default ~1 ?2 tip]> hg add
-
adding Slidy\ShyAlex.Tiles.Tests\Properties\AssemblyInfo.cs
-
adding Slidy\ShyAlex.Tiles.Tests\ShyAlex.Tiles.Tests.csproj
-
-
C:\_hg\slidy [default +2 ~1 tip]> hg com -m "Added test project for ShyAlex.Tiles."
-
-
C:\_hg\slidy [default tip]>
Commit 4 – Build Scripts
Now I’d like to get some scripts together so that I can easily build, test, and get code coverage on my project. This will be done with good old .bat files stuck in a Build directory. The files reference applications in the 3rdParty folder via relative paths where possible.
The Build.bat script needs to reference a compiler for our project, and I choose MSBuild.exe located in the Windows .NET framework folder, as it’s the one most likely to exist, it’s easy to reference, and it allows the project to be built on machines where Visual Studio or C# Express are not installed.
I add the scripts, switch to the build directory, then test them in powershell. I do hg status to check any test output which needs excluding, add the scripts, update .hgignore, and commit.
-
C:\_hg\slidy\build [default ?3 tip]> .\build;.\test;.\report
-
[Build/test output omitted]
-
-
C:\_hg\slidy\build [default ?6 tip]> hg st
-
? Build\Build.bat
-
? Build\Report.bat
-
? Build\Reports\index.htm
-
? Build\ShyAlex.Tiles.Coverage.xml
-
? Build\ShyAlex.Tiles.Tests.xml
-
? Build\Test.bat
-
-
C:\_hg\slidy\build [default ?6 tip]> hg add *.bat
-
adding ..\Build\Build.bat
-
adding ..\Build\Report.bat
-
adding ..\Build\Test.bat
-
-
C:\_hg\slidy [default +3 ?3 tip]> notepad .hgignore
-
-
C:\_hg\slidy [default +3 ?3 tip]> hg st
-
M .hgignore
-
A Build\Build.bat
-
A Build\Report.bat
-
A Build\Test.bat
-
-
C:\_hg\slidy [default +3 ~1 tip]> hg com -m "Added build/test scripts."
Finally
There, I’m ready to code, and this initial article is done. I now push back to bitbucket.
-
C:\_hg\slidy [default tip]> hg push
-
pushing to ssh://hg@bitbucket.org/ShyAlex/slidy
-
searching for changes
-
remote: adding changesets
-
remote: adding manifests
-
remote: adding file changes
-
remote: added 5 changesets with 102 changes to 99 files
-
remote: bb/acl: ShyAlex is allowed. accepted payload.
-
C:\_hg\slidy [default tip]>
Anyone can download the code, and run the build, test and report scripts. Although it won’t do them much good yet.
Next time: let’s actually write some C# and some tests.