Andre de Cavaignac

Let's blog it out...

Technical Lead: Managing Development & Source Control

Through my time in software development, I've often been a project lead or a technical lead in the group that I've been in.  The management of several developers and of the source that is generated has always been an issue, and with every project I've come closer to perfecting my solutions to these problems.  On the way, I've picked up advice from articles, coworkers, superiors and trial and error.  I certainly don't have the be-all-end-all answer to these problems, and am not sure if anyone does have them, however I like to believe that I'm edging closer to the holy grail.

Good and professional software developers are very hard to come by.  I've been told before that you need one good developer and a bunch of code monkeys to put together a project.  No matter how hard I'd like to believe that, its not true.  Modern software development requires deep understanding of core concepts that many people lack.  If you have a group of a few highly talented developers your ROI will be much higher than if you have 100 times the number of code monkeys, even if there is a talented developer overseeing them.

The most dominent difference between a code monkey and talented developer is an understanding of architecture.  A talented developer understands the architecture of the environment around him, and is able to architect his solution on the fly, building classes and methods necissary to make an intuitive, reusable and refactorable code base.  Unfortunately, this is one of the most difficult talents to come by.

The three most difficult (and most in demand) talents are also the most important for effective software development.

  • Architecture
  • Software management
  • Environment setup and maintainance

These three items, although a very small portion of development, are closely connected and probably the most important things to a groups effectiveness.

 

Environment Setup and Maintainance

The configuration and maintainance of the development environment is one of the most critical aspects of running development in a team.  The initial setup takes some time, usually a day to a week, depending on your experience with setting up environments and the training required in your team, but can save endless hours and headache once properly configured.  Very few teams properly configure their environment for effective development.  A well configured team will need the following (and must use them appropriately).

  • Source Control - Most teams configure a source control system, however very few teams that I have worked in or seen working use source control properly.  Branches and merging are two of the most important aspects of source control, however very few teams seem to understand how and when to properly use branches.  Nearly every feature in your project should be developed on a branch, and code merges should happen regularly.  See more below in the "Source Control" subsection.
  • Team task and issue management - Task and issue management is probably the second most common thing teams configure.  Unfortunately, most teams work with paper-based systems and do not seem to make a good distinction between "completed" and "released".  It is a big benefit if this aspect of your rig integrates with source control's changesets and the integration's builds, but software packages that do this (like Team Foundation Server) are not always available.
  • Continuous integration (daily builds) - One oft-overlooked component of a good development environment is a daily build of the trunk (and/or important branches) of the source control.  Daily builds allow for regular status checks and a working build of the application that can be used and tested, with everyones changes combined.

 

Source Control

Source control is a difficult thing to tackle without seeing a system congfured properly in the first place.  It took me a while to fully understand how source control should work.  Ultimately, there are two ways to think of source control, and it depends on how large and how long running your project is.

Source Control Method 1: Long running, Large Project and/or Many Developers

The first method uses branching to split off versions of the project.  This means that you know ahead of time what features will enter which version of the project.  If a version is a long-running development effort "sub version" branches may be created to mark milestones.

Very large developer groups may want to have a version branch, and branches off the version branch for features or feature sets.  This allows smaller groups of developers to share code amongst themselves, but not affect the other developers on the version.

In any case, all code that is checked into or merged into the version and trunk should be buildable code.  These are the branches that you will do your continuous integration on, and any new feature may be derrived from.  A broken trunk will significantly slow down development time.

Typically when releasing when using this model, you will release from your "version" branch, not from the trunk, as other versions may have edited the trunk.  Hotpatches and critical bug fixes that affect all versions, or need to be released as a patch to the current production version should be a new branch off the trunk that is merged back into the trunk when its completed.  Any version that is about to be released should have the trunk reverse-merged into it so it picks up these changes.

Source Control Method 2:  Small Development Teams and/or Short Running Projects

The second source control method uses less branches to achieve similar goals.  In a rapid paced environment where less emphsis is placed on versioning, the trunk can be considered the "latest version" that is released.  In this scenario, all work is done on a seperate branch (or multiple branches if different features are being built).  Small fixes or patches are applied as short-lived branches off the trunk that are immediately merged back in.

