Monday, November 26, 2007

My New Favourite Analogy: Design Like Water


I am a big fan of analogies and metaphors. When I think of a good (or funny) one, it is often the very definition of a good day.

Well, I discovered a doozie. Influenced by positive reviews from several corners, I have been reading a bit of the book Getting Things Done. Though only mentioned in passing at the beginning, GTD mentions a beautiful idea.


Mind Like Water

The book describes an image from Karate: Mind Like Water. The idea is that, in Karate, a state of perfect readiness is having a "mind like water". Water (e.g. a lake) responds perfectly to a disruption; that is:

Water reacts appropriately and then returns to a calm state.

If one throws a pebble into a pond, there's a ripple, then calm. If one lobs a boulder, then there's a huge splash, then calm. The reaction fits perfectly, and the disruption is dismissed.

Design Like Water

For me, that is a beautiful analogy for all kinds of things in computer science. This is all very subjective, and hard to quantify, but consider this:

Shouldn't a software system (e.g. web application) be designed like water? i.e. A small number of requests should be a pebble; perhaps a Superbowl TV ad spawns a massive boulder. But in all cases, it should react appropriately and then return to a calm state.

Some real world examples include the Big Databases and the massive e-commerce sites. One doesn't hear of eBay or Amazon "being rebooted". They're designed like water.

What about computer languages? Though hopelessly whimsical, it strikes me as beautiful: a language should barely react to small things. It is allowed to require a big splash for big things, but ultimately it should shrug off the disturbance and provide calmness.

Specifying examples for languages is much more difficult, because the idea is so abstract. Long time readers will predict, correctly, that I'll offer Python as an example. It's a big pond of OO, functional capability, and brevity that seems to react appropriately to both pebbles and boulders.

What do you think? Do you buy the metaphor? If so, which languages resonate for you in this philosophy? Does Java or C# ?

Wednesday, November 21, 2007

Ctrl-Space Invaders

Ctrl-Space Invaders: The scenario where a user of Idea will use Ctrl-Space to view a list of available methods on an object, and search by pressing keys for the first letter of the method, with a fervor that is reminiscent of an early 1980s arcade game. Coined by a teammate.

Hey, can you tell me how to send a holiday greeting with a List? I've been playing Ctrl-Space Invaders for 10 minutes and don't see it.


Tuesday, November 20, 2007

Ambient Info: Hear Your Build

In a previous post, someone commented that wacky comments brighten one's day.

True that. So, too, does Ant's sound task. On past projects, we used it to denote a failed or successful build. We used:

Not only was it fun (as James Brown sang throughout various cubes) but it was a great way to subconsciously know the state of the build. This is a small example of ambient information. (For a far cooler example, check out this device built by Kohsuke Kawaguchi).

Does your project use the Ant sound task? What sounds does your team use?

Here are some ideas.....

For Success
More fun (or painful) are ideas for Failure:
Add your own ideas in the comments!

Thursday, November 15, 2007

My Grails Aha Moment

Recently, I attended a training class led by Gruru Jeff Brown. (A Gruru is a Guru in Groovy & Grails, esp. if one is a committer)

I have some experience with Groovy and plenty experience with webapps, but none with Grails, nor with Ruby on Rails.

Here's a few neat tidbits that I discovered:

  • In terms of configuration, Grails has no XML and the only properties files are i18n messages. Almost everything else is Groovy. I am familiar with 'convention over configuration', but I didn't know the configuration was so fluid and dynamic.
  • Many of the language features of Groovy become perfectly obvious in the context of Grails. The big one, for me, was named parameters. As a Groovy language feature, I was neutral on it; in the DSL setting of a web application, the feature is vital. Similarly for closures and other constructions.
  • Also, the MOP (Meta-Object Protocol) becomes extremely important. However, it is so sublime that it is hard to "see". That is, the Groovy code looks so lucid that it is easy to gloss over the machinations behind the scenes.
The Moment

In Grails, we created a test application, and created a domain class.

Subsequently, we created an MVC controller for our app. At this point, we had a barebones app that could be launched and viewed.

Cool beans. However, the turning point for me was that Jeff said we could generate a controller: that is, Grails would generate the full code and then we could tweak it. Without a hint of irony or coyness, he warned us that it would generate a lot of source-code.

Being from the Java world, I braced myself for the output. Surely it would be verbose, impenetrable, and a rats nest in terms of formatting.

