Monday, October 25, 2010

TDD: What's the Point?

What's the point of TDD?  This might sound outrageous, but IMHO, the point of TDD is not to exhaustively test your code as your developing it.  It's not to test every corner case, every possible input/output scenario imaginable.  It's not even -- gulp -- to achieve 100% code coverage. 

What?!  Blasphemy! 

Yeah, yeah.  100% coverage is a worthy goal, and if you're doing TDD right, you'll get pretty close anyway.  But still, 100% coverage isn't the point.

The point of TDD is to force you to design and write your code from an outside-in perspective, rather than an inside-out. It therefore also ensures that it is testable, well modularized, free of inappropriate foreign entanglements, and is most likely to work the way you need it to.  The focus is on the use of the class, not the implementation of the class. 

When you're not doing TDD, you're thinking more (sometimes exclusively) about what the class needs, and how it will do what it will do.  When you do TDD, you think more about how the class is used, what it's user's need, and what the rules are.

You write better code that way.  So TDD is a way of getting yourself to write better code.

So TDD is an approach to development -- not an additional task added to development.  It isn't overhead.  That brings me to the next topic.

Wednesday, October 13, 2010

Sabotage Your Code with Time Bombs

Sometimes you need some code for a short period of time, after which
it needs to be removed.  I've been having to do that a lot in the past
few weeks.  If I'm an average developer, then the average developer
has, at one time or another, done this by putting in comments like:

// XXX HACK FIXME TODO remove this!!!

The problem with this is you write it and then forget about it.  It
gets lost in the bazillions of other auto-generated TODO comments.
Granted, an above average developer doesn't tolerate all those
auto-generated TODO comments.  But then, by definition, most of the
developers in the world are average.  Like me.

The point is, it gets forgotten, and many times you never go back to
make the fix.  Well in a case I ran into this week, I had to be
absolutely certain that this time, it couldn't slip through the
cracks.

The solution?  TimeBomb.

It looks like this:

TimeBomb.explodeAt(11, 1, 2010, "Remove the following line or else...");

The explodeAt method checks the current system date, and if it's past
the date you've given it, will throw a java.lang.RuntimeException with
the message you provide in the last argument.

It's easy to ignore a TODO comment. Not so easy to ignore a broken app.

Oh, and I'm not showing the implementation, because if you can't
implement that, then you aren't (or shouldn't be) writing Java code to
begin with.

Wednesday, September 22, 2010

Murphy's Law for Business Application Data

If a system lacks data integrity constraints, the data will lack integrity.  If it permits illogical, incorrect, unreasonable, or even theoretically impossible states to exist, then illogical, incorrect, unreasonable and theoretically impossible states will exist in the data.

Corollary: The more someone insists that a data condition will never happen, the more assured you can be that it already has.


Monday, July 26, 2010

Estimates, Targets, Quotes: Semantics!

I just had a brief conversation with a project manager on the way back from the coffee hole.  

