Sunday, 6 July 2008

Using Subversion

As far as source control is concerned I've decided to go for Subversion (SVN) using the TortoiseSVN client. I've been using this combination for a while now and through my experiences and articles I have read, I've come to believe it is one of the best source control systems out there despite it's freeness. I believe that commercial system offer more in terms of integrating source control with other systems such as the IDE, an issue tracking system, ect. etc., but no more in terms of a source control system. It's easy to use but behind the childlike interface of Tortoise is the power of a source control system that successes CVS which has been used in the majority of open source projects out there and as such is an indication of its ability to enable smooth collaboration between a development team. This is in my mind the primary goal of such a system.

The structure of the repository I'm going for is as follows:
  • Trunk
    • Tools
    • Library
    • Source
  • Tags
    • Builds
    • Releases
    • Other
  • Branches
    • Tasks
    • Personal
    • Other
Each of these folders are described bellow:

Trunk

This is where all artefacts that are related to the project go.
Tools
Tools used in the build process of the project are stored here. Examples may include assembly merging tools (ILMerge), obfuscation tools, compilers, unit testing tools, etc.
Library
All externally compiled assemblies should be placed in an appropriate folder inside the library folder.
Additionally, svn-external projects/ libraries should be placed her. However, care should be taken with respect to Tags. If the SVN-Externs points to the head of a Trunk, then when Tagging, no information is stored with respect to which revision of the trunk was in use at the time. For this reason, when it becomes important for tags to be exact (for example for the purpose of recreating a build), svn-externs should be made to point to either a Tag or a specific revision. When this is the case, care should be taken to update this when changes are made to the external repository.
Source
All artefacts that are compiled or in some way make up the release should be placed here. Solution projects should be nested inside the solution folder. Each business project should ideally be made up of only one solution file. External assemblies/ Libraries/ Library projects should be referenced from the Library Folder. Setup projects should be in a folder of their own and the source files for the setup project should be taken from a source folder insider the setup project folder. Finally the source route should contain a batch file of something of that sort that generates a release. The hows and whys of this will be covered in a released post.
An example structure for the source folder is as follows:
  • Source
    • Solution
      • projectA
      • projectB
    • SetupProject
      • SourceFiles
      • SupportFiles
    • build.bat

Tags

This is where Tags (snapshots of) the Trunk are kept to represent the state of the trunk at a particular moment of interest. Care should be taken not to commit changes made accidentally (and changes should not be made purposefully) to Tags. (Because SVN treats Tags and Branches in the same way, it allows this).
Builds
This is where tags of builds are kept. These are generally automatically created by the CI server.
Releases
This is where tags of releases (i.e. versions of the code that have been assigned a specific release version and have been sent for testing of to the client) are kept.
Other
This is where others tags are kept.

Branches

Branches are for copies of the trunk made in order to fulfil a particular task. Branches assist developers in that they allow them to commit unstable and untested code that should not under normal circumstances be committed to the trunk. It is often necessary to do this because a logical task may span over a few days in which case the developer will still want to keep his code in the safety of the repository.
The general purpose of branching is to eventually merge changes back into the trunk. In Subversion, this is often a delicate operation - not as straight forward as one would hope. So far I've found a couple of things that can cause issues when merging. These are generally related to renaming and moving files/ folder on the branch. (Maybe even on the trunk, though I haven't tried this). Thus my recommendation is to avoid these operations on branches.
Tasks
This folder contains branches that are related to a particular task (e.g. 'issue 345' or 'Adding paging to SearchLists'.
Personal
This folders contain branches that are for personal use/experimentation by developers
Other
This folder contains other branches.

Bringing the old to the new

Before I dive into the details of what tools I'll be using and how I'll be using them I thought I should mention another defining factor which will inevitable affect the progression and success of our project. The developers working for my company are split into two teams: the ones developing and maintaining older systems written in Delphi 7 and the ones working on the future systems using .NET and C#. I work as part of the later team and one of the aims of my project is to get the developers in the Delphi team involved and familiarize them with the newer technologies.

This brings me against two to three areas of 'stuff' I have to transfer to the older developers. Primarily, the obvious first is the tools we use. The IDE: Visual Studio and the language C#. I think that will be the easy part. What I’m worried about is the getting them to think in a more object oriented, low coupling and high cohesion way about the software they are writing (not to in any way pass judgment in the software that they are already writing). I just believe that given the tools we use nowadays, we have two options: to either produce the same software faster or produce higher quality software in the same time. My thoughts are skewed towards the later.

Finally I have to introduce them into the processes we use. This I think will the hardest of the three to achieve. The reason is that processes in general stand up to the test of time: meaning that they'll have equivalent processes for working and those will be based on years of experience that I just don't have. And given my lack of experience I have to go by what is being written about with regard to software development processes. I have to understand the state of the art to the extent that I can present it in a comprehensible manor, to back it up when I have to, and genuinely believe in it to the extent that I can convey this belief to others. At the same time I have to draw on their experience and use it to factor and refactor the processes that we use to deliver software of the quality and in the time required by the business.

Friday, 4 July 2008

Software Development Project Management: Take 1

For the sake of documenting some of the processes or set-ups I'm using for the project I'm working on at work (which I will refer to as BS.NET Project), I'm going to try post stuff here to that end.

Primarily what I'm pushing towards is an 'everyone for everything' approach. Not to say that all developers working on the project will be working on all parts of it, but I do want everyone to have a deep enough understanding of the whole project such that at any time they can work on any part of it that is needed.

This is actually quite a tall order in the context of the company that I'm working for. The developers there (and I'm sorry to say both new and old) don't have a strong feeling of 'shared ownership'. I.e. that the code belongs to no-one and everyone at the same time. That is to say that everyone is equally responsible for all the code. Viewing the code as one inseparable unit of ownership and not fragmented parts written and maintained by separate developers. Not to say that any one won't have their area of expertise, but rather that no-one will be confined to their area of expertise and that given the right circumstances, their areas of expertise will grow.

