Saturday, December 5, 2009

Three heresies

I encourage people to think for themselves rather than following cargo cults. You might or might not agree with the three heresies I've written about here, but do at least think about them.

Public fields

In Java code, instead of having a public getter and public setter for a field, why not just make the field public? It's much simpler and less code. If you later need a getter and setter for some reason you can always refactor to that (and many IDEs will give you help doing it). There is a comment by Richard Gomes at the end of this previous article on the subject of public fields for data objects. I think public fields make most sense for NOJOs (data objects) (in the rare case where a NOJO is useful - not very often) but maybe it would sometimes make sense for other sorts of classes too?

Note that having public access to a field is not what I'm trying to encourage. The point I'm making is that if you do have public access to a field then it doesn't matter much whether it is by getter/setter or making the field public, so you might as well use a public field as it is simpler. (But please, tell don't ask instead.)

Magic values instead of constants (in build files)

Instead of always factoring out magic values as properties in your build file, consider just using the magic value where it makes sense. For example, maybe instead of "${src}" just use "src" (and get rid of the property) - this was suggested by Jeffrey Fredrick at CITCON Paris 2009. I think there is a lot of merit in this approach. What are the chances that you'd be able to just modify the value of the "src" property and everything would still work? Probably quite low - you'd probably do a text file search for "src" anyway. What are the chances that you'll want to change it anyway? I think it's worth thinking about whether it's better or worse to factor out constants in some cases.

Make the CI build fail fast rather than run all the tests

Rather than running all the tests in your CI build, how about have the build fail as soon as any test fails? That way, a failing build uses less of your build farm's capacity. If your build farm capacity is limited, then this approach may result in getting a passing build sooner (as when the fix is committed there may be a build agent available for running the build with that commit sooner because it's time isn't being taken running a build which will eventually fail anyway). I think it's often more important to know which commit broke the build than which tests failed in order to know both who should fix the build and what caused the build breakage. This approach might not be so good if you have a flickering build (i.e. randomly failing tests) - however, making the build reliable can be achieved and is worthwhile anyway.

More heresies to follow

I have other heresies to write about. Please suggest your own in the comments.

Copyright © 2009 Ivan Moore

Tuesday, November 24, 2009

Java Enums with constant-specific methods

One of my colleagues introduced me to this handy language feature of Java 1.5 and I wanted to write an article about it because I hadn't seen this before.

Using google reveals that it is already well documented if you RTFM, but I will repeat it here because talking to other Java developers indicates that it isn't as well known as it deserves to be. Here's a slightly reworded extract from the first hit on google or bing for "java enum":

You can declare abstract methods in an enum and override them with a concrete method in each constant. Such methods are known as constant-specific methods. Here is an example using this technique:

public enum Operation {
PLUS { double eval(double x, double y) { return x + y; } },
MINUS { double eval(double x, double y) { return x - y; } },
TIMES { double eval(double x, double y) { return x * y; } },
DIVIDE { double eval(double x, double y) { return x / y; } };

// Do arithmetic op represented by this constant
abstract double eval(double x, double y);
}

Copyright © 2009 Ivan Moore

New version of Jester released

It's been a while since I last updated Jester (a mutation testing tool).

Today I released a new version of Jester - not much changed - but hopefully a bit easier to get it to work, based on my experiences of trying to use Jester when I haven't tried for a while.

It now doesn't read configuration files from the classpath - instead you specify the relevant files on the command line.

Copyright © 2009 Ivan Moore

Sunday, November 8, 2009

XpDay London, 7th & 8th December 2009

It's XpDay soon - book your place now. The Keynotes look particularly good this year.

On Monday there's an experience report that looks very interesting "When Agile Might Not Be The Best Solution" - it's good to see this sort of experience report on the programme because there's probably more to learn from it than one which goes something like "we did XP and it worked".

There are lots of other interesting looking sessions too - plus lots of open space sessions which can be excellent.

Copyright © 2009 Ivan Moore

Saturday, October 31, 2009

Pair Programming interviews/auditions

I have done a lot of pair programming interviews for my client. I enjoy doing them and I think they are extremely valuable.

Hiring is probably the most important thing to get right, and I think that pair programming interviews (or "auditions" as some like to call them) are usually the best way to interview developers.

