Thursday, February 18, 2010

Code Katas I'd Like to See More Of

If you haven't heard of code katas, then you should really check them out. Like their namesake in Karate, code katas are little pieces of code you write over and over to exercise your coding muscles. And as opposed to bench pressing to exercise your coding muscles, katas are designed to fine tune not just strengthen.

I'm not sure who coined the term or idea, but I tend to get most of my katas from Dave Thomas at http://codekata.pragprog.com/

I like the katas listed there, but my experience is that they are mostly just programming contest problems designed to exercise your problem solving skills. That's a good thing, by the way, but there are more than just problem solving skills to master on the road to becoming a software craftsman.

What I'd like to see is more katas like:

Given the follow class:

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;

import junit.framework.TestCase;


public class PolyKata extends TestCase {
 private PrintStream stream;
 enum shape {square, triangle, rectangle}
 
 private void drawPoly(shape the_shape) {
  switch (the_shape) {
   case square:
    stream.print(shape.square);
    break;
   case triangle:
    stream.print(shape.triangle);
    break;
   case rectangle:
    stream.print(shape.rectangle);
    break;
  }
 }
 
 public void test_drawPoly_square() throws Exception {
  PrintStreamFake stream_fake = new PrintStreamFake(shape.square);
  stream = stream_fake;
  drawPoly(shape.square);
 }
 
 public void test_drawPoly_triangle() throws Exception {
  PrintStreamFake stream_fake = new PrintStreamFake(shape.triangle);
  stream = stream_fake;
  drawPoly(shape.triangle);
 }
 
 public void test_drawPoly_rectangle() throws Exception {
  PrintStreamFake stream_fake = new PrintStreamFake(shape.rectangle);
  stream = stream_fake;
  drawPoly(shape.rectangle);
 }
 
 private static final class PrintStreamFake extends PrintStream {

  private shape the_shape;

  public PrintStreamFake(shape theShape) throws IOException {
   super(File.createTempFile("temp", "file"));
   this.the_shape = theShape;
  }
  
  @Override
  public void print(Object obj) {
   assertEquals(obj, the_shape);
  }
  
 }
}


Refactor using "replace conditional with polymorphism". Do this kata five days in a row, refactoring to a different design pattern each time. Then do it one more time only this time focus on taking the smallest steps possible and still keep the tests green. Also find ways to clean up the test code, as there's some duplication that can go as well.

To become a craftsman, you must refine your problem solving and coding skills, but you must also refine your code nose and refactoring skills. You must learn to quickly identify the stench of crap code and perfect your refactoring skills so you can quickly, cleanly, and efficiently replace crap code with clean code.

This is a perfect task for code katas. I only hope more of these come into play. I'll try to contribute my fair share, and if there are katas of this ilk out there in the tubes of the Internets already, please don't hesitate to point them out in the comments.

And I have to add, I had to look up how to do enums and switch statements in Java. That's how much I use them :)

Tuesday, February 9, 2010

Don't Swallow Exceptions - Ever!

Among lots and lots of good reason not to swallow exceptions, I just ran into a doozy. I'm rewriting a VB.Net application in Java. It has some really complex calculations. One of the calculations involves using a 2D array to setup some default values. The array is in a try catch block. With a catch(Exception e) and nothing else. No logging. Nothing.

Two days of trying to figure out why my calculations are slightly off what's expected. Thank you FitNesse, by the way. Anyway, come to realize that I'm swallowing an IndexOutOfBoundsException. See, VB.Net starts arrays at 1 while Java starts arrays at 0, so my array initialization was barfing and returning a bad value.

I did what most of us do now and then. I saw the empty catch block and thought, "I'll get back to that. I just want to get these calculations right. Then I'll fix those exceptions." Woops.

Handle exceptions as soon as you write the catch block. Handle it as best you can. At the very least print it to standard error, so when it happens you know it happened. Had I done at least that, I wouldn't be two more days behind.