That’s that one covered.

Almost every project I have worked on over the last 6 years has incorporated a code coverage analysis tool into the build. Most of them have failed the build if the level of coverage has not reached a pre-defined standard and the others have at least reported on the coverage attained by the test suite. It’s nice to show a colourful chart showing a well-tested code base. Stake holders love that.

I recently joined a new project where the build was wired up with Cobertura which was happily reporting that the coverage levels were exceeding 90%. Everyone seemed happy. Nice charts, lots of green bars, warm fuzzy feeling.
In an idle moment, and out of the blue (I’d just built and checked in and was about to start something new), a few questions popped into my head:

Why did we have code coverage checks?
Why would these checks fail the build?
Why would we set the target to 90%?

The easy answers were:

To ensure that our code is tested.
To stop us from ignoring untested code.
It seems like a large enough number.

Hmm, those answers weren’t cutting it for me. I wasn’t feeling warm and fuzzy any more. Slightly upset, I asked myself:

How can I feel warm and fuzzy again?
What piece of testing information would make me happy?

Thankfully, the answer to those questions were also easy to come by:

I would be happy if the desired functions of the system were behaving as they should.
If the functional test suite was complete, correct, and showing 100% passes then we were delivering the right solution. Warm and fuzzy again. Phew.

But what about code coverage? Wasn’t that important? Did the code coverage report perform a useful task for us? Apparently, with regard to the functional tests, the answer was no. Functional tests drive the application; if the application behaves correctly code coverage is irrelevant.
Yes, that’s right, I was saying that I didn’t care if the functional tests exercised all of the code base as long as the system behaved as I expected in the situations I placed it.
So I removed the functional tests from consideration in the code coverage reports. That felt better. What about the integration tests? Same story. If the subsystem behaved the way I expected then the code coverage was irrelevant. I cared about behaviour not how much the code was exercised. The integration tests were also removed from consideration in the code coverage reports.

What about unit tests? Aah, that was it; the penny dropped. Unit tests drive the design (well they do if you test-drive design). One of the project development goals was to test-drive the system. Write a test. Watch it fail. Write some code. Watch the test pass. Refactor, rinse, repeat. We wanted to do this to help ensure that the system was well-constructed and easy to maintain. We care about unit tests exercising particular parts of the codebase. We would only write code to either satisfy a failing test or to refactor to improve design and eliminate duplication.

The build was now changed to only instrument the codebase for the unit test run. No other testing would be part of the code coverage analysis. The build failed. We no longer had 90% coverage. Code had been exercised during integration or functional testing that had not been exercised during unit tests. That code was not test-driven. It had been exercised coincidentally.

Our build was now doing its job of reporting on a failure to adhere to one of the development goals. The penny had dropped. That’s why we had code coverage reports incorporated into the build. Code coverage is important for unit tests. It shows that unit tests are driving the development.

My answers to the original questions were now:

Why did we have code coverage checks?
To ensure we are only writing the code we need.
Why would these checks fail the build?
If we forget to test-drive.
Why would we set the target to 90%?
We won’t, we’ll set the target to 100% and discuss any exceptions to this rule if and when we encounter them.

Posted in coding, testing, values | Tagged , , , , , | Leave a comment

LoFi Prototyping with Balsamiq Mock-Ups

Every now and again I get to use an application that just works. Sometimes I feel compelled to tell others about it.

We had a product development workshop this weekend and one of our aims was to ensure that our target customers would be happy with the experience when they eventually use our application. To reach that goal, we’d invited a selection of our target customers to help shape the direction of the product.

These customers are users of a system that isn’t quite cutting it on a number of levels; one of which is the capture and re-presentation of data in an appropriate context. It’s important for us to get it right so we got them to walk us through screen flows, describing the data to be captured and also how it should be represented within different contexts.

In preparation, Andy had stumped up 79USD for a copy of Balsamiq Mockups and within a few minutes had our customers happily designing screens and flows. The LoFi sketch look and feel helped to keep a sense of things being changeable and our customers were quite happy to move controls and data fields around until they felt comfortable.