Setting up a pair programming interview

For interviewing Java developers, I have a machine set up with a choice of IntelliJ IDEA and Eclipse with an empty workspace. I think it is important to try to make the candidate as comfortable as possible with the development environment so that it isn't a distraction. If you work with Apple Macs, also provide Windows (and maybe Linux) machines for candidates who aren't familiar with Macs because otherwise the difference in IDE shortcuts gets in the way and the idea of a pair programming interview isn't to see how familiar the candidate is with a particular OS.

I allow one hour for these interviews - I have found that is long enough to get a good idea about the suitability of a candidate.

Choosing a problem

One of the most surprising things is how small the problem has to be in order to be achievable in one hour. Developers (including myself) are often very optimistic about how quickly they can program a solution to a simple problem. I would urge you to try out the problem you want to use for a pair programming interview with a trusted colleague, before using it with a candidate, to find out whether it is realistic. To give you an idea of the size of problem you need, I used to use the problem described in this article.

I know of another team at my client who provide a small code base pre-prepared for the interview which includes a bug which the candidate has to find. I think this is a great idea. Choose a problem which is realistic for the sort of code that the candidate will be writing (or the sort of work they will be doing, e.g. debugging legacy code) in the job you are hiring for. There is no point testing for whether a candidate can write WeakHashMap from scratch if you are hiring for a typical enterprise IT project.

What pair programming interviews demonstrate

Pair programming interviews aren't a silver bullet for recruiting developers - they are good at determining some qualities of a candidate but not all. In particular I think they are more valuable in demonstrating programming style and personal interaction rather than problem solving. However, in typical enterprise IT projects, more problems are caused by over complex solutions to simple problems, or by solving the wrong problem, than having problems that are unique and difficult and require a brand new algorithm.

Sometimes it is good to use a problem which has some potential for ambiguities in the details of what is being asked for. This is a very good way to see whether a candidate asks for clarification or just makes assumptions which aren't justified. In enterprise IT systems, making assumptions about the desired behaviour of a system can cause a lot of rework and bugs so I look for candidates who demonstrate that they are thinking through possible ambiguities and who pro-actively ask for clarifications about the problem.

Being realistic

I make it very clear to candidates that I am looking for production quality, simple code rather than for them to show off all the language features they know. The problems that I choose are simple enough that I'm not interested in just getting a solution. I am looking for code that I would be happy working with. My boss, Pippa Newbold, has a very good rule of thumb. "At the very least, don't hire someone who will make the code base worse". It seems obvious and yet at other companies I have sometimes observed panic hiring just to make up the numbers where this rule would have saved lots of rework and bugs.

Giving something back

I try to teach the candidates something new in a pair programming interview where possible. Often this is something like an IDE shortcut but is occasionally a language feature or a "programming in the small" style discussion. I like candidates to get something back for giving up their time to come in for an interview, and a pair programming interview can be very daunting for candidates not used to pair programming.

Does it work?

As far as I can tell, all candidates that I have "passed" using a pair programming interview have turned out to be worth hiring.

However, that doesn't include those candidates that I've "passed" who didn't take the job and I don't know whether any of those candidates that I've "failed" would have been good either.

My suspicion is that it is a technique which is slightly more prone to "failing" good candidates than hiring poor candidates, but that really is just a gut feeling. If anyone knows any studies on pair programming interviews I'd be very interested to hear more.

Where it probably doesn't work

I guess that interviewing people for research or work which requires solving deep and difficult problems probably requires a different approach. Also, for hiring people with limited programming experience who you want to train up it might not be suitable.

Copyright © 2009 Ivan Moore

Thursday, July 9, 2009

Cleaner code

I recommend the book "Clean Code" - I completely agree with its philosophy and have written a few articles of my own about "programming in the small".

Mike Hill and I presented a session on "programming in the small" at the "Software Craftsmanship" conference 2009 in London and at QCON London 2009 - and one of or examples was taken from "Clean Code".

Clean Code

One of the examples in "Clean Code" is some code for parsing command line arguments, written in Java by Bob Martin. It is shown as an example of code which has already been made clean. There is an article (separate from the book) by Bob Martin about the code we use for this example. The source code is available from github:

git clone git://github.com/unclebob/javaargs.git

