Thursday, September 30, 2004

Policy-Based Design

I recently had the pleasure of reading an article written by one of my Systematic colleagues, Jan Reher, entitled "Policy-Based Design in the Real World" published in the C++ Users Journal. The article shows an example from a real application of the use of policy-based design, as described in Alexandrescu's book Modern C++ Design.

Policy-based design allows functionality to be parametrized in a number of independent dimensions. The textbook solution is an elegant application of C++ templates and multiple inheritance. The point of Jan's article was to demonstrate that the textbook solution can actually be used in a real application.

I found the article very interesting for a number of reasons. One of Jan's concerns was the real-world utility of policy-based design. I see this as a broader issue: many of us are familiar with the situation where an elegant textbook solution evolves into an unmanageable mess when applied in practice, so it is always good to get real validation of such a solution. On a practical note, since I have worked mainly with Java for the last few years, it was interesting to try to recast Jan's solution in Java (pre J2SE 5.0's generics). What became rapidly apparent was that the solution would be significantly more clunky in Java. Actually, even with generics, the Java solution would be less concise than the C++ one due to the use of multiple inheritance in the C++ solution.

Sunday, September 19, 2004

JXTA at FWJUG

Attended the monthly meeting of the Fort Worth Java Users Group last thursday where we learnt about JXTA and P2P solutions from Daniel Brookshier who is part of the JXTA development team and has written a book on the subject. The talk was very good and for me there were a couple of things that I really took away from the meeting:

- JXTA is not a Java specific technology. It is a protocol for P2P communication, and there are already implementations in several languages.

- P2P is really a paradigm shift in distributed computing, compared to a traditional client-server architecture. This is really blowing my mind a bit, and I still don't think I have totally got my head round it.

One of the examples that Daniel referred to several times was 312inc.com's product lean on me that performs backup using a P2P approach. This was a good example of where a bit more thought up front yields a massive saving in initial investment since a traditional approach would involve investing in backup servers etc.

Sunday, September 12, 2004

The difference between Britain, Denmark and the US

Being a Brit who has spent the last five years living in Denmark and now lives in the US, I have a unique perspective on the differences between these countries. Of course when you get down into the details, there are a huge number of contrasts that can be drawn. However I think I have been able to distil the the fundamental difference into a simple concept: how the different countries deal with problems.

In the US, if a problem arises, the solution is to throw more people at it. In Denmark, if a problem arises, a new tax is created to solve it. In Britain if a problem arises, people go to the pub, grumble about it over a beer, then stagger home solutionless but happy.

Readers are most welcome to provide their own national approach to problem solving :-)

Sunday, September 05, 2004

Book Review: IT Architectures and Middleware

IT Architectures and Middleware Second Edition
Chris Britton & Peter Bye, Addison Wesley 2004.

I have been reading a lot of books about architecture recently, so when I spotted this one at my local Borders, I bought it without looking too closely at it. If I had paid more attention then I would have noticed that even its title hints that it isn't a standard book about n-tier architecture and/or UML modelling. First, the book is about IT architecture not software architecture, and second middleware is a major driver for the book.

In fact I have to say this is one of the most refreshing books I have read recently. It has the subtitle "Strategies for Building Large, Integrated Systems"; though this is undoubtedly true, I would be more inclined to call it "Everything you wanted to know about architecture but daren't ask"! Certainly for me it filled in some gaps in my knowledge and in general drew together a number of topics that aren't always treated in architecture books, and gave them a nice coherent thread.

The approach the book takes is that making decisions about middleware are critical to an IT architecture, and the choice of middleware really drives the architecture. Practical issues that arise when creating an architecture are described at a level of detail which highlights the critical issues without getting bogged down in technology solutions. The policy throughout the book is to be vendor neutral; that's not to say that particular technologies are not discussed such as J2EE and .Net, but there is no rabid claim of unconditional superiority for any specific technology. That said, there are a number of examples (more of these below) that reflect that the authors have extensive experience with Unisys.
Avoiding specific technologies also means that the reader doesn't have to wade through pages of listings! On the other hand, the authors' experience is very useful when highlighting potential gotchas throughout the text.

