Wednesday, November 12, 2008

Everybody Needs Cron

I was looking at one of my daily emails from javablogs.com when I saw one entitled "Nobody should need cron". This struck me as rather naive, so I went over to read Odd Thesis's entry: Nobody Should Need Cron, hoping to learn what I've been doing wrong all these years.

I posted a comment on the blog which hasn't shown up yet. I'll recreate it here.

Trying to recreate cron in Java/Ruby is asking for trouble. Any real-world application will have activities which are hard or impossible to implement in Java or Ruby. They will be OS-specific, or low-level, or be needed to monitor the very container you are trying to run them from. They often need to be extremely robust (more robust than Java apps can be) in the face of very unusual conditions on the box (huge load, almost zero memory available, etc). Cron and OS-specific tools are well-suited to these situations. Java and Ruby are not.

I'm a software engineer who has been working with Java since 1.0 beta, and I find it a great development language (I'm less experienced with Ruby but it is nice also). But they are simply inappropriate replacements for cron.


I understand the desire to stay in the productive, known world of Java or Ruby. And for periodic tasks "within" the application, some sort of cron-like facility is a nice feature. But robust software systems that are resilient and handle 'unexpected' (i.e. difficult to handle) situations without simply falling over require developers to step outside the virtual machine and deal with the OS and hardware (and databases and filesystems and other software systems) that the virtual machine depends upon. For those watchdog or maintenance activities that have to occur outside the virtual machine, cron (or it's OS-specific equivalent) are indespensible.

If you really think you can build a non-trivial system without cron, you've failed to identify or are ignoring requirements which you must satisfy to make your system robust.

Thursday, September 11, 2008

Interface Chaining

I was recently talking with my friend Mark Volkmann about an application framework he was developing. The framework, named WAX, is a very nice Java API for writing out XML. Despite it's small size, it's much nicer than any other XML writing API I've ever seen and you should go check it out.

As part of the API, Mark implementing method chaining. This allows for very compact code that is still quite easy to read. For example, you could produce this XML:

<?xml version="1.0" encoding="UTF-8"?>
<car year="2008">
<model>Prius</model>
</car>

with just this code::

WAX wax = new WAX(WAX.Version.V1_0);
wax.start("car").attr("year", 2008)
.start("model" ).text( "Prius").close();

Much of the compactness comes from the fact that each method called returns the WAX object, allowing the developer to chain method calls together.

As we were discussing the code, the topic of incorrect ordering of calls came up. For example, what happens if you try to call the attr method to create an attribute after already creating some text inside the element with the text method?

Because WAX is a streaming API, you can't 'go back' and add an attribute in the start element tag after having already 'moved on' to putting text in the body of the element. For example, what if I tried to create an attribute to the model of the car after putting text in it, like this:

WAX wax = new WAX(WAX.Version.V1_0);
wax.start("car").attr("year", 2008)
.start("model" ).text( "Prius").attr( "trim", "GT" ).close();

WAX detects this situation and throws an exception at runtime, which it should do. But I'm a fan of static type checking. I love having tools do as much checking for me as possible. So I suggested to Mark that he create a set of interfaces. Each interface would contain only the methods that make sense at the current point in the output stream. This would allow the compiler to catch invalid method invocations. Even better, modern IDEs like IDEA would flag the method invocation visually even before compilation.

For example, if we arrange for the text method to return an interface which does not have an attr method, then the compiler will catch it and the IDE will flag the error visually. For example, in IDEA, the error is flagged like this:



Now we get the compactness of runtime exceptions (which Mark really likes) and static checking (which I really like). I did some looking around and couldn't find a design pattern that really fits. A number of people suggested that this was an example of a domain-specific language (DSL). But to my thinking, something that deserves the moniker of 'language' should be more involved than simply constructing some interfaces so that static checking is applied.

But whatever you call it, I think it's a useful design pattern than can be applied in other situations to make for clean, compact, yet statically checked APIs.

Thursday, July 17, 2008

Create inbox items in OmniFocus from the dashboard

I am a very heavy user of OmniFocus. It has many ways to enter information. For example, you can use the "Quick Entry Window", which is great for creating an item with a project, context, and optional description.



But sometimes I am not in OmniFocus and don't have any text selected. This means there is nothing for OmniFocus to treat as a clipping. As a result it won't bring up the quick entry window.

So, I wrote my first Dashboard widget. It has a text area where you type the text for your item and a "Send It" button. When you click the button or hit enter in the text area, a new item is sent to your inbox.



I submittted it to Apple for inclusion in their download area for dashboard widgets download site. Until it shows up there, you can get it directly from here.

[Updated 2008-07-17 21:05]

Someone pointed out that I had forgotten that there is a separate keystroke to bring up the quick entry window without having any text selected. This eliminates much of the purpose of this widget unfortunately, unless you spend a lot of time in the dashboard anyway. At least it was a good learning exercise... :-)

Monday, May 05, 2008

Groovy Type Handling is Broken

Here's a very simple Java program snippet:

List<Integer> list = new ArrayList<Integer>();
Collection<Integer> col = list;
list.add( 2 );
list.add( 1 );
list.add( 0 );
System.out.println( list );
col.remove( 0 );

Run this and you'll get what you'd expect. Before using the col reference to remove the integer/Integer with value 0 (zero), you see:

[2, 1, 0]

Then, after calling remove on the collection, we see the integer/Integer with value zero is gone (that's the one we said to remove):

[2, 1]

Groovy says that it allows you to use types and will honor them at runtime. But it doesn't.

Take the same snippet of code and run it as a Groovy script. Remember that the Collection interface has a remove method, and that method expects you to pass it an object which it will remove from the collection. So we would expect to see the same result as in Java. But we don't. Instead, we get this:

[2, 1, 0]
[1, 0]

Groovy has removed the Integer with a value of 2! It did this because of Groovy's 'multi-methods'. Groovy looked at the real type of col, which is an ArrayList. It then found a remove method that takes an integer/Integer. That method removes the Nth item from the list. It used that method and removed the zero-th item (the one with a value of 2).

But remember, I invoked the remove. method through the Collection interface. The collection interface does not have a method taking an integer/Integer but it does have a remove method taking the object to be removed!

This is a truly awful result. It removes our ability to reason about how code will behave by looking at the types involved. In order to know how this will behave, I cannot make any use of the type information; in fact the type information is downright misleading. Even worse, as the type system evolves and new classes are introduced, new methods with entirely different signatures may get invoked.

This approach to handling types is essentially broken. The claim that Groovy honors types (even the weakened form of honoring it by doing casts at runtime) is flat out wrong.

Groovy needs to either start honoring type information, or get rid of it.

Thursday, April 24, 2008

Insidious Coupling

This will get to the topic of code coupling soon enough, but bear with me for a bit of background.

I like to use the 'fail fast' approach to my code. This means that invalid inputs cause a failure in the code as quickly as possible. Perhaps the simplest example of this in the JDK is the collections classes, whose iterators fail as soon as they detect that the underlying collection object has been modified. This allows them to avoid synchronization costs while also detecting unsafe usage.

In my own code, the most common situation where I find fast-fail code is in constructors. If an argument the constructor cannot be null (either because it will be used in the constructor, saved to a field, or both), I check that the object reference is not null. For example:

public class Foo {
// ...
public Foo( Bar b ) {
// Check that b is not null
// rest of constructor...
}
}

I started out performing this check with an if statement:

public class Foo {
// ...
public Foo( final Bar b ) {
if ( b == null ) {
throw new IllegalArgumentException( "Bar b cannot be null" );
}
// rest of constructor...
}
}

This gets us a pretty understandable stack trace:

Exception in thread "main" java.lang.IllegalArgumentException: Bar b cannot be null
at org.sandbox.Foo.(Foo.java:10)
at org.sandbox.SimpleDoesStuff.doIt(SimpleDoesStuff.java:11)
at org.sandbox.Baz.main(Baz.java:10)

But this Java code is pretty verbose, especially if you have multiple arguments to check. After that I tried creating a static method named assureNotNull which would perform the check:

public class Foo {
// ...
public Foo( final Bar b ) {
assureNotNull( b );
// rest of constructor...
}
//...
private static void assureNotNull( final Object o ) throws IllegalArgumentException {
if ( o == null ) {
throw new IllegalArgumentException( "Object cannot be null" );
}
}
}

This has the unfortunate consequence that it becomes harder to track down the nature of the problem.

Exception in thread "main" java.lang.IllegalArgumentException: Object cannot be null
at org.sandbox.Foo.assureNotNull(Foo.java:14)
at org.sandbox.Foo.(Foo.java:9)
at org.sandbox.SimpleDoesStuff.doIt(SimpleDoesStuff.java:11)
at org.sandbox.Baz.main(Baz.java:10)

The stack trace on the exception shows assureNotNull as the source of the exception, which while strictly true doesn't clearly show that the real problem was with someone passing a null Bar to the Foo constructor. This can be mitigated to some degree by taking an description as argument:

public class Foo {
// ...
public Foo( final Bar b ) {
assureNotNull( b, "Bar b cannot be null" );
// rest of constructor...
}
//...
private static void assureNotNull( final Object o, final String msg ) throws IllegalArgumentException {
if ( o == null ) {
throw new IllegalArgumentException( msg );
}
}
}

This provides a somewhat more helpful exception message but the method generating the exception is still 'off by one':

Exception in thread "main" java.lang.IllegalArgumentException: Bar b cannot be null
at org.sandbox.Foo.assureNotNull(Foo.java:14)
at org.sandbox.Foo.(Foo.java:9)
at org.sandbox.SimpleDoesStuff.doIt(SimpleDoesStuff.java:11)
at org.sandbox.Baz.main(Baz.java:10)

And even with this semi-fix to help find the cause of the problem, we're still left with recreating this method in every class. From here the logical next step is to centralize the method. We can do this with an Assertions class:

public class Assertions {
// ...
public static void assureNotNull( final Object o, final String msg ) throws IllegalArgumentException {
if ( o == null ) {
throw new IllegalArgumentException( msg );
}
}
// ...
}

Now, our Foo constructor becomes simpler:

import org.acme.Assertions;

public class Foo {
// ...
public Foo( final Bar b ) {
Assertions.assureNotNull( b, "Bar b cannot be null" );
// rest of constructor...
}
//...
}

And with Java 5's static imports, we can even simplify it further:

import static org.acme.Assertions.assureNotNull;

public class Foo {
// ...
public Foo( final Bar b ) {
assureNotNull( b, "Bar b cannot be null" );
// rest of constructor...
}
//...
}

But we still have the wrong method as the first listed in the stack trace:

Exception in thread "main" java.lang.IllegalArgumentException: Bar b cannot be null
at org.acme.Assertions.assureNotNull(Assertions.java:9)
at org.sandbox.Foo.(Foo.java:7)
at org.sandbox.SimpleDoesStuff.doIt(SimpleDoesStuff.java:11)
at org.sandbox.Baz.main(Baz.java:10)

Since all of us Java developers are big on frameworks, we might even take it to the 'next level'. Why not centralize the Assertions in some common framework? If the Assertions class were in a common framework, the thinking goes, then we'd all be able to use it everywhere. That consistency would really help us read unfamiliar code.

Ignoring the issue of getting any set of developers of size greater than one to agree on anything, especially a basic assertions framework used everywhere, we've just introduced insidious code coupling where it really doesn't belong. In our desire to achieve clarity, brevity, and avoid redundancy, we've coupled code together. If we have a common class in our framework, all the classes in the framework are now coupled to it and indirectly to each other. If we move the class to a generic framework, we externalize the coupling, making it even broader. This coupling introduces many hazards for versioning and incompatibility problems that come with the independent evolution of code.

So, what choice are we left with? Well, we could always depend upon the runtime itself to generate an exception for us. We can do this quite briefly, with less redundancy of code than the other approaches, and with zero coupling:

public class Foo {
// ...
public Foo(Bar b) {
b.getClass(); // Assure not null
}
}

This code is quite short, and generates a NullPointerException with the top element pointing to exactly the line of code where the problem occurred:

Exception in thread "main" java.lang.NullPointerException
at org.sandbox.Foo.(Foo.java:7)
at org.sandbox.SimpleDoesStuff.doIt(SimpleDoesStuff.java:11)
at org.sandbox.Baz.main(Baz.java:10)

This code also avoids nearly all redundancy, and I think after seeing it once it becomes quite clear. As a bonus, it's easy to create a macro in any modern IDE to help in generating the code.

Sometimes, the right solution to a problem is not abstracting code into a separate method/class/framework.

Friday, March 07, 2008

Something else Apple Gets Right

Eric Burke made a reference to the work Apple puts into making their applications simple but capable. He also gave Google as an example. That item produced quite a few comments and Eric followed up with more details. Again, the discussion wasn't just about Apple but the company was again an example of hard work making things simple and functional. I agree with his comments, and remembered another example of Apple's efforts toward elegant designs.

For as many years as I can remember, the Apple website has had simple URLs to get to various parts of the website. For example:

Yes, other sites do this now. But Apple was doing this many years ago, long before competitor's sites.

This seemingly simple idea makes it much easier to navigate their web site for the vast majority of people going to the site. It allows people to get more quickly to the area they want. Without this, the task becomes much more involved:
  1. Visit the home page

  2. Parse the layout

  3. Find the navigation links

  4. Find the right link - if it's not there guess where to drill down

  5. Get to where you wanted to go

Wednesday, February 13, 2008

An alternate syntax for Java closures

I'm no expert on the details of the closures proposals. I do think if we're going to put closures into the language, we need to make them complete, full-fledged closures. Generics are a mess precisely because the semantics and features were compromised for the goal of getting it into the language.

But one thing I do know about the BGGA closures proposal is that I don't like the syntax. Take the example in Weiqi Gao's recent Java Quiz:

public class Fib {
private static {int=>int} fib = { int n =>
n==0 ? 0 :
n==1 ? 1 :
fib.invoke(n-1) + fib.invoke(n-2)
};

public static void main(String[] args) {
System.out.println(fib.invoke(6));
}
}

To me, this is just hard to read. The whole "=>" thing seems like a weak attempt to create a new lexical character and is too visually similar to ==, >>, etc. I also don't like the 'invoke' syntax. I was discussing this with Weiqi the other day and came up with a syntax that I like better.

public class Fib {
private static {int # int} fib = { # int n #
n==0 ? 0 :
n==1 ? 1 :
#fib(n-1) + #fib(n-2)
};

public static void main(String[] args) {
System.out.println(#fib(6));
}
}

Note that you could also invoke fib like this:

System.out.println(#Fib.fib(6));

I wonder what other people think of this alternative?