Mike and I chose this code because we wanted to take code which was already quite clean and show how even good code can sometimes be cleaned up even more - we wanted to push the cleanliness as far as possible in the session.

Just looking at the "Args" class only, this method seemed the one most wanting some further work (sorry, formatting is ugly - reformatted to fit blog page width):

private void parseSchemaElement(String element)
throws ArgsException {
char elementId = element.charAt(0);
String elementTail = element.substring(1);
validateSchemaElementId(elementId);
if (elementTail.length() == 0)
marshalers.put(elementId,
new BooleanArgumentMarshaler());
else if (elementTail.equals("*"))
marshalers.put(elementId,
new StringArgumentMarshaler());
else if (elementTail.equals("#"))
marshalers.put(elementId,
new IntegerArgumentMarshaler());
else if (elementTail.equals("##"))
marshalers.put(elementId,
new DoubleArgumentMarshaler());
else if (elementTail.equals("[*]"))
marshalers.put(elementId,
new StringArrayArgumentMarshaler());
else
throw new ArgsException(INVALID_ARGUMENT_FORMAT,
elementId, elementTail);
}

So - what could be better? What struck Mike and I was the duplication of "marshalers.put(elementId, new XXX());"

To remove this duplication, first extract a variable called argumentMarshaler of type ArgumentMarshaler in each of the branches, then move the expression "marshalers.put(elementId, argumentMarshaler);" outside of the if statement, and the declaration of the variable "argumentMarshaler" before the if statement. You end up with:

private void parseSchemaElement(String element)
throws ArgsException {
char elementId = element.charAt(0);
String elementTail = element.substring(1);
validateSchemaElementId(elementId);
ArgumentMarshaler argumentMarshaler;
if (elementTail.length() == 0) {
argumentMarshaler =
new BooleanArgumentMarshaler();
} else if (elementTail.equals("*")) {
argumentMarshaler =
new StringArgumentMarshaler();
} else if (elementTail.equals("#")) {
argumentMarshaler =
new IntegerArgumentMarshaler();
} else if (elementTail.equals("##")) {
argumentMarshaler =
new DoubleArgumentMarshaler();
} else if (elementTail.equals("[*]")) {
argumentMarshaler =
new StringArrayArgumentMarshaler();
} else
throw new ArgsException(INVALID_ARGUMENT_FORMAT,
elementId, elementTail);
marshalers.put(elementId, argumentMarshaler);
}

Now it's clearer that this method is doing too many things - one of those things being to find the relevant marshaler. We can extract a method for finding the marshaler and, having been extracted can improve it further by removing unnecessary structured programmingness, ending up with:

private void parseSchemaElement(String element)
throws ArgsException {
char elementId = element.charAt(0);
String elementTail = element.substring(1);
validateSchemaElementId(elementId);
marshalers.put(elementId,
findAppropriateArgumentMarshaler(elementId,
elementTail));
}

private ArgumentMarshaler findAppropriateArgumentMarshaler(
char elementId, String elementTail)
throws ArgsException {
if (elementTail.length() == 0) {
return new BooleanArgumentMarshaler();
} else if (elementTail.equals("*")) {
return new StringArgumentMarshaler();
} else if (elementTail.equals("#")) {
return new IntegerArgumentMarshaler();
} else if (elementTail.equals("##")) {
return new DoubleArgumentMarshaler();
} else if (elementTail.equals("[*]")) {
return new StringArrayArgumentMarshaler();
} else
throw new ArgsException(INVALID_ARGUMENT_FORMAT,
elementId, elementTail);
}

Notice that "elementId" is only used for the exception to throw if an appropriate ArgumentMarshaler cannot be found. Further investigation shows that actually this parameter isn't used in ArgsException for an "INVALID_ARGUMENT_FORMAT" and we can just delete this argument (and hence the "elementId" parameter of "findAppropriateArgumentMarshaler") with no change to the behaviour of the code!

There is more that can be done with the Args class - but that is beyond the scope of this article.

Conclusion

I hope this has shown that even clean code can be made cleaner - without having to do anything too clever or drastic. It's often easier to see such opportunities in other people's code or code you haven't seen for a while - even the best programmers can miss opportunities for making code simpler.

Copyright © 2009 Ivan Moore

Saturday, June 20, 2009