Surprise: the generated Groovy was gorgeous. Due to the brevity and style of the language, the generated code was 2 screens long -- without doc. And I was able to grok it and start tweaking it immediately.

At first, I just started changing some code. But then I realized that I was working with generated code. That was the profound moment. I understood.

Below, I've provided the generated code for a Gambler controller (think of a casino app) on my local machine. Give it a glance.... As a hint, the controller contains several methods which are actions (in MVC parlance) on either a target Gambler object or a list of Gambler objects.

Note that I'm not asking if you can understand it cold. I'm asking "do you think you could understand it, if warm?". Remember... this is generated.

Personally, I think it is stunning.

Final Score: Grails 1 My Old Biases 0. Check out Grails here.

class GamblerController {

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

// the delete, save and update actions only accept POST requests
def allowedMethods = [delete:'POST', save:'POST', update:'POST']

def list = {
if(!params.max) params.max = 10
[ gamblerList: Gambler.list( params ) ]
}

def show = {
[ gambler : Gambler.get( params.id ) ]
}

def delete = {
def gambler = Gambler.get( params.id )
if(gambler) {
gambler.delete()
flash.message = "Gambler ${params.id} deleted"
redirect(action:list)
}
else {
flash.message = "Gambler not found with id ${params.id}"
redirect(action:list)
}
}

def edit = {
def gambler = Gambler.get( params.id )

if(!gambler) {
flash.message = "Gambler not found with id ${params.id}"
redirect(action:list)
}
else {
return [ gambler : gambler ]
}
}

def update = {
def gambler = Gambler.get( params.id )
if(gambler) {
gambler.properties = params
if(!gambler.hasErrors() && gambler.save()) {
flash.message = "Gambler ${params.id} updated"
redirect(action:show,id:gambler.id)
}
else {
render(view:'edit',model:[gambler:gambler])
}
}
else {
flash.message = "Gambler not found with id ${params.id}"
redirect(action:edit,id:params.id)
}
}

def create = {
def gambler = new Gambler()
gambler.properties = params
return ['gambler':gambler]
}

def save = {
def gambler = new Gambler(params)
if(!gambler.hasErrors() && gambler.save()) {
flash.message = "Gambler ${gambler.id} created"
redirect(action:show,id:gambler.id)
}
else {
render(view:'create',model:[gambler:gambler])
}
}
}

Android, GWT, and Lingua Java

One can almost feel the Blogtomonous Collective try and wrap their minds around the Android SDK. Between the Mensa puzzle of the legal-speak and creative lure of the prize money, there is a lot to contemplate.

Looking back a week or so, there are some weird psychic fingerprints that led up to the announcement.

  • At the St Louis JUG, Andrew Prunicki presented a cool talk on the Javelin Stamp. This is a microcontroller that uses a Java-like syntax which compiles onto a JVM (of sorts). The VM doesn't have garbage collection. My theory is that it can't be licensed as true Java and so that the company chose the wonderfully clever name Javelin.
  • Eric "Photoshop till You Drop" Burke posted satire: Android shuns Java. The joke being, of course, that there is no way Android could shun Java: such a prediction would be as ill-fated as "Dewey defeats Truman". But Android does shun the JVM!
I think we are seeing an interesting dichotomy:
  • On one hand, JVM Tunneling implies that the JVM is The Thing. Scala, JRuby, Groovy, and others all run on the JVM. Java is being marginalized as merely one syntactic "view" of the virtual machine. It's not even the coolest view going these days.
  • On the other hand, Javelin Stamp, Android and the Google Web Toolkit make the case that the Java syntax is The Thing. It certainly looks like Google believes it is the Lingua franca of our time. Who cares what transformations take place, as long as we have the apple pie of "public class MyClass {}" !
Call it Lingua Java.

This just in: we are in interesting times.

Tuesday, November 13, 2007

Trivial Pursuit: Unit-Testing Getters and Setters

While I was in Vegas, Eric, Alex, and Brian posted some ideas on unit testing trivial code.

The question: should we unit-test everything? The hive-mind currently says: yes.

E.g. Relevance recently posted a job offer that mentions 100% code coverage. At a recent NFJS, Stuart Halloway made the point that code coverage is one of the few things where one has to be extreme: 80% doesn't work; it has to be 100%. (Relevance is adamant on this point.)

