Josh Kerievsky called me to task for not following up on his third version of his story of providing a quick fix before a test-driven fix. As I said, I don’t want to be critical of Josh. I will, however, cast a critical eye on the code he has shared.
For those just tuning in, the previous installment talked about differences between the culture we espouse and the culture we practice. This installment will return to that.
Should your tests mock outside services or not? I keep seeing discussions on this topic. On the one hand, it lets your tests be in control of the testing context. Otherwise it may be very difficult to create a reliable automated test.
- The external service might return different results at different times.
- The external service might be slow to respond.
- Using the external service might require running the test in a particular environment.
- It may be impossible to generate certain error conditions with the real service.
- There may be side-effects of using the real service.
On the other hand, our mock of the external service might differ from it in important ways.
- Our mock service might have a slightly different interface than the real one.
- Our mock service might accept slightly different parameters than the real one.
- Our mock service might return slightly different results than the real one.
- The real service might change behavior, and we won’t notice until we deploy to production.
This leaves us in a quandary. What to do? Read More
I saw that Alistair Cockburn had written a post about Seb Rose’s post on the Diamond Kata. I only read the beginning of both of those because I recognized the problem that Seb described with the “Gorilla” approach that, upon reaching the ‘C’ case.
“The code is now screaming for us to refactor it, but to keep all the tests passing most people try to solve the entire problem at once. That’s hard, because we’ll need to cope with multiple lines, varying indentation, and repeated characters with a varying number of spaces between them.”
I’ve run into such situations before, and it’s always be a clue for me to back up and work in smaller steps. Seb describes that the ‘B’ case, “easy enough to get this to pass by hardcoding the result.” Alistair describes the strategy as “shuffle around a bit” for the ‘B’ case. I’m not sure what “shuffling around a bit” means and I don’t think it would be particularly easy to get both ‘A’ and ‘B’ cases working with constants and not heading down a silly “
if (letter == 'A') "¦ elseif (letter == 'B') "¦” implementation. I was curious how I would approach it, and decided to try. (Ron Jeffries also wrote a post on the topic.) I didn’t read any of these three solutions before implementing my own, just so I could see what I would do. Read More
When we write code, we’re often thinking about the short term. We need this code to function correctly so we can deliver within our immediate deadlines. I’ve found it important to also think of the long term. Sooner or later, we might encounter our own code, again.
I spent a chunk of my career where I often worked solo on projects that might get enhanced every year or two. This taught me a lot about the importance of code readability and what sort of things helped me quickly understand and avoid overlooking important considerations. I’ve also worked on a lot of legacy code bases, so I’m well aware of the pain and problems created by code that’s not readable, or is not organized in a helpful manner. Read More
In my previous post, Avoiding Iteration Zero, I suggested starting with “the one obvious thing that needs to be done? (Hint: it’s not ‘login.’)” As Jon Kern has recently mentioned, this same topic has come up elsewhere. I was also in that list discussion.
Jon is, of course, right in a narrow sense. You can start with login, if you want. You can also start with an Iteration Zero. (Or, an Iteration Minus One, as I’ve seen one organization do when their list of pre-planning outgrew one iteration.) I’ve observed that you can generally get better software, faster if you start somewhere else.
There are some very good reasons for this. Read More
Michael Feathers has just written a post on The Carrying-Cost of Code: Taking Lean Seriously. He says,
No, to me, code is inventory. It is stuff lying around and it has substantial cost of ownership. It might do us good to consider what we can do to minimize it.
I’m not sure I can see the analogy of code that’s in production to inventory. Code that hasn’t shipped, yes.
But all code is a liability, I think. When code is in production, then it’s offset by the asset that is the functionality. Whether or not the net is positive is another question.
There’s no doubt to me that code, whether in production or not, has carrying costs that are larger than generally realized. Perhaps it’s a depreciating capital expense?
Carrying costs are larger than we think. There’s competitive advantage for companies that recognize this.
It’s something that takes up space. It takes maintenance. It takes attention. It does have a substantial cost of ownership–larger than we think.
The analogies may be failing me, but I think Michael’s sentiment is correct.
Jeff Langr requested a Blog Pair for a tic-tac-toe program that he says “screams out for refactoring.” I looked at the code, and didn’t see an easy way to refactor it given the fragment posted. I did, however see a different solution. Read More
I’ve never really liked stored procedures. I always put it down to the fact that I’m a programmer, not a database person. I like keeping the functionality in the code. The database is just a place where objects go when they sleep.
My current client uses stored procedures for all database reads and writes. It probably made sense when the code was ASP, but Java JDBC code has all the expressibility you could want.
Today, I learned a new reason to not like stored procedures. Read More
Recently, I wrote about using the JfcUnit and Abbot frameworks to test-drive the creation of a Java Swing GUI. Since then, a post by Liz Keogh on the ExtremeProgramming yahoogroup led me to another option. It a wrapper around Swing written in conjunction with JBehave, but as Liz points out, it’s not dependent on the framework and can happily be used with JUnit, also. I like the fact that it’s really lightweight and fast. Read More
It’s been awhile since I’ve written any Java Swing code, and doing so now is making me feel a little stupid. Test Driving the development of Swing hasn’t improved much since the last time I did this.
Back in 2003, Jeff Waltzer and I decided to experiment with TDDing a Swing application to see if GUIs could be test-driven. It wasn’t always easy, but we convinced ourselves that they could. We started out rolling our own Swing test framework, but soon found ourselves immersed in AWT threading issues and Swing peculiarities. So, since we seemed to be headed down the road of reimplementing JfcUnit, we decided to switch and use the real thing. Read More