Why aren’t we using Git?

This is a template email I’ve saved for when anyone bales me up in the elevator at work, asking why we’re not using Git:

I get asked this a lot. Almost weekly.

First of all, I think Git is great, it really shifts teams away from the single node distributed development model used by CVS and Subversion and opens up a world of possibilities for feature branching, release branching, mixed stream development and various other source code gymnastics that teams might need to perform. I personally use it at home. It makes Subversion look like “the dark ages” (yes, someone has actually said that to me with a straight face).

However, at |company name|, we will not be migrating to Git in any foreseeable future plan; I would not expect Git to be in mainstream |company name| usage for at about 10 years. For a company that is just phasing out IE6, this would be like the Wright Brothers planning a lunar mission.

“Why?” I hear you ask. “It’s awesome. It gives us so much more flexibility!”, “…it’s more powerful”, “..it’s more reliable”, “..it’s faster”.

Some of the hyperbole people use to describe Git is completely true, and some is just outrageous hype. 10 years ago I remember exactly the same comments about Subversion. “How can I possibly survive without atomic commits?” they said. This is usually uttered by those who want to bang every nail with any shiny new hammer they can get their hands on; resume driven developers.

Yes, Subversion gave us some important improvements over CVS; directory movements and history by far the most important. But when it was new it also brought a whole heap of trouble. The tools were very poor. They were unreliable and at times quite dangerous. I’ve lost a few local changes over the years. But now it’s mostly stable. The tool support now is good, 1.7 seems to be a pretty well supported format. Not perfect, but good enough for my precious source code. And the transition from CVS to Subversion is pain free. The model is the same: single node, distributed. Nothing too hard to get your head around.

On the other hand Git is not easy to get your head around. In inexperienced and undisciplined hands it has the possibility to become a vastly complicated network of source code branches and sub-branches and sub-sub-branches. The tools are flatout terrible, hard to use and poorly documented. Is this “bad”? – no absolutely not, it’s exactly where Subversion was 10 years ago.

But at the moment, it’s bad for us.

We’re a bank. In a large organisation we rely on a variety of people at different skill levels to perform tasks using source control for really, really important reasons. These people are of mixed capability, some would be fine dealing with Git, most would not without significant investment in training and safety “process”; And there’s nothing we can do about the tools, it would only make the safety measures more critical. When you run software teams for a large number of different platforms and business goals (and I mean large), standardisation is important, allowing for the transfer of skills, ease of administration, support etc.

Subversion is currently the bank standard for non-mainframe application source control. There are critical audit remediation programs across the bank to move applications to source control (not just to Subversion, but to source control). There are other audit programs to move application source control to the banks supported Subversion service.

“moving to git” for one tiny, relatively insignificant application within |company name|, would be contrary to trying to achieve standardisation; contravening audits, not to mention the capability issues already mentioned.

“moving to git” is a much more problematic proposition than just how you check out your code.

The Maginot Line Anti-Pattern

Maginot Line
aka Maginot aka Unpainted Corner aka Ligne Maginot

Intent
To model, design or program something without any thought to flexibility or possible change.

Description
A design that will address a specific, direct problem without any possibility of being changed easily (in any way) in the future. A fixed fortification of code that can only ever address one very specific set of circumstances without being completely re-written. This pattern can be manifested at all levels: coded implementation, application architecture or enterprise architecture.

Taken from the Maginot Line – a fixed fortification built before World War 2 spanning the French/German border. Designed to protect France from a German invasion. Developed and maintained at great expense, it drained other parts of the French Armed Forces of more judicious investment, just in time for the war. The crafty Germans just went around it and conquered northern France in a few weeks in 1940.

Lighthouse

I purchased a build light for my team at work in November last year and have finally gotten around to putting it in place to monitor my CI server. I wrote a little framework called Lighthouse to manage when and how it turns on.

At about the same time I noticed that Simon Harris also purchased the same build light, but used a different CI server (servers?).

So, all this lead to Lighthouse supporting Hudson and Team City.

Download Lighthouse.

The Carrier Pigeon Anti-Pattern

I’m not sure if this lives by another name, but if not:

Carrier Pigeon
aka Viral Host aka Uninvited Guest aka Alien Attribute aka Chest Burster