They went away feeling that they had contributed to designing a usable product and we went away knowing we had enough information to make a start on development. Hats off to the people at Balsamiq for producing such a cool application.

Posted in usability, user-interface | Tagged | Leave a comment

Don’t spike till it hurts

Out of a spike, nothing but the newly acquired knowledge should be part of the final solution.

Both technology and technical creativity move along at a quick pace and people are always looking for better ways to solve their particular problems. The quest for improvement is a natural one. It is part of human nature. Innovation abounds and the abundance of new open source projects tackling similar problem spaces provide ample opportunity for the curious software developer to scratch that particular itch, be it as a contributor or a user.

Most software projects I’ve been involved with have included some new element of technology, or some new feature of a trusted technology. Whether this is a feeling of responsibility to always provide the optimal solution, or whether it is an eagerness to play with a new toy is debatable and there may be an element of both underpinning the quest for improvement. Fortunately, there has usually been the awareness of a responsibility associated with innovation. The introduction of the unknown should always be seen as a risk and should not be embarked upon without some means of mitigation.

If you try something new then you really need to have a safety net to take away the risk.

Typically this risk mitigation takes the form of a spike or technical task to prove the appropriateness of the technology to the solution. In the agile world a spike story is usually scheduled early on and is targeted to prove that the technology feature satisfies the project’s needs (as opposed to a time-boxed technology investigation where you schedule a fixed amount of time to explore a technology to see what features it offers).
In some cases, new technology adoption will involve the scheduling of a time-boxed technology investigation followed by a targeted spike. Firstly, find out what the technology can do then, secondly, prove that one of the identified features is suitable for the solution.

The use of spikes can be seen as reasonable and responsible risk-mitigation. And what’s more, it’s win-win. On one hand, proving the technology is a good thing – we made the right choice. On the other hand, disproving the technology is also a good thing – the risk mitigation was effective. What can go wrong?

Sadly, people occasionally forget that spikes are meant to be throw-away implementations. The only important artifact from a spike should be the knowledge acquired during the spike. Everything else should be thrown away. Ok, before anyone jumps on my case about that last sentence, it should read

Out of a spike, nothing but the newly acquired knowledge should be part of the final solution“.

Feel free to keep the spike code in subversion (or whatever SCM you use), just don’t use that code for anything else. A spike is a spike is a spike.

I have seen, too many times, programmers become attached to the spike, not wanting to let go.

If I just add a little more then it will solve our problem. Almost there…look it works!

Sure, it may be functionally correct, but how much attention to maintenance/readability/abstraction was paid during this spike? When I first thought to write this entry I was tempted to suggest that you code your spike in as procedural code as you can; violate your checkstyle checks; remove all temptation to include it in your main codebase. I almost suggested that any extra effort to provide the normal things we aim to produce in our coding efforts (clean, readable code with appropriately chosen abstractions) are fluff in this context.
A little over the top? Probably.

The focus of the spike should have been to prove or disprove the technology, nothing more, nothing less.

However, I’m trying not to send the wrong message here. I’m not advocating that programmers should throw away good habits; in fact, I’d hope that not to be the case. I’m advocating programmers acknowledge that spikes are disposable and should be treated as such. The nature of a spike precludes a programmer’s finest coding efforts and, consequently, spiked code should never be considered to be part of the final solution.

Look for shortcuts to get you to the aim of the spike. If this forces a temporary relaxation of rigour then acknowledge the reasons for the relaxation and complete the spike. This approach cannot be taken, however, if the goal of the spike is uncertain. The intent of the spike has to be clear. You need to know when to stop. There needs to be constraints applied to the story, similar to acceptance criteria, that make it obvious that the story is complete.
e.g. Stop if the library is not thread-safe.

Another manifestation of the programmer becoming attached to a spike is solution-affinity. This occurs when a programmer tackles the spike using the same metaphor as the project.

e.g. the project is concerned with car finance and the spike aims to prove that a particular workflow engine is suitable. If the spike uses concepts from car finance to prove the workflow engine (i.e. exactly the same metaphor as the project) then it becomes difficult to relinquish the approach taken in the spike. Any efforts to implement the technology will mirror that of the discarded spike. Again, this is a problem because the intent of the spike is different to the intent of the project. Different rules apply.

