Tuesday, July 31, 2007

IFoo or just Foo? Please stop naming interfaces IFoo.

I am not sure where the idea came from to name intefaces IFoo, but I think the practice is counter-intuitive and generally ugly. Java is not C++, nor C, and it most definitely is not Windows, so why do we have a good section of the Java community dead set on writing pre-historic looking code?

Aside from the aesthetic issues, which is important if you ask me -- code that looks funny most definitely smells funny, I believe naming an interface IFoo instead of Foo really misinterprets the fundamental idea of what an interface is.

An interface is an object - at least from the standpoint of the code that calls it. When you deal with it in code, there is no distinction between an interface and a full blown class. That, in my opinion is the beauty of Java. We can argue all day long about whether or not Java should have multiple-inheritance, the fact is that it does not. And in its place is a rather elegant solution - multiple interfaces.

My point is, when I instantiate FooImpl that implements Foo, for all intents and purposes, FooImpl is not a FooImpl, it is a Foo. If FooImpl happens to implement Bar, then it is also a Bar, but it most definitely is not an IFoo or an IBar.

To further belabor the point, calling your interface IFoo or IBar demotes the status of the interface, and the resulting "object" that is used by clients of the implementation of IFoo or IBar, thus subtly changing the way a programmer understands your code. It is as if the interface IFoo is second in nature to the implementation. But nothing could be further from the truth. Design by Contract means that you are coding to interfaces as first class citizens, not backwater denizens of the design. The implementation is what does NOT matter, and that's why you call it FooImpl, because you could have SuperDuperFooImpl and ReallyLameFooImpl too. The point is that any one of these is a Foo, and that's all your program should care about.

If you disagree with my opinion, look no further than Java Collections, do you implement an IMap or a Map? Josh Bloch had it right, so stop using IFoo already.

I am sure you'll still disagree with me, so flame on in the comments...

p.s. In the "nobody's perfect department", we even have examples in our own Terracotta code base.

Saturday, July 21, 2007

Email This (Link) for iPhone

Problem:


Send a link to a friend via iPhone

Solution:


Add an email bookmarklet to your links. I found this one at macosxhints.com:


javascript:location.href='mailto:?SUBJECT='+document.title+'&BODY='+escape(location.href)


Add this bookmark to your bookmarks bar in Safari, synchronize with iPhone, and you can send links to friends on your iPhone. I wonder if there is a way to access the SMS application?

Monday, July 16, 2007

Distributed Groovy in 5 minutes

Ok Groovy is cool, but can your Groovy do this?



This took me about 20 minutes to do with Terracotta.  If you're not new to Terracotta, this is pretty old hat.  Distributing a LinkedBlockingQueue is really easy (as seen above).  But then again, being able to use Groovy to distribute anything in Java is ... well pretty powerful.

What if you wanted to synchronize two scripts?  Just use a java.util.concurrent.CyclicBarrier:



I could build a distributed test harness in ... oh I don't know another 10 minutes.  But I'll leave that up to you :).

Here's how to get going with Clustered Groovy:

1) Download and unpack Groovy.
2) Set GROOVY_HOME (per their instructions)
3) Download and unpack Terracotta. (Hint: get Version 2.4.  If it's not already final, it will be soon)
4) set TC_HOME (this makes your life easier)
5) You need my Groovy Startup Script - I saved it as groovyConsoleTC.  Sorry, I use a Mac so it is not Windows friendly, but at 5 lines, hopefully you can figure it out:

DIRNAME=`dirname "$0"`

TC_INSTALL_DIR=${TC_HOME}
. "${TC_INSTALL_DIR}/bin/dso-env.sh" -q $DIRNAME/groovy-tc.xml
JAVA_OPTS=$TC_JAVA_OPTS
echo $JAVA_OPTS

. "${GROOVY_HOME}/bin/startGroovy"

startGroovy groovy.ui.Console "$@"


6) You need my RootMap class.  It's not that pretty, it could be improved, but it works:


import java.util.*;
import java.util.concurrent.*;

public class RootMap
{
public final Map root = new ConcurrentHashMap();
}


7) You need my Terracotta config (save it to a file called groovy-tc.xml)


<?xml version="1.0" encoding="UTF-8"?>
<!--

All content copyright (c) 2003-2007 Terracotta, Inc.,
except as may otherwise be noted in a separate copyright notice.
All rights reserved.

-->
<tc:tc-config xmlns:tc="http://www.terracotta.org/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-4.xsd">
<servers>
<server host="%i" name="sample"/>
</servers>
<system>
<configuration-model>development</configuration-model>
</system>

<application>
<dso>
<instrumented-classes>
<include>
<class-expression>Root*</class-expression>
<honor-transient>true</honor-transient>
</include>
</instrumented-classes>
<locks>
<autolock>
<method-expression>* *..*.*(..)</method-expression>
</autolock>
</locks>
<roots>
<root>
<field-name>RootMap.root</field-name>
</root>
</roots>
</dso>
</application>
</tc:tc-config>


If you saved all that to some directory, now:

8) Compile RootMap.java : > javac RootMap.java
9) Make sure your classpath has . in it: > export CLASSPATH=.
10) start up the TC Server in $TC_HOME/bin/start-tc-server.sh
11) start one ore more Groovy Consoles using groovyConsoleTC

Validate you can see a root by executing a Groovy script:


root = new RootMap()
root.root.put("message", "Hello World")


If you run the admin console, you can see your root:

> $TC_HOME/bin/admin.sh

Now try out more advanced stuff like LinkedBlockingQueue!

Update: I've added a tar.gz file with the relevant code: distributedGroovy.tgz