Intent
To transport or represent a value or property.

Description
Add an attribute or property to a completely unrelated object so that the property or attribute can be used at a location, or within a scope, that the carrier object will exist in.

Implementation

public class Customer {
    private String firstName = null;
    private String lastName = null;
    private Date dob = null;
    private String databaseConnString = null;
    ....

    public void setDatabaseConnString(String value){
        this.databaseConnString = value;
    }

    public String getDatabaseConnString() {
        return this.databaseConnString;
    }
}

Software Development Minutiae Debates

I’m tired. I’m tired of endless circular debates, arguments, conversations and meetings about the minutiae of software development preferences and ‘best practices’.

Here’s a list of ones I’ve recently been swept up in at work:

  • Tabs versus Spaces
  • CVS vs SVN vs (yes, I know) Clearcase
  • random checkstlyle checks and their thresholds
  • Java generics usage
  • Spring MVC vs Struts vs Someotherfuckingframework
  • assert expect actual or assert actual expected
  • Maven vs notmaven
  • Mocking vs Stubs
  • business keys vs numeric keys in databases
  • pluralised database table names
  • Eclipse vs IDEA vs Somerandom IDE
  • Interface naming patterns – the “Impl” problem
  • Braces at the end or the beginning of a line
  • ..ad nauseum

I’m tired of these debates because, realistically, IT DOESN’T FUCKING MATTER.

All of the above choices are good and bad. They all have reasoned, sensible arguments, for and against. They will all help to render a working system. Your particular faith/experience based choice in any one of these religious debates is absolutely meaningless. You are merely pouring cash down the toilet by being stubborn and argumentative about your particular flavour of icecream.

What actually matters is that everyone in your team adheres to that choice consistently. So, seriously, shut the fuck up and get on with it.

There are much more important issues to change hearts and minds on:

  • Customer engagement models
  • Application design, layering and patterns
  • Work spaces for developers
  • Continuous Integration
  • Deployment
  • Consistent environments
  • Application responsibility
  • Developer skill/experience make up within teams
  • Automated unit/integration/interaction testing
  • Estimation models

The small stuff only diverts our attention from the things that actually matter.

Testing applicants for the 1% of knowledge is insane

At my current employer I’ve spent a substantial amount of time vetting potential software development staff. In fact this is something I’ve done at a number of employers, but perhaps more so at my current one. As it’s a very large organisation I’ve been able to see various departments do it in various ways.

I’m constantly staggered when departments decide that the best way to filter applicants is to test them with a type of syntax-and-language-peculiarity questionaire (usually multiple choice). They do this in preference to any sort examination of the applicant’s design or problem solving skills.

In my experience (I obviously don’t have numbers for this) I would say that the vast majority of problems caused by unskilled development staff were not because they didn’t know the semantics to a JVM configuration flag, or something equally as obscure. I would say that the vast majority of problems are because they have little or no experience in designing and writing a program that other people can read and change (socialisable code) without melting their brains.

Why on earth would you bother with the obscure problem test? Sure it might show a depth of knowledge you might need, but in preference to any sort of design and code type test is pure insanity. Yet development managers all over the place think it’s really important if the applicant knows that ‘>>>’ is an unsigned right shift operator. Apparently testing an applicant for the 20 seconds of their career that they’ll actually need to know this (without access to Google) is more meaningful. Go figure.

Interface and Implementation naming

A friend at work recently pointed me towards this blog entry about naming practices for interfaces and their implementations. He essentially asserts that practices such as:

Service service = new ServiceImpl();
IService service = new ServiceImpl();

are completely redundant, and probably point to a lack of focus on the implemented functionality, it’s like the developer doesn’t really “get” interfaces. Anyway, the article twitched one of pet peves when I read other people’s code.

In my opinion such naming “practices” also show a complete lack of imagination. An implementation of an interface is designed to be a specific version of some abstraction; there must be something about it that would differentiate it from another implementation of the same interface. So a generic “practice” or “standard” for naming them is utterly useless.

My preference is:

CurrencyDAO dao = new PropertiesBasedCurrencyDAO();
CurrencyDAO dao = new JDBCBasedCurrencyDAO();

Ahh, isnt that so much more descriptive?