To avoid solution-affinity, attack the spike with a different metaphor. Try to divorce the proving of the technology from the overarching domain. Spike the workflow engine using a different domain. Change the context to free the programmer from bias built up during the spike.

Spikes can be effective risk mitigation tools but try to remember:

  • Never forget the purpose of the spike.
  • Always know when to stop.
  • Spike using a different metaphor.
  • Keep your rigour but optimise your approach to keep to the intention of the spike.
  • Throw away all but the acquired knowledge.
Posted in coding, spikes | 1 Comment

We value Technique over Technology

Today I spotted a job ad asking for a “Spring Developer”. This caused me to chuckle for a while as, a few months ago, James Pott and I had ribbed a new programmer on our team with the question

Do you consider yourself to be a Spring Developer or a Senior Spring Developer?“*.

Now this in itself isn’t a source of mirth but, in the context of said programmer consistently offering up Spring-based solutions to each project problem, it was humorous enough to continue the tease for a short while.

Is it enough in today’s market to express an affinity for a grouping of languages, e.g. “I’m an OO-programmer”? If that is too generic then would it suffice to narrow it down to “I’m a Java programmer”? Please don’t tell me that the level of granularity in the software job market now has to go down to a particular technology solution implemented in a particular language, e.g. “I’m a Spring Developer”.

I can understand a recruitment ad stating desired competencies in particular technologies but, surely, these specialisations should be mentioned under the main heading and as part of a list of desired skills. Restricting the position to those that have already spent the ridiculously short time period picking up a technology is short-sighted. These technologies are meant to be easy to learn. It’s not meant to be difficult to become competent in Spring.

Advertising jobs with an emphasis on technology knowledge will probably result in a swathe of applications from inexperienced developers. It’s a lot easier to pick up these technologies than it is to master the techniques demonstrated by mature programmers. Surely the recruiter has a responsibility to find the most suitable candidate for the position? If that is the case then the job ad should be phrased to that effect.

If I were placing a job ad, what skills would I be emphasising as desirable?

As a start, I’d be looking for someone who knows how to produce clean, self-describing, maintainable code; someone with a mastery of OO techniques; someone who understands how to refactor and how to drive design through tests. And yes, I’d be looking for someone who is knowledgeable about multiple technologies.

In the style of the agile manifesto, I’d say (on behalf of Gigantiq):

We value technique over technology.

Now that doesn’t preclude people with skills in Spring or any other technology. In fact, as I said, I would be looking for someone knowledgeable about multiple technologies, but that knowledge would be the icing on an already scrumptious cake.

Have you ever witnessed someone who prefers technology over technique? Is this even possible, never mind likely?

The answer to both questions, sadly, is “yes”. It usually manifests itself in bottom-up approaches to problem solving. i.e. start with the technology and work our way back to solve the business problem. James describes the drawbacks of this approach well in one of his blog entries.
It also manifests itself in poor implementations of new technologies as the solution only serves to tick another box in a CV skills matrix. Andy Trigg scathingly refers to this as “design by resume“.

If you are looking to hire then please think hard about the skills you want your candidates to demonstrate. Try to prioritise real skills over easily-acquired knowledge.

Value technique over technology.

*His answer was “Senior Spring Developer“. I’m sure he really meant “Senior Developer”.

Posted in hiring, values | Tagged , , , | Leave a comment

Revisited: AmbiguousTableNameException with DBUnit

I only had a little time yesterday to follow up on this issue (the priority is low as we know that making the user a non-DBA works) but I’ll document what I have encountered.

The programmatic solution I mentioned

connection.getConfig().setFeature(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES);

was dependent on me using DBUnit 2.2.2. I was using DBUnit 2.2 and had to upgrade.
On upgrading to DBUnit 2.2.2, I discovered that a new dependency had been introduced on slf4j. I then discovered that the dependency was on version 1.4.3 (not version 1.5, which I had installed). Eventually, I had all of the correct libraries but, sadly, the AmbiguousTableNameException was still being thrown.