My hope is that I will accomplish this by getting developers to work on many small chunks of the project in parallel as opposed to splitting work into large ones. So, let’s say that tasks A, B, C and D are related, and 1, 2, 3 and 4 are related. Instead of getting one developer to work on ABCD and another on 1234, I’m going to get one to work on AB and one on CD, then the first on 12 and the second on 34. Yes, I appreciate that I’ll be missing out on specialization of labour, and the efficiencies of that, but I believe primarily specialization has the tendency to dumb the mind resulting in potentially good refactoring chances being missed, and secondly, in the long term, this approach will result in greater capacity to maintain code and to avoid resource bottlenecks (i.e. one developer holding up a project because he is over allocated, but no-one else can do his job).

I want to get across the way to prevent code from breaking when someone other than the person who wrote it working on it is unit tests. Getting across the idea that the way to manage changing requirements leading to changes in the code such as not to introduce bugs, isn't by having everyone working on and being responsible for 'their' code, but instead everyone providing tests for code they have written that verifies that that code does what it should. If we can develop a standard for testing various parts of the system, then we can be more confident when it comes to changing them.

On the other hand I do believe that you can over test. That is to say at the end of the day it all boils down to money. There comes a point when the cost (in terms of man-hours) of writing extra tests to iron out another 50 percent of bugs isn't worth it. For example, let’s say with 1 unit of time we can iron out 50% of bugs in a project. And for the sake of argument, let’s say that this is constant. 1unit of time = 50%of bugs, 2 units = 75% of bugs (50% of the 50% left), 3 units = 87.5%, 4units = 93.75... And so on. It should be clear that there comes a point where the absolute number of bugs found isn't work an extra unit of time. The trick is finding where this point is: and in general, it depends on the nature of the system. If it’s a safety critical maybe you need to have a 99.9% bugs eradicated. If it’s a finance system, maybe you can live with 3% bug, and if it’s a game maybe you can do with 8% bugs. In practice I guess you never know how many bugs are in the system, but you do know how much it costs to catch the next bug. From my point of view, I have to guestimate how much our boss is prepared to live with such that he allows a Test Driven Development approach without getting pissed off at the perceived time it is taking (I say perceived, because convincing him the time will be made up when it comes to testing it and supporting it is an equally difficult task)

In order to get everyone working on everything smoothly, I definitely need a source control setup and I've decided to try a continuous integration setup too. I want developers to know how to use the source control tool, and what their responsibilities towards it are. I don't want them to be constrained by it or afraid of it. I want the CI process to run unit tests and to check code coverage. I need to think about configuration management and thus define a build process, a release process and a versioning policy. I would also like to eventually introduce an issue tracking system to better bring together support, development and management but define a process for its use and make sure that users are familiar with it and understand that is isn't an extended e-mail system.