On the negative side, the book is very concise (337 pages including index). Though I welcome a change from the standard 600+ page treatise, there is a fine line between being concise and being dry. I found towards the end that it was harder and harder to take in all of the information in the text, and I suspect that I will have to reread it to pick up the things I missed first time round. I was therefore surprised that there are a number of examples described in the final chapter of all places. I would much rather have seen these examples (and many more examples for that matter) earlier on, driving and motivating the material. This would inevitably have increased the length of the book, but I think it would have made it much kinder to the reader. As it is, I think any reader of the book needs to have some background in architecture; there is too much for a total novice to take in.

All that said, I would thoroughly recommend this book for anyone creating IT architectures who wants a solid, vendor neutral overview of the different issues that need to be considered. I have just started reading Beyond Software Architecture by Luke Hohmann which in its own way also provides an alternative take on software architecture. More of that later.


Saturday, September 04, 2004

Instanceof Code Smell

I have noticed several times over the last few years that Java developers misunderstand when to use instanceof. In particular I have noticed an instance of java.lang.Object interrogated using instanceof through a sequence of if statements. Each time I have seen this I have explained why this is a bad idea and have tried to find a reference that summarizes this code smell, but to no avail, so I have chosen to write something myself.

First of all, there are legitimate uses of instanceof. A good example is overriding the equals method in a class you are designing yourself. However too often instanceof is used as a solution when the underlying problem is poor class structure. To illustrate this, I have created a toy example. Suppose we have two entity classes: Book and Car. The Book class is shown below.
package example1;


public class Book {
private String title;
private String author;
private String isbn;

public Book(String title, String author, String isbn) {
this.title = title;
this.author = author;
this.isbn = isbn;
}

public String getAuthor() {
return author;
}

public String getIsbn() {
return isbn;
}

public String getTitle() {
return title;
}
}
There is nothing special about this class. Similarly with the Car class:
package example1;


import java.awt.Color;


public class Car {
private String manufacturer;
private String model;
private Color colour;

public Car(String manufacturer, String model, Color colour) {
this.manufacturer = manufacturer;
this.model = model;
this.colour = colour;
}

public Color getColour() {
return colour;
}

public String getManufacturer() {
return manufacturer;
}

public String getModel() {
return model;
}
}
The important thing to notice with these two classes is that from a business point of view they are unrelated, so there is no natural class hierarchy for them. Their only common superclass is java.lang.Object.

Suppose now that we want to be able to generate an XML representation for a list that can contain either Book or Car instances. Using instanceof we could do this as follows:
package example1;


import java.util.Iterator;
import java.util.List;

public class XMLGenerator {
public String generateXML(List items){
StringBuffer result = new StringBuffer();
Iterator iterator = items.iterator();
while (iterator.hasNext()){
result.append("<item>");
Object obj = iterator.next();
if (obj instanceof Book){
result.append(generateXML((Book) obj));
} else if (obj instanceof Car){
result.append(generateXML((Car) obj));
} else {
throw new IllegalArgumentException("Unexpected object: " + obj);
}
result.append("</item>");
}
return result.toString();
}

private String generateXML(Car car) {
StringBuffer result = new StringBuffer();
result.append("<car>");
result.append("<manufacturer>");
result.append(car.getManufacturer());
result.append("</manufacturer>");
result.append("<model>");
result.append(car.getModel());
result.append("</model>");
result.append("<colour>");
result.append(car.getColour());
result.append("</colour>");
result.append("</car>");
return result.toString();
}

private String generateXML(Book book) {
StringBuffer result = new StringBuffer();
result.append("<book>");
result.append("<title>");
result.append(book.getTitle());
result.append("</title>");
result.append("<author>");
result.append(book.getAuthor());
result.append("</author>");
result.append("<isbn>");
result.append(book.getIsbn());
result.append("</isbn>");
result.append("</book>");
return result.toString();
}
}
The part of this class that I really object to is
    Object obj = iterator.next();