Whilst DBUnit will now ignore all tables that begin with BIN$, my user has access to all tables in the system and some of those may be repeated for different users (the one I am currently failing on is DR$CLASS).

I will leave this investigation now as I’m happy for my test user not be a DBA.

Posted in dbunit, testing | 1 Comment

AmbiguousTableNameException with DBUnit

We had a problem this week whilst using DBUnit to set up some test data. A quick google didn’t really reveal much so I’ve included a (snipped) stacktrace to help anyone who also encounters this problem:


Caused by: org.dbunit.database.AmbiguousTableNameException:
BIN$S/1W2ofvNM7gQAB/AQEkDA==$0
at org.dbunit.database.DatabaseDataSet.initialize(DatabaseDataSet.java:140)
at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:186)
at org.dbunit.operation.AbstractOperation.getOperationMetaData(AbstractOperation.java:59)
at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:130)
at ...

Our quick fix (based on a hunch) was to ensure that the database user did not have DBA privileges. We’re using Oracle 10g XE and this privilege change was easy to make using Oracle APEX. As soon as we’d changed the user privileges, the exception went away.

Now that the weekend is here I have a little more time to investigate the cause of the problem and the (potentially) correct fix.

It looks as though this problem is caused by the Oracle’s use of a recycle bin to hold deleted objects. The objects in this recycle bin are still accessible as schema MetaData if you issue a jdbcConnection.getMetaData().getTables(..).
As DBUnit uses the schema MetaData to build up a map of tables in the schema, the duplicates in the recycle bin will result in the AmbiguousTableNameException.

Fortunately, DBUnit offers a means to ignore these recycled tables. I haven’t tried it yet (I’ll give it a go on Monday) but it looks as though you can set a property DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES on the connection and all should be fixed.

I’ll update the post on Monday to let you know if it worked.

Posted in dbunit, testing | Leave a comment

Read my mind not my code

I was pairing with James Pott the other day (welcome to Gigantiq, James) when we had an interesting mini-squabble.

We were writing a test to state that we expected a class at a layer boundary to catch a SQLException and wrap it in a LayerException.
I was at the keyboard and started typing something like this

SQLMapClient sqlMapclient = EasyMock.creatNiceMock(SQLMapClient.class);
EasyMock.expect(sqlMapClient.blah()).andThrow(new SQLException("bad things happened"));

At this point James stopped me and the conversation went something like this:

James: “we should be using a stub. We are not stating that we expect the SQLMapClient to be called; we are only stating that we expect the exception to be wrapped”.
Mike: “I’m not stating any expectations on the SQLMapClient being called” (at this point I may have crossed my arms).
James: “but you’re writing a Mock”
Mike: “no, I’m writing a stub” (my eyebrows had now become knitted)
James: “look at what you just typed”
Mike: “I used EasyMock to create a stub”
James: “look at what you just typed”
Mike: “EasyMock.expect… oh yeah. That should be EasyStub.when(..) shouldn’t it?”

I’ve spent so long enjoying that I could use EasyMock to knock up a quick and easy Stub that I stopped paying attention to how it reads. If I am using a Stub then it should be clear that I am using a Stub.

Posted in coding, mocks, stubs | Leave a comment

That explains the eclipse fans…

From “Explaining Cognitive Lock-In: The Role of Skill-Based Habits of Use in Consumer Choice” via “Product loyalty: consumers mistake familiarity with superiority”.

“We introduce and test a theory of how the choices consumers make are influenced by skill-based habits of use—goal-activated automated behaviors that develop through the repeated consumption or use of a particular product. Such habits can explain how consumers become locked in to an incumbent product. The proposed theory characterizes how the amount of experience with the incumbent product, the occurrence of usage errors while learning to use that product, and the goal that is activated at the time a choice is made interrelate to influence consumer preference. The results of three experiments support the theory’s predictions.”

If you persist with a product, making a few mistakes along the way, you will eventually get used to the interface and will operate it without thinking. This familiarity (the cognitive lock-in) confuses the user into believing the interface is superior to rival offerings.

Posted in usability, user-interface | 4 Comments