15 February 2011

Test-First for Mental Health

I've been thinking recently about how a Test-First approach to development is good for our emotional well-being and psychological balance, and I believe this may be the most important reason to adopt test-driven  development.

Consider how we would traditionally develop software using a conventional Test-Last approach. We read our requirement spec (whatever form that takes), perform some design work -- as much as we feel we need to go forward with some confidence, and we start cutting code. Time goes by. Our codebase grows. We're doing some informal testing as we go along to feel confident that the code under development does what we think it should be doing...

And here's Important Point Number One: "the code does what we (the developers!) think it should be doing". Not what the business thinks it ought to be doing. See? We're inherently unsure -- even if only subconsciously -- whether we're doing work that actually serves the business. And unsureness is insidious and destructive to our well-being. We feel much better about ourselves as developers when we know that we're producing useful stuff that really has value. So here's the first way that having tests defined up-front helps us preserve our mental balance: With a reasonable set of tests1, defined together with our business partners, there's no bullshit involved; no trying to convince ourselves of the (probably shaky) value of our ever-growing codebase. We have an external, automated, objective, easily understood yardstick of value.

But there is, I think, a deeper psychological value to the Test-First approach.

So much of the time -- I will thumbsuck something like 99% of the time -- our code is broken. The system we're working on doesn't work. This is inherent in the fact that it takes us time to design and write software, and the continual not-workingness can be powerfully demoralising. Especially when we (finally, right towards the end of the project lifecycle) start formal testing, and our tester (often users) start coming back with bug after bug after bug after bug, and all that beautiful code we're so proud of is labelled "Less Than Satisfactory" -- usually in much stronger language than that.

Herein lies the secret destructiveness of Test-Last. Our code is always broken, and we can never do more than run after the brokenness trying to patch it up, until, at last, demoralised and exhausted, we move on to the next job or project.

Contrast this with a Test-First pattern.

We first write a bunch of tests. Sure it takes some time, can often be pretty tedious, and is frequently little more than a first-pass best-guess at what the code is supposed to do. Almost certainly we will add more tests as our code grows and evolves and begins to tell us the shape it wants and needs to be. But at least we start with a battery of (automated!) tests. And we start with the expectation of them all failing. This is by definition! We haven't written the necessary code, yet. A short time later we may have enough of the boilerplate in place that we can at least compile everything and actually run our tests, but we still expect them all to fail because our methods all read

throw new UnsupportedOperationExcetion( "TODO" );

So we run our tests, and they all fail. And we're happy about that! Everything went as we predicted. We feel in control.

As we go along replacing those stubbed-out methods, some of our tests begin to go green. We're making visible progress towards a well-defined end goal. We gain an ever-increasing feeling of confidence and accomplishment. We have tangible, objective evidence that we're making progress. Even when we make some of the "test bar" revert somewhat to red -- because we add new tests, or because we do some large-scale refactoring that breaks stuff -- we still feel good about it, because we know that our self-built safety-net is working! We've actually decreased the likelihood of things going wrong, so we know we're enhancing the quality of our product. (And every good developer I've ever worked with has an inner Proud Craftsman lurking in their soul.)

So it seems to me that Test-First builds our confidence and self-esteem as we go along, whereas Test-Last contains an inherently destructive, soul-sapping subversiveness to it.

I think this value outweighs the sum of all the other benefits (many though they are) of Test-First.

[1] Note that I make no distinction, here, between Unit Tests, Functional Tests, or System Tests (which would probably involve real databases, external systems, and so forth, albeit serving test data to our system-under-test.) I don't really care what form of Test-First is most useful to your team and situation. It's the principle that counts!

08 February 2011

Fusion Cuisine: Slicing and Dicing Courses to Suit Different Palates

Ever been faced with setting up training for some of your developers, but the courses offered by the usual suspects fail to cover the technologies your team uses? Or cover technologies that you don't use? Or lack the depth you're looking for in particular areas? Or too much depth...?

I was recently faced with a request from a client who want to put some of their junior developers through an Intro to Java course. The developers in question come from various other programming backgrounds, and already understand OO concepts and normal development disciplines. The "obvious" choice is the Sun/Oracle SL-275 mainstay course which I have been teaching (on and off) for something like 15 years, now.

But! A good part of SL-275 – and of my own Intro to Java course – delves into developing applications using the Swing GUI toolkit, used to construct desktop applications. This particular client is a company that only does web-applications, so learning a bunch of Swing concepts does them little good. I was happily able to propose that, instead of using Swing for that portion of the course, we could substitute some Servlet and JSP concepts and development. This arrangement serves them much better, as it also equips their developers with knowledge they will be able to immediately put to productive use. Fortunately I have lately put in a lot of work on a Servlet/JSP course, so I'm able to cycle some of that material into the Java Intro course.

It's not as simple as it sounds, though!

The Swing portion of "Intro to Java" also serves some other pedagogic purposes. It reinforces some of the OO groundwork covered earlier in the course by driving home the differences between inheritance, containment and usage. (At least it does the way I teach it!) Swing also provides a good platform for introducing listeners (Observer Pattern in the GoF book), Java's anonymous-inner class mechanism, and the exception-handling framework, along with a bunch of other bits-and-pieces that are useful for new-to-Java developers to learn, like converting between Strings and numbers.

So the challenge, now, is to make sure that I can adequately cover the same territory, and serve the same purposes, using servlets and JSPs. Not too hard, really, but it should make for a fun course where we can do a lot more hands-on, practical development work than the stock SL-275 allows.

The other tricky bit to watch is making sure that the level of detail doesn't overwhelm new-to-Java developers with too many web-application specifics. It is important to keep the focus on "Introduction to Java", and not lose sight of the real objective in a welter of webapp configuration and deployment.

Just a single, simple example of where and when customised courses can much better match the client's needs than any standardised, templatised training provided by a 4-week-per-month manual-pusher.
Contact me for a course customised to your organisation's needs!
Related Posts Plugin for WordPress, Blogger...