Agile Zone is brought to you in partnership with:

David Green is a developer and aspiring software craftsman. He has been programming for 20 years but only getting paid to do it for the last 10; in that time he has worked for a variety of companies from small start-ups to global enterprises. David co-founded the London Software Craftsmanship Community (http://www.londonswcraft.com/) - a group of professional programmers who meet regularly to exchange ideas and improve their craft. David is a DZone MVB and is not an employee of DZone and has posted 24 posts at DZone. You can read more from them at their website. View Full User Profile

Shame driven development

12.27.2011
| 6745 views |
  • submit to reddit

I always aspire to write well-crafted code. During my day job, where all production code is paired on, I think our quality is pretty high. But it’s amazing how easy you forgive yourself and slip into bad habits while coding alone. Is shame the driving force behind quality while pairing?

We have a number of archaic unit tests written using Easy Mock; all our more recent unit tests use JMock. This little piece of technical debt means that if you’re changing code where the only coverage is Easy Mock tests you first have to decide: do you fix up the tests or, can you hold your nose and live with / tweak the existing test for your purposes? This is not only distracting, but it means doing the right thing can be substantially slower.

Changing our Easy Mock tests to JMock is, in principle, a relatively simple task. Easy Mock declares mocks in a simple way:

private PricesService prices = createMock(PricesService.class);

These can easily be converted into JMock-style:

private Mockery context = new Mockery();
...
private final PricesService prices = context.mock(PricesService.class);

EasyMock has a slightly different way of declaring expectations:

prices.prefetchFor(asset);
expect(prices.for(asset)).andReturn(
    Lists.newListOf("1.45", "34.74"));

These need to be translated to JMock expectations:

context.checking(new Expectations() {{
    allowing(prices).prefetchFor(asset);
    allowing(prices).for(asset);
        will(returnValue(Lists.newListOf("1.45", "34.74")));
}});

This process is pretty mechanical, so as part of 10% time I started using my scripted refactoring tool – Rescripter – to mechanically translate our EasyMock tests into JMock. Rescripter let’s you run code that modifies your Java source. But this is more than just simple search & replace or regular expressions: by using Eclipse’s powerful syntax tree parsing, you have access to a fully parsed representation of your source file – meaning you can find references to methods, locate method calls, names, parameter lists etc. This is exactly what you need given the nature of the translation from one library to another.

This was inevitably fairly exploratory coding. I wasn’t really sure what would be possible and how complex the translation process would eventually become. But I started out with some simple examples, like those above. But, over time, the complexity grew as the many differences between the libraries made me work harder and harder to complete the translation.

After a couple of 10% days on this I’d managed to cobble together something awesome: I’d translated a couple of hundred unit tests; but, this was done by 700 lines of the most grotesque code you’ve ever had the misfortune to lay your eyes upon!

And then… and then last week, I got a pair partner for the day. He had to share this horror. Having spent 10 minutes explaining the problem to him and then 15 minutes explaining why it was throwaway, one-use code so didn’t have any unit tests. I was embarrassed.

We started trying to make some small changes; but without a test framework, it was difficult to be sure what we were doing would work. To make matters worse, we needed to change core functions used in numerous places. This made me nervous, because there was no test coverage – so we couldn’t be certain we wouldn’t break what was already there.

Frankly, this was an absolute nightmare. I’m so used to having test coverage and writing tests – the thought of writing code without unit tests brings me out in cold sweats. But, here I was, with a mess of untested code entirely of my own creation. Why? Because I’d forgiven myself for not “doing it right”. After all, it’s only throwaway code, isn’t it? It’s exploratory, more of a spike than production code. Anyway, once its done and the tests migrated this code will be useless – so why make it pretty? I’ll just carry on hacking away…

It’s amazing how reasonable it all sounds. Until you realise you’re being a total and utter fucktard. Even if it’s one-use code, even if it has a relatively short shelf-life 

the only way to go fast, is to go well

So I did what any reasonable human being would do. I spent my lunch hour fixing this state of affairs. The end result? I could now write unit tests in Jasmine to verify the refactoring I was writing.

Not only could I now properly test drive new code. I could write tests to cover my existing legacy code, so I could refactor it properly. Amazing. And all of a sudden, the pace of progress jumped. Instead of long debug cycles and trying to manually find and trigger test scenarios, I had an easy to run, repeatable, automated test suite that gave me confidence in what I was doing.

None of this is new to me: it’s what I do day-in day-out. And yet… and yet… somehow I’d forgiven myself while coding alone. The only conclusion I can draw is that we can’t be trusted to write code of any value alone. The shame of letting another human being see your sorry excuse for code is what drives up quality when pairing: if you’re not pair programming, the code you’re writing must be shameful.

 

From http://blog.activelylazy.co.uk/2011/09/06/shame-driven-development/

Published at DZone with permission of David Green, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Robert Craft replied on Thu, 2012/01/26 - 5:08am

I love the idea of using a programming tool to solve a programming problem, would love to see a demo one day (one of my projects is thinking of moving from JMock to Mockito). The only tests I’ve got so far are for some very specific scripts I’m using in some refactoring at work (which means I can’t share the details). But I will share a project with the jasmine & rhino integration – then I can hopefully give a quick example of how it works. When I get chance I’ll try and write some tests for the tutorial. I’m also working on a bigger example which I might try and test drive with jasmine.

Spring Framework

Mike Dzone replied on Tue, 2011/12/27 - 10:25am

Whenever you are dealing with tests, you are stuck with the unfortunate fact that development time is going to greatly increase. I typically give two time estimates for projects, one doing things the "right" way by writing unit test coverage and two, getting the project done.  Needless to say, getting the project done wins out every time. 

Personally, I am quite tired of this whole push for the software developer to do everything.  I typically have to do my job (developing software), the testing teams job (automated testing of the software), the DBA's job (table design, indices, keys, etc.), and operations job (firewall rules, glassfish config, etc.)  This is absolutely insane! Imagine building a house and requiring a plumber to do electrical and concrete...you'll never get a good house built.  Same with software.  There is zero reason, NONE, why I should have to teach or maintain tests for software.  This is the test teams job, let them do it.  If a tester cannot do it, the tester is not doing their job.  Developing complicated enterprise software is a team effort and EVERYONE should be held accountable.  This doesn't happen though.  Instead the development team has to make up for the weak links everywhere else, so we get into the mess we are in now.  

Aaron Digulla replied on Tue, 2011/12/27 - 10:58am in response to: Mike Dzone

I feel this is wrong on several levels:

- Giving two estimates: Is the quality the same without tests? If so, great. But then, your projects are either dead simple or maintenance cost is taken from another budget - which means you still hurt the customer, just not up front (which often works better but still ...)

- Developers need to do everything: The comparison with a plumber is a apples with oranges. Software is like nothing in the real world. It's about managing information and ideas. Plumbers work with rock and steel, not ideas. Their creativity is mostly how to cover up their blunders and how to stretch breaks to get a full workday break without annoying interruptions.

Yes, we don't have the proper tools to do everything right but we make many important decisions (like the DB design) so we need to know about DBs. We decide how the result works, how it must be installed and configured, so we need to know about operations, monitoring, file systems, procedures and stuff.

Getting developers to test their code with unit tests is much cheaper and way more efficient than (ab)using the testing team. The testing team should be used for tests that "can't" be automated. Well, "can't" as in "way too expensive to automate", not as in "we've written software that behaves random".

In my own career, I routinely find that I can reduce stress levels to normal when I have enough unit tests, so that I don't have to worry all the time what I might accidentally break. On top of that, I can work more boldly because I can stride with confidence. If a developer doesn't care about tests, they are either in the middle a nightmare shipping (deadline was yesterday) or they are dangerous and should be fired.

Mike Dzone replied on Tue, 2011/12/27 - 1:09pm in response to: Aaron Digulla

It is not an apples and oranges comparison.  It's a matter of skill sets and what's needed to get something done.  Most software projects are lacking key skill sets and it is usually up to the developer's to pick up the slack.  This is insane and does not and cannot happen in other disciplines.  Yet for some reason we think it is OK and we make work arounds in our daily work to reinforce that it's OK. 

Aaron Digulla replied on Fri, 2011/12/30 - 4:50am in response to: Mike Dzone

Sounds like the "being too agreeable" problem. Erick Erickson wrote a great piece on that: Stop being so agreeable!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.