Monday, 12 December 2011

Does knowing a specific programming language matter?

This post is mostly inspired by a suggestion Steve McConnell makes in Code Complete: "Don't program in a language, program into it" (emphasis mine).


The traditional method of recruiting software developers is to go "We are writing our program in C++ so we should get a guy who does C++". I imagine many recruiters and companies use keyword filters on CVs to filter out candidates who don't have experience in the particular language used on the job. The basic premise of this post though, is that this is not necessarily going to get you the best man for the job.


My main points are:
  • The time needed to learn a new language is shorter than it was and isn't that long
  • 3 years doing 3 different languages is a better sign of a good and keen programmer than 3 years of 1 language
  • The overhead of learning a new language becomes a smaller proportion over time and is overridden by the extra productivity of a "better" employee
  • If you've only hired say, Ruby developers and then stop doing Ruby you can be in trouble
I should be clear and say that given 2 near-identical programmers, one with experience in the language you are using and one without, I would choose the one with experience in the language, but rather the point I'm making is that you shouldn't be afraid to hire someone who looks like a better programmer but doesn't have direct experience in the language.


A collegaue of mine recently said that you can grasp the basics of a language in about a month and start being confident and expressive in about 3 months and I agree. After that roughly 3 month stage, you start seeing diminshing returns on learning more particulars of that language (perhaps an example of the Pareto principle). The time taken to learn a language has dropped over the years, thanks to the wealth of information available on the internet in tutorials, blog posts and places like StackOverflow, as well as the reduction in the costs of publishing meaning more people are able to produce books on specific programming languages.


A good basing in a variety of languages, of different styles (eg OO vs functional, static vs dynamic typing) and a willingness to learn something new (I still don't quite believe that some people who were interviewed for my current role didn't want to learn JavaScript, I mean why wouldn't you want to learn something new?) are I believe, a better base for a productive programmer than just having experience in 1 language but for more years. This brings me to another point made in Code Complete applicable across all langauges (not just programming ones), that the language you know can actually affect the thoughts you are able to think. Being able to say "I know we're meant to be writing this in Java but there's a really easy and elegant way of doing it in Haskell" is of more value in my opinion that just steaming in and writing a sound Java implementation of every problem you come across. Importantly, experience in a variety of langauges is also a good sign that you've got someone who's interested in software development and does stuff outside of work rather than someone who just rolled into a say, Java job out of uni and then stayed in Java because that's what they'd done before and have never done any programming outside of work and education.


Now obviously, someone who's experienced in a language is going to be quicker to start writing in it than someone who isn't but that initial overhead will become a small proportion over the course of a long term employment (and hopefully you're hiring the kind of people you want to keep for a long time). The 3 month timescale I suggested above is obviously up for debate, but the argument here is based on the assumption that multi-language programmer will turn out to be more productive than the single-language programmer and thus cancel out the overhead, however large it is.


My final point is that hiring language specific programmers can seriously backfire if you decide to stop using the language. Kevin Rose of Digg raised this point at LeWeb conference where he said about hiring PHP developers to build out the Digg site "you end up with lots of PHP developers, but at some point, PHP isn’t a problem anymore and you are stuck with all of those developers". This is especially relevant I would think for startups, whose business direction is not as fixed as large corporations and may decide to pivot from say web development to iOS development and therefore suddenly need to be able to program in a different language.


Now obviously there will be some jobs where in-depth knowledge of the specifics of a language are going to be extremely useful, for instance in performance or safety critical applications (though many performance problems are best solved at the architectural level and so aren't very language specific anyway) but I don't believe that the majority of jobs are like that. Also I'm particularly biased in this discussion because I was hired into my current role as a JavaScript developer with no experience of JavaScript.

Sunday, 11 December 2011

Test-Driven Development Review

This post is a review of Test-Driven Development - By Example by Kent Beck

The book is organised into 3 parts. Firstly, Kent takes the reader through an example of using TDD to drive a simple few classes for dealing with money in different currencies, secondly, in a fun bit of meta-ness, he takes the reader through test-driving a unit testing framework from scratch, using the framework he is writing to test itself! The final chapter consists of a large number of patterns for TDD.

The book is written in a very casual, conversational style which makes for easy reading. There are a few times in the book where the author states that he cannot think of something or a better way "at the moment" though I would guess these were more a way of suggesting exercises for the reader than placeholders left over from the editorial process.

Some of the more interesting points I found in the book were:
  • Eliminate duplication, including duplication in tests of things in the production code
  • First make tests compile with stubs
  • When writing a test, invent the interface you would like to have
  • First make a test pass, then refactor bit by bit, keeping the test passing until the code is clean
  • 2 ways to quickly get to "green" (tests passing) - Return constants and gradually replace with variables until you have real code - use the real implementation straight away
  • Value Objects - represent a value, value never changes, operations return new value objects
  • Letting a test of 1 function depend on another function working is an educated risk
  • TDD cycle:
    1. Write a test
    2. Make it compile
    3. Run it to see that it fails
    4. Make it run
    5. Remove duplication (clean code)
  • you can entertain a brief interruption but never interrupt an interruption ( use a to do list to stop forgetting things)
  • "Sometimes you should just ask the computer" - make a change and run the tests
  • Sometimes write tests not to test external functionality but to inform future readers
  • After you've finished your todo list, review the code
  • 3 A's of tests: Arrange - create objects, Act - invoke methods on them, Assert - check results are as expected
  • If a test you write requires lots of changes to be made to pass, write smaller test cases and then reintroduce the big test
  • Isolating tests from each other encourages orthogonality in your code
  • Write the asserts in a test first and work backwards
  • Try to avoid mirrored data, eg 2 / 2 won't notice if arguments are wrong way round
  • First tests can be extremely simple but allow to decide where the function belongs and what inputs and outputs it should have step by step
  • Leave a broken test case at the end of a session so that you have something to work on next time, which will get you back into the same frame of mind
  • Abstract (ie return more than constants) only when you have 2 or more examples (tests)
  • If the obvious implementation is really obvious then just use that but fall back to faking and triangulation if you get red bars
  • Composite Object - treat collection of objects as if it were a single one of the objects
  • Seeing more than one message sent to another object in a method is a smell
  • "In TDD the tests are a means to an end - the end being code in which you have great confidence"
  • Keep tests that exercise the same path through the code is they convey different information to the reader
  • TDD leads to "just-enough" design
One of things I would recommend to do as was suggested by the author was to actually write the sample programs as you go through the book. This is because the book itself did not always provide an overview of all the classes at every stage and also because it's more normal for most people to look at code on a computer rather than in a book.

A point often made against TDD is that much time is spent writing test code as opposed to production code, and whilst the author believes that it is time well spent, he does also suggest that if you do start using TDD you should measure your productiveness so that you can see for yourself whether it works for you and your organisation.

In summary, the books serves as a very useful introduction to TDD and inspires in the reader the want to try it out. I would have liked to see more patterns about how to write code that is easy to test but that was not within the main aim of the book.

Link to buy the book at Amazon.com