I Know What You Did

It takes about two seconds to determine whether or not someone used TDD to derive a set of unit tests. While it’s possible for someone to write as high-quality unit tests using TAD (test-after development), it just doesn’t happen. Invariably I see many of the same problems, most significant of which is that the TAD tests don’t cover nearly enough of the cases.

Most of the time, developers doing TAD simply refuse to follow the single-responsibility principle (SRP) at the class or method level. (Despite bizarre claims by Jeff Atwood and Joel Spolsky, asking people to push in the direction of Uncle Bob’s five principles of class design is a reasonable and sensible thing to do.) They build large classes and large methods–not small, cohesive, potentially reusable units–and then complain about the difficulty of testing them.

My simple answer for now is, “How can you expect to write unit tests when you don’t have any units?”

Agile in a Flash

Make sure you check out the Agile In a Flash blog, where Tim Ottinger and I will be cranking out an agile flash-card deck.

Convention and Case

I’m learning Grails. I found a good tutorial written by Jason Rudolph. It does a great job of covering a broad range of the typical things you’d want to do in putting up a quick web site.

Unfortunately, it’s for an older version of Grails, but so far that hasn’t been a barrier; most of the changes I need to make are self-explanatory. I’m almost finished, and feel I have a good grasp on using Grails.

Still, I struggled for about two hours last night on a problem in going through the tutorial. Here’s a form I defined.

<g:form controller="user" method="post">
    ...
    <g:actionSubmit value="Log In"/>
    ...
</g:form>

And here’s some of the controller:

class UserController extends BaseController {
  def beforeInterceptor =
 [action:this.&auth, except: ['login', 'logout']]

  def index = { redirect(action:list,params:params) }

  def allowedMethods = [delete:'POST', save:'POST', update:'POST']

  def login = {
   // ... 
  }
  // ...
}

I think that’s all that’s relevant to show. Those of you who know Grails know how the form knows which controller method to call; I wasn’t paying enough attention and missed the simple cause of my problem, which was that a simple form submit from the login page kept generating a 404, URL not found. It showed me the request URI:

RequestURI=/racetrack/user/index

Yet that is a valid URI (index redirects, of course). In fact, if I copied the URL grails generated, and pasted it into the address bar, the proper page came up. I tried a few things, including explicitly specifying the action:

<g:form controller="user" method="post" action="login">

No dice, same problem:

HTTP ERROR: 404

NOT_FOUND

RequestURI=/racetrack/user/login

Frustrated, I tried a few other things. Still no dice. I looked at the HTML provided in the book and looked to ensure I typed it correctly (I almost always type my own sample code rather than paste it, I learn better that way). Looks pretty much the same. Web search, no exact match on my same problem; found a couple odd things that it might be, tried ’em, not the problem.

When in doubt, really make sure you have exactly the same thing. Whitespace and case. Case couldn’t possibly matter on button text, could it? Well, yes, especially when you follow this notion of programming by convention or programming by default or whatever you want to call it. An actionSubmit defines the controller method, either explicitly or implicitly. Explicitly, you can simply say:

<g:actionSubmit value="Log In" action="login"/>

In the absence of the action attribute, it uses the value attribute. Apparently, it lowercases the first letter for you, but then simply removes spaces, not lower-casing any subsequent letters. Thus it was looking for a controller action named “logIn,” apparently. The tutorial code has it typed as “Log in.” I typed it “Log In” (I thought it looked nicer). Harumph.

Dumb on my part, for not paying enough attention to how the form was supposed to figure out which controller method to call (I hadn’t figured this out yet, and thought this was another “by convention” element, perhaps from somewhere else). Dumb on Groovy’s part, for not showing me the URI with the improper casing.

Lesson for me: Pay more attention. Lesson for tools that play by convention: If you’re going to do something as clever as use button text to define an action, make sure you are picky about case everywhere, and make it clear from whence that action name came (i.e. better error messages). Lesson for tutorial writers: It’s hard work to write a great tutorial. A good one gets you through all the happy path circumstances. A great one helps you out with all the dumb mistakes you’ll inevitably make.

Atom