Part of the problem with waterfall projects is that we have to "estimate" the delivery date and cost at the beginning of the project.  So we take mostly wild guesses and give estimates that we only learn later are unreasonable -- or at least pretty inaccurate.  [Dilbert's project uncertainty principle hits the mark here.] But these estimates set the customer's expectation.  They then get (understandably) bent out of shape when things go down the way they usually do in the real world: late and over budget. 

We usually call our wild guesses "estimates," which most non-technical folks expect to be something like the estimate we get from our car mechanic.  Oddly, the estimate we get from our mechanic is actually more like a quote than an estimate.  Most of the time, the "estimate" is exactly what we pay.

And that's pretty easy for a mechanic to do.  Car parts have been standardized, and the mechanic has done the same thing hundreds of times.  If every car had a custom-designed engine, mechanics would suffer the same difficulty we do.

But to the point, people get upset because they expect our estimates to be equivalent to car mechanic estimates.  So I'm wondering whether -- if you are forced to work in a waterfall world -- would it help to refuse to use the word estimate?  

How about "target" instead?  When you're tumbling in a waterfall, that's more like what you've got -- a target.  You hit it or not depending on the flow and the wind.

Thursday, July 22, 2010

Rubout

Our three-year-old found a large pencil eraser last night.  She started rubbing it furiously on my head.  It started to make me wonder.  Was she trying to erase me?

Thursday, June 24, 2010

Wily Code

Ok, so it all started when I encountered this curiously laborious little line of code in a client's app:
String s = String.valueOf(" ");
As I said, it's quite a laborious way to initialize a string to a space. Never mind that the code in question didn't actually need that space for anything. I thought it was quaint, and wondered what other creative idioms we might employ to initialize a string to a single space character.

So Eric Galluzzo and I came up with some "brilliant ideas." Most of the samples will actually work if you compile and run them.

New
String space = new String(MessageFormat.format(
 new String(new byte[]{123,48,125}), new String(new byte[]{32})));

Symmetrical
/*/
/*/; String space = "" + " " + ""  /* | *\ "" + " " + "" = space String ;/*/;
/*/
/*/

Bees!
String space = "b\bb\bb\bb\bb\bb\bb\bb\bb\bb\bb\bb\b ";
  // only works if you write this to something that will actually execute the backspace.

Binary-Encoded Space
String charCode = "100000";
        int chr = Integer.parseInt(charCode.substring(5)) 
         + (Integer.parseInt(charCode.substring(4, 5)) << 1)
         + (Integer.parseInt(charCode.substring(3, 4)) << 2)
         + (Integer.parseInt(charCode.substring(2, 3)) << 3)
         + (Integer.parseInt(charCode.substring(1, 2)) << 4)
         + (Integer.parseInt(charCode.substring(0, 1)) << 5);
        String space = String.valueOf((char)chr);
Bit Twiddler
String space = String.valueOf((char) (32&1 + 32&2 + 32&4 + 32&8 + 32&16 + 32&32); 

ASCII Art
String space = (
                  "#####                               " +                            
                  "#     # #####    ##    ####  ###### " +
                  "#       #    #  #  #  #    # #      " +     
                  " #####  #    # #    # #      #####  " +
                  "      # #####  ###### #      #      " +
                  "#     # #      #    # #    # #      " +
                  " #####  #      #    #  ####  ######. "  ).replaceAll("#", "").trim().replaceAll(".", " ");
Around-The-World
// get space from China
    HttpClient client = new HttpClient();
    GetMethod get = new GetMethod("http://www.china.cn");
    client.executeMethod(get);
    String response = get.getResponseBodyAsString();
    String space = response.charAt(response.indexOf(" ")) + "";
    
    // or if you're feeling more poetic, get your space from space at nasa.gov
Wait for space to come to you
DatagramSocket udpSock = new DatagramSocket(68);  // get data from DHCP requests on the network
 DatagramPacket packet = new DatagramPacket(new byte[5120], 5120);
 boolean found = false;
 while (!found) { 
   udpSock.receive(packet);
   byte[] data = packet.getData();
   Arrays.sort(data);
   int indx = Arrays.binarySearch(data, 32);
   if (indx >= 0) {
  String space = String.valueOf((char) data[indx]);
  found = true;
          }
        }

 // disclaimer: your network security group might not like you sniffing the wire, so although
        // this code works, I recommend you don't ever use it, even though it's an irresistible way
        // to initialize a string ;-)

Java Intermediate Language (IL)
0  ldc  [16]
    2  astore_1 [space]

Perl programmer
String exp = "/( {1})/";
Pattern.compile(exp)... ah forget it, I can do this in Perl without even typing anything !!

Vendor-Specific
/*
 * Thanks to Eric Galluzzo for reminding us of the importance of vendor-specific implementations!
 * I wouldn't doubt that someone, somewhere is doing this...
 */ 

import com.vendor.string.String;
import com.vendor.string.StringInitializer;
import com.vendor.string.StringUsingApplication;
 

public class MyApplication extends StringUsingApplication {

    private String myString;

    @Override
    protected void initializeStrings() {
        myString = StringInitializer.getInstance().initializeString( " " );
    }
}

String-Definition Domain Specific Language
# file space.stringdef
 define string {
    immutable
    encoding UTF-8
    locale en-us
    initialize with \s
 }
// file SomeClass.java
String space = StringDSLEngine.loadString("space.stringdef");
    
// implementation of StringDSLEngine is left to the reader as an exercise.


Enterprise Architecture

It has been recommended, in keeping with corporate architectural strategies and best practices, that the new string initialization service be designed to be as simple as possible, while leveraging key synergies across business unit infrastructure.  We have achieved this goal, and, as required by the SOA governance board, provide for all critical SLAs.

    All applications going forward will be required to use the string initialization service, as an enterprise best practice, to ensure optimal flexibility, uniformity and reliability.

    Initial development and deployment is projected to see an initial $2 million investment, it is also projected to produce $10 Million ROI per annum.

    Among key benefits of this architecture are the new character database that allows seamless support for new character encodings, a vital capability if new character sets are ever introduced.  This uniquely positions the organization to respond quickly as Unicode is retired in favor of the Intergalactic Character Set (IGCS).

Wednesday, June 23, 2010

I Love This Code

Just saw the following at a client site...

if (name != null){
  person.setName(name);
}else if (name == null){
  person.setName(null);
}

I love it.  It could only be improved by being even more explicit.

if (name.equalsIgnoreCase("Allen")) {
  person.setName("Allen");
} else if (name.equalsIgnoreCase("Bob") {
  person.setName("Bob");
} else.
   /* omitting lines in this post */
} else if (name.equalsIgnoreCase("Zuzu") {  // hand cramp at line  1087667556223
  person.setName("Zuzu:);

} else if (name == null) {
  person.setName(null);
}


The only drawback I can see to this approach is that it is open to modification under new first names, otherwise, it is brilliantly self-documenting!  ;-)