Project management lessons - commitment

Have you ever heard (or said) something like "you've got to work [long hours/weekends] because the customer has been promised [some system/feature] by [some date]"?

Commitments can be made but not assigned

People only feel committed to things they have committed to themselves. Telling someone that they have to work long hours/weekends because of a commitment someone else has made can lead to demotivation and resentment. Productivity is very likely to suffer (quality decreasing, more rework due to mistakes, more stupid things done due to rushing or tiredness). Seeing that the work isn't being completed quickly enough, bad managers think that it just requires even more hours to be put in (they try to impose "more commitment" and concentrate on the inputs rather than the outputs). This is the recipe for a "death march" project.

Estimates are not commitments

As a project manager, you have to understand the difference between an estimate and a quote. An estimate is not a commitment. As a project manager, if you make a commitment that something will be done by a certain date then do not rely on being able to just use estimates directly - you need to apply some project management techniques. One technique that I have found works well, as mentioned in my previous article is "extreme planning".

Commitment can work wonders


When someone really feels committed to something, then they will be motivated and focused. Software developers will often work harder and more effectively on their pet open source project than they do at work due to this motivation. This sort of commitment cannot be forced onto someone. There are lots of ways to ensure it doesn't happen (sadly common) and a few things you can do to provide an environment in which it might happen - and hence see massive improvements in productivity and quality as a result.

One factor is the level of technical autonomy. Many large companies have standards which are intended to reduce costs (for various reasons I won't go into). Unfortunately, I think in many cases these standards tend to reduce teams' technical autonomy, which reduces motivation, having a larger negative effect on productivity (hence cost) than the savings made by the standardization. I'm thinking of things like (for example) being told you have to use Wholly Pointless Server when some free open source app server would be a better choice.

Another factor which I think is very important is how directly developers work with their customers. A lot of developers (and certainly the ones I like working with) like to do things which are useful and appreciated by the users of their software. Sometimes the way teams are set up there is a separation between developers and customers - often a business analyst who understands the business and is more available than the real customer(s). This does have benefits when a developer wants a question answered straight away (but the customer isn't available), because otherwise the developer would be blocked or have to context switch onto another area of work. However, I think the best arrangement (not always possible) is when the real customer is available all the time and the developers talk directly to them. The worst situation is when only the project manager or business analyst talks to the customer and approaches the developers with an attitude of demanding features rather than working collaboratively for the best solution.

There are lots of other factors involved in motivation - I might write more in a future article - if I can be bothered. :-)

Bike ride commitment

As an example of commitment - I said I'd do the London to Aachen bike ride and people sponsored me to do it (many thanks), so I felt a commitment to do it. If I hadn't felt any commitment then I wouldn't have done it because, frankly, it wasn't much fun. Here's a quick summary of how it turned out:

Day 1 - Gatwick to Dover/Dunkerque (85 miles cycling) - it wasn't too bad - a bit of drizzle, nice scenery and the cycling was not too tough. (We then got a ferry to Dunkerque - the staff at Norfolk line ferries were great, putting on a fantastic meal, and a tour of the bridge, specially for us).

Day 2 - Dunkerque to Waterloo (139 miles) - we had an early start (breakfast at 6:30am local time, i.e. 5:30am UK time) - in order to do 70 miles before lunch - the roads were totally flat but it was into a headwind the whole way - it was brutal. Some participants skipped the afternoon cycling and got a minivan to the hotel straight after lunch. Immediately before lunch I felt like going in the van too, but after some food felt much better and thought I'd try to keep going. The afternoon turned out to be much better - it was a bit hilly but much less windy. At around 100 miles for the day, 3 other particpants dropped out and got in the support van. At around 120 miles for the day I was knackered - but just about managed to finish the day's ride - going really slowly for the last 20 miles.

Day 3 - Waterloo to Aachen (106 miles) - I was knackered from the day before - so I took it very easy, along with some of the others who had struggled to complete the previous day's ride. There were some cobbled roads, which on a race bike are very scary. Near the end of the day, going up a long climb (which features in the pro cycling "Amstel Gold" race), we cycled through a thunder storm - we had hail, torrential rain (consequently very bad visibility), thunderbolts and lightning (very very frightening).

Copyright © 2009 Ivan Moore