Tuesday 6 October 2009

Brief is not simple

I am always keen to reduce the world into simple metaphors and proverbs. Big fan of "the emperor has no clothes" for example (and not only because H. C. Andersen was danish!), as it can be applied to so many things. Particularly, while we battle for the hearts and minds of the IT industry, advocating simplicity and denouncing ceremony, it seems to come in handy time and again.

Anyway, I was reading about Guava (thanks for the link Simon!), and stumbled upon one that was missing from my library: "brevity is the soul of wit". In the context of source code, you can imagine a snooty Perl hacker uttering this phrase after writing a particularly pleasing regular expression that no-one will ever be able to decode. However, I cannot think of anything less appealing in source code that brevity or wit. As a way of communicating, code is really best expressed simply, not briefly or cleverly.

Of course, outside the world of code I am a huge fan of folks who can be concise, thus.

Tuesday 14 July 2009

Watch your dependencies

Dependencies are a headache. They cause all sorts of problems. So you should keep aware of them.

Tools are a-plenty, for many languages, but here is a good starter for your favourite open platform: Byecycle

Other tools do more, but are also more complicated and hard to interpret. If you want a gentle introduction, start with this little visual tool.

It can help you find dependency cycles



It can help you spot classes that do too much



It simply gives you a 30.000ft view of how your code looks, something which is difficult to get from text files on even a medium sized code base.

Monday 11 May 2009

I like Apache HTTP Client over java.net.HttpURLConnection

My last project involved CAS and a lot of integration points, so we ended up with lots of HTTP traffic as part of our integration tests.

We started having problems with our build, spurious exceptions would break it, but we couldn't reproduce the problem. It was not until we did some rudimentary load testing that the problem surfaced: Persistent HTTP connections.

Problem was, we had written our tests using java.net.HttpURLConnection like this:

try {
HttpURLConnection connection = (HttpURLConnection) new URL("http://localhost:8080").openConnection();
connection.connect();
assertEquals(HttpURLConnection.HTTP_OK, connection.getResponseCode());
} catch (...){
...
}
finally {
connection.disconnect();
connection.close();
}


Turns out, because we didn't care about the response body and thus never bothered reading it, and that would tie up TCP connections. The more tests we ran, the more likely it became that we would see an exception like this:

Exception in thread "main" java.net.BindException: Address already in use: connect

So while we thought we were being diligent by writing a finally block to disconnect and close the connection, it turns out that is completely superfluous. What we would have to write was this:

try {
HttpURLConnection connection = (HttpURLConnection) new URL("http://localhost:8080").openConnection();
connection.connect();
assertEquals(HttpURLConnection.HTTP_OK, connection.getResponseCode());
} catch (...){
...
}
finally {
while (connection.getInputStream().read() != -1) ;

connection.disconnect();
connection.close();
}


(Actually, that just works for happy HTTP responses, as this library will throw an exception on 4xx and 5xx's!? But lets not digress...)

Now that's a lot of code for something so simple - look at Apache HTTP Client for the same task:

HttpClient httpClient = new HttpClient();
GetMethod method = new GetMethod("http://localhost:8080");
assertEquals(HttpStatus.SC_OK, httpClient.executeMethod(method));


Notice, no cleanup code! And even better, comparing peak use of TCP connections as a function of number of connections opened (measured with netstat -a on my Windows box):



And look at the number of exceptions we get on a sample run - HTTP Client cleans up the input buffer automatically up and gives zero exceptions:



So while the API library can be made to work, I don't think I will be using it in future. On top being verbose, the way it handles "unhappy" response codes and the fact that it will insert a Content-Type behind your back makes it a poor choice.

Tuesday 5 May 2009

Waldo: Excellent!

Being currently beached and briefly free of family life, I had some time to catch up on my reading. This one really filled a gap in my knowledge of distributed computing and its history.

I was in a conversation once that only now makes proper sense. The phrase "Waldo taught is that" was used in a discussion about REST, which puzzled me - I hadn't heard of Waldo except for the fellow in the striped sweater. Later I was reading some notes from QCon via Steve Vinoski's blog, and again the mysterious Wally was mentioned. And finally a quick googling turns up a reference from Uncle Bob and his friends on their list of reading recommendations. Now I can't ignore Wally any longer.

Waldo et al. described the impedance mismatch of language abstractions and distributed computing in this 1994 thesis. And I am regretting it took 15 years before I read it, as it makes some very straight forward arguments - things I wish I had been more aware of in past. In fact, thinking back, in 2002 I took a course which featured CORBA, and I was very impressed with it at the time.

Qouting from the abstract: "We argue that objects that interact in a distributed system need to be dealt with in ways that are intrinsically different from objects that interact in a single address space. These differences are required because distributed systems require that the programmer be aware of latency, have a different model of memory access, and take into account issues of concurrency and partial failure".

So if you are doing any web/ SOA/ remoting at all, you really should go find Wally and get some extra context.

Thursday 19 February 2009

Manual Deployment Antipattern

It always felt wrong and now I found that it is actually a named antipattern! Yay! Now I can take that and use it to knock people on the head. Intellectual bullying - I'm lovin' it!

Alright, the article is about deployment automation, and this one in particular brings back memories. Hours and hours spent, manually deploying and redeploying a system, trying to ensure all dependencies were met.

Oh and of course, the reason I am loving this is the Antipatterns book, which I thought was brilliant. The whole concept of common pitfalls is just great - read it and you already know things you should be avoiding, you don't have to learn the hard way.

Monday 16 February 2009

Digital signatures in Java

We needed this for work, so while learning I wrote this very small program.

package digisign;

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

/*
 * http://java.sun.com/docs/books/tutorial/security/apisign/index.html
 */
public class Main {
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, InvalidKeySpecException {
// create some keys
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

// sign some data
byte[] data = "Hello, world!\n".getBytes();
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
signature.update(data);
byte[] sign = signature.sign();

// serialize public key and hand it over
byte[] pubKey = publicKey.getEncoded();
// store to disk, read in etc...
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(pubKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(encodedKeySpec);

// verify signature
signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(publicKey);
signature.update(data);
boolean b = signature.verify(sign);

System.out.println("signature " + (b ? "ok." : "invalid!"));
    }
}

Monday 5 January 2009

Software Sloth

I know I should be babysitting, but I saw Ian's nuanced post about technical debt and thought he left one out, and it is a cardinal one.

The fundamental problem is you either do not care enough and/ or you are too proud to change your was. The blogosphere is full of good advice, there are loads of great textbooks available, and peer learning is catching on - so help is available. So why do some still not "get it" and start producing good software?

Technical debt can be excused if it is backed up my conscious, well thought through decisions. There can be justification for skimping on quality. However, I contend that most technical debt is accrued through sloth. You either do not know what quality is, because you do not care enough to go and find out. You do not know the price of short sightedness. You cannot be bothered to read good books, or participate in collaborative peer efforts to better yourself. Or you are sinister, arrogant and not interested in improving your ways, not receptive to better ideas - even when you see mounting technical debt all around you.

I am a firm believer in evolution, and if we frame the problem thus, it is clear what the real problem is: because there isn't enough talent to go around, to fill enough posts and attain critical mass, sloth is allowed to thrive. Evolutionary pressures only work when resources are scarce, and sloth is apparently a smaller problem than getting bums on seats and poor code out the door.

Or maybe I am mistaken, and quantity is the real measure of success?