Fine, so the answer is yes. But how do we remove the tedium of writing that testing code?

  • Modern IDEs generate code for getters/setters. They should do the same thing for generating unit-tests for this code. I haven't seen this: perhaps they already do? I've looked in Idea 6 and didn't see anything obvious.
  • It seems possible to write an abstract base class for unit-tests that uses reflection to auto-test common getters/setters. Is there such a tool out there?
  • Interestingly, we are seeing the impact of this issue in language development. Groovy will auto-generate getters and setters for a class member if they aren't provided. Not only is there less code to read, but also there is less code to test.
Post a comment if you know of a neat method to facilitate this testing...

ps. Here is a post from last winter on my experiences with unit-testing: in particular, TDD. It was a true growth experience for me.

pps. Here is the obligatory acknowledgement that getters/setters should not be automatically provided without just cause!

Thursday, November 8, 2007

The Name Game: Improve on Map for Java 7

What's in a name? that which we call a map
By any other name would associate as sweet;
-- with apologies to The Bard

Kevin Bourrillion has posted a joint proposal for minor additions to some core APIs in Java 7.

This is pretty cool stuff:
  • The proposal itself smacks of being agile: it's small in length and in scope.
  • The changes address some corner cases in the vein of Java Puzzlers, and fill some inconsistencies in various APIs.
The most interesting proposal, IMHO, is #7. The idea is to have a new Map interface that is fleshed out with new methods (those from ConcurrentMap) and have all Map implementations use that new interface.

Of course, we need a name for this new interface. The doc has this line:

not likely to happen, due mostly to lack of tolerable name

Like many thoughtful developers, my reaction is:

  • No doubt, names are important, and vitally so for a core API.
  • Can I come up with a better name?
  • Can I come up with an absurd name? (Delightfully, they offer MapDaddy)
  • Why can't I stop thinking about this?
I could write an entire post about the importance of names and how much fun/challenging it can be to find just the right name.

What would you name a new Map interface? Here are some of mine
  • Dictionary. Has a classic appeal to it, but is already used (and deprecated) in the JDK.
  • Lookup. Another classic but somehow it doesn't seem strong enough. It seems like we should have a derivative of 'Map'.
  • Map7. The doc cites this as a bad name but it makes my shortlist, for some reason.
  • ReplaceMap. Probably too cute, the idea here is (a) the new methods involve replacement and (b) we are replacing the Map interface. At this point, one starts to realize how hard this task is. I can understand the reluctance expressed in the doc.
and some more yet:
  • iMap. That will get Apple's attention.
  • NüMap. Java has great support for Unicode, so let's go Euro. Plus we could sell lots of Java 7 schwag to heavy metal fans and feed the proceeds back into the Open JDK.
  • Map#. We need to grab mindshare from from the .NET crowd before F# takes off.
  • MapQuest or GoogleMap. Now, we're on to something: Java could be the first language to embrace corporate sponsorship in its core libraries. Call Nike and CocaCola immediately! (though they will probably want to brand the String class)
Your turn. What do you think?

Tuesday, November 6, 2007

Las Vegas Lobbies for Java 6 on Leopard

CtJ Newswire
Las Vegas, Nevada

13949712720901ForOSX

With the recent news that Java 6 is absent from the Leopard edition of Mac OS X, CodeToJoy reporters went on location to Las Vegas. In the world-famous district known as The Strip, people protested in the streets, appealing directly to Apple CEO Steve Jobs.




Carrying signs that read "Java 6 for Leopard / Steve, hear our cry", the protesters staged a rally that spilled throughout The Strip and went on late into the night. Many people had traveled far and wide for the event, including such remote locales as Australia and Wyoming.




In the midst of the turmoil, Apple maintained its policy of secrecy. There were no reps at the protest, and text messages, intended for Steve Jobs, went unanswered, though possibly because his contact info was not at hand.



Organizers of the protest felt that the outing was ultimately a success. Only time will tell if Apple will respond to the lobby.



Friday, November 2, 2007

Searching Jars Redux

A previous post translated a Groovy file into Java using the closure proposal. The main goal was to see how the new Function Type fit into the Java syntax.

Unfortunately, as Neal pointed out, the resulting Java file wasn't very closure-esque. Here is the same idea, cleaned up.