if (obj instanceof Book){
result.append(generateXML((Book) obj));
} else if (obj instanceof Car){
result.append(generateXML((Car) obj));
} else {
throw new IllegalArgumentException("Unexpected object: " + obj);
}
The point is that we know from our design that all of the objects in this list should be capable of having XML generated. However by using instances of java.lang.Object we are throwing away this information and then recovering it using instanceof. That is, we are using features from the language to help us overcome our poor design.As an aside, I can also point out that using method overloading in the way this class does, is another symptom of this code smell.

How can we resolve this? The issue is to in some way pass responsibility for generating the XML onto the objects themselves. A first step could be to define an IGenerateXML interface
package example2;


public interface IGenerateXML {
public String generateXML();
}
Book and Car will then implement this interface:
package example2;


public class Book implements IGenerateXML {
private String title;
private String author;
private String isbn;

public Book(String title, String author, String isbn) {
this.title = title;
this.author = author;
this.isbn = isbn;
}

public String getAuthor() {
return author;
}

public String getIsbn() {
return isbn;
}

public String getTitle() {
return title;
}

public String generateXML() {
StringBuffer result = new StringBuffer();
result.append("<book>");
result.append("<title>");
result.append(getTitle());
result.append("</title>");
result.append("<author>");
result.append(getAuthor());
result.append("</author>");
result.append("<isbn>");
result.append(getIsbn());
result.append("</isbn>");
result.append("</book>");
return result.toString();
}
}

package example2;

import java.awt.Color;


public class Car implements IGenerateXML {
private String manufacturer;
private String model;
private Color colour;

public Car(String manufacturer, String model, Color colour) {
this.manufacturer = manufacturer;
this.model = model;
this.colour = colour;
}

public Color getColour() {
return colour;
}

public String getManufacturer() {
return manufacturer;
}

public String getModel() {
return model;
}

public String generateXML() {
StringBuffer result = new StringBuffer();
result.append("<car>");
result.append("<manufacturer>");
result.append(getManufacturer());
result.append("</manufacturer>");
result.append("<model>");
result.append(getModel());
result.append("</model>");
result.append("<colour>");
result.append(getColour());
result.append("</colour>");
result.append("</car>");
return result.toString();
}
}
The XMLGenerator class is now greatly simplified:
package example2;


import java.util.Iterator;
import java.util.List;


public class XMLGenerator {
public String generateXML(List items){
StringBuffer result = new StringBuffer();
Iterator iterator = items.iterator();
while (iterator.hasNext()){
result.append("<item>");
IGenerateXML obj = (IGenerateXML) iterator.next();
result.append(obj.generateXML());
result.append("</item>");
}
return result.toString();
}
}
That's it! No messing around with java.lang.Object, instanceof or erroneously overloaded methods.

Friday, September 03, 2004

nVidia and Mandrake 10

My PC at home runs Mandrake 10.0 and has done for the last couple of months since I upgraded from Mandrake 9.1. In general I have been very pleased with the distribution. My first brush with Linux was nearly 10 years ago when I installed Slackware off 4 floppy disks on a 386 machine which had previously run Windows 3.1. I was amazed by the transformation in the previously feeble machine; whereas under Windows 3.1 it felt like the machine was constantly dragging itself through mud, with Slackware it just flew. However even I have to admit that that installation wasn't very user friendly. In comparison modern distributions such as Mandrake have made quantum leaps.

However since upgrading I have had a problem with periodic random freezes. There seemed to be no consistent cause, but the result was always the same: the screen froze and would not accept any input (not even ctrl-alt-f1) and I couldn't even log in remotely and restart X.

Recently this seems to have been happening more frequently, culminating this evening when it seemed to freeze within 5 minutes of booting. I was sufficiently frustrated to be bothered to do something about it. Given that the machine previously was stable, I guessed the problem was a driver. Experimentation revealed that disabling the onboard nVidia network card (I have an Asus A7N8X motherboard) fixed the problem. Further investigation revealed that Mandrake 10 had automatically installed the open-source forcedeth nVidia driver. I downloaded a driver from nVidia's website and sure enough that fixed the problem. I have at least been running for over half an hour now without a freeze, so fingers crossed!