In this model, when releasing, you will merge any features destined for the release into the trunk and build that as your release.  The risk to this model is that the trunk is overall less stable because it is being continuously changed for releases.  If less QA is going into your product between releases, this model should suffice.

Notes on Source Control

The hardest part about source control is getting everyone else to play along.  Users should only checkin code that works.  Many developers checkin whatever they have daily, for fear of losing it.  This is fine, but then give that developer their own branch and let them merge when they are done.  Developers who checkin code that doesn't work should feel your wrath :-).

Continuous Integration

Continuous integration benefits you because you can always checkup on the health of your branches, always have the option of testing and releasing a build on a given day, and have the ability to rollback to a previous release should something go wrong.  In addition, by doing the integration processing on a seperate machine, you ensure your project thats in source control is always buildable by a machine not configured as a development machine.  This meants that your project will most likely "copy and run" when setting up new developers.

I much prefer Team Foundation Server for the continuous integration tasks.  The reporting you can get from TFS is great.  In circumstances where TFS does not exist, your options are usually NAnt, or MSBuild.

I am not a big fan of NAnt, as creating project specs is not simple.  I have been using MSBuild in this situation along with PowerShell.  I create a PowerShell script that pulls from source control, sets up my environment and runs MSBuild with the SLN file, then copies output to an "install" directory.  This is typicially a pretty solid solution.  Throw the PowerShell script in the "Scheduled Tasks" and instant continuous integration. Woot!

 

Developers, Developers, Developers.... Management

Management of development teams is not a trivial task, especially when the team is not of your picking (as is usually the case).  Many teams you will enter have a mix of good and "less good" developers.  The good (level 1) developers will be happy with a good architecture and will architect their own code while they write it, keeping in mind where the project is going.  The not-so good (level 2) developers will write long procedual code, copy/paste and generally ignore their sorroundings and habitat.  Unfortunately, we are typlically required to manage both types.

Management of a development team is a test of not only your social and managerial skills, but also your architecture skills.  The goal as a technical lead of a project should be two fold:

  • Manage the tasks at hand to complete the project
  • Manage the architecture of the system

Managing the tasks is mostly handling the assignment of the jobs.  Choosing the right person for the task, and making sure it gets done.  This is basic project management, and in large projects, may be delegated to a project manager.  I am not going to write a project management book here as there are plenty of them already, so lets skip this.

Managing architecture is a skill that few people talk about and more people should be doing.  This is a skill that I am still working on perfecting, and something I only recently discovered.  Good architecture is many things.  Many people say good architecture means code is legible, flexible, consistent, reusable/refactorable and stable.  These are definately major qualities of good architecture, but I'd like to add one more.  Good architecture should be usable by the not-so-good developers in your team.

The developers that can't see architecture generally know somewhat how to use it (they use the .NET of Java SDK's, for example).  Your architecture should be transparent enough to them that they can query simple interfaces you give them for data.  Outside of that, it should blackbox any code that someone rights.  Like modular, unit-test driven development, the not-so-good developers should be coding an object or screen or whatever in a box -- somewhere that you say "here are your inputs, here are your outputs, and here are the services you can use -- make me this".  No one should ever care whats going on inside as long as the code works.  Service oriented architectures generally aid this situation greatly.

A few things to consider when building an architecture that can handle bad code:

  • Modularize as much as possible
  • Use things like dependency injection to allow novice developers to get to interfaces without having to touch any of your external APIs.  If you can say "use interface IDataAdapter" and they can just "import" that, all the better.  If you are writing a Winforms app, consider using CAB (Microsoft Composite UI Application Block) to aid in this.
  • Consider using an SOA design.
    • If this is a GUI application, have your better developers work out the backend, and expose an interface early on.  The SOA can be a Windows Service in the backend and the UI in the front end querying it over remoting.  Let the more novice developers deal with UI layout code (especially in the context of ASP.NET).  Give them the interface and let them go. 
    • If this is a server-side application, modularize components into seperate services talking through interfaces or remoting, and have developers concentrate on their part

In any case, this turned into a much more lengthy rant than I expected.  I really just wanted to write down some thoughts.  I hope this is somewhat helpful to someone.  None of this is revolutionary, but I've never read anything that summarizes development in a team, so I figured I'd write something up.

Tell me if you have any ideas to contribute!

Leave a Comment

(required) 

(required) 

(optional)

(required)