The new file does this:

  • Accepts a search directory and a target string
  • Recursively traverses the search directory and, for each file found, applies a concept
  • The concept is, in essence, a closure. In this case, the concept is to (a) check to see if the file is a jar and, if so, (b) check the entry list of the jar for a target string
  • The key is that we now have an algorithm that calls a block of code. The block of code is bundled with any local state that it needs to process the input parameters.
Here is the code listing. It is very instructive to contrast (1) the original Groovy file (2) the first attempt at Java and (3) this program. Note that #2 in this list does something slightly different (i.e. it counts occurences, and does not traverse recursively).


import java.io.*;
import java.util.jar.*;
import java.util.Enumeration;
import java.util.*;

class FileExtension {
private String dirStr = null;

public FileExtension(String dirStr) {
this.dirStr = dirStr;
}

// @param block a closure
// @throws IOException (because the closure declares it)
// This method will recursively traverse a directory
// structure and call block for every file found.

public void eachFileRecurse(
{ File => void throws IOException } block
) throws IOException {
File file = new File(dirStr);

for( File thisFile : file.listFiles() ) {
if( thisFile.isFile() ) {
// file
block.invoke( thisFile );
} else {
// dir
FileExtension subFileExtension =
new FileExtension( thisFile.toString() );
subFileExtension.eachFileRecurse( block );
}
}
}
}

public class JarSearcher2 {
static final private String JAR = ".jar";
static private String target;

// closure block
// Iterates through a directory tree and applies the
// closure to each file
// @param file an input file
// @free JAR used as an extension
// @free a target string in a jar's list of entries
// @throws IOException

static private { File => void throws IOException } myClosure =
{ File file =>
String fileName = file.getName();

if( fileName.contains(JAR) ) {

JarFile jarFile = new JarFile(file);

// old-style Enumeration
// don't blame me or closures!
for( Enumeration e = jarFile.entries() ;
e.hasMoreElements() ; ) {
JarEntry entry = (JarEntry) e.nextElement();

if( entry.getName().contains(target) ) {
System.out.println("found " + target
+ " in: " + file.toString() );
}
}
}
};

// iterates through a directory tree and applies the
// closure to each file
// @param args[]
// @throws IOException
public static void main(String[] args) throws IOException {
String searchDirStr = args[0];
target = args[1];

(new FileExtension(searchDirStr)).eachFileRecurse( myClosure );
}
}

Thursday, November 1, 2007

Closure Puzzlers: Greetings


If you have read my previous post on the basics of the Java closures proposal, then you might enjoy the puzzler below. A double-reference to Neal Gafter: it uses his recent prototype and is in the vein of Java Puzzlers.

This is not designed to be an elegant example: I was experimenting with closure literals, function types, and free lexical bindings. 'Tis a simple introduction... A greeting, if you will.

What is the output from the following program?


public class Greetings {
static private Object freeVar = null;

static public void main(String[] args) {
{ String => String } greetings = null;

// @param greeting
// @free freeVar
// @returns a simple message String
greetings = { String greeting =>
greeting + ", I am " + freeVar };

freeVar = "a free variable!";
System.out.println( greetings.invoke("Hello") );

freeVar = new StringBuffer("a new ").append("value");
System.out.println( greetings.invoke("Bonjour") );

freeVar = greetings;
System.out.println( greetings.invoke("Hola") );

freeVar = { String self => self }.invoke("my self");
System.out.println( greetings.invoke("Shalom") );

freeVar = { => freeVar + " too" }.invoke();
System.out.println( greetings.invoke("Namaste") );
}
}


Don't cheat but here is the output. If you understand this output, then you understand the content of the original post.


$ newJava.bat Greetings

Hello, I am a free variable!
Bonjour, I am a new value
Hola, I am Greetings$1@10385c1
Shalom, I am my self
Namaste, I am my self too

I won't explain everything but here is a brief annotation:
  • The local variable, greetings, is declared with its function type, and initialized to null. This is a separate line in order to emphasize that it is a local variable with a new, strange type.
  • We assign a closure literal to greetings. Note that it uses a 'free lexical binding' called freeVar. One issue with the current prototype is that it does not yet bind local variables (hence the static member field).
  • We alter freeVar in various ways and let greetings construct a message based on its toString() method.
  • Note that the last greeting uses a truly literal closure that is invoked in situ.
Fun! If you liked this one, stay tuned for more.