Verbosity is not Java’s fault « Schneide Blog

Quiz: Whats one of the most heard flaws of Java compared to other languages?

Bad Performance? That%u2019s a long overhauled myth. Slow startup? OK, this can be improved%u2026 It%u2019s verbosity, right? Right but wrong. Yes, it is one of the most mentioned flaws but is it really inherit to the language Java? Do you really think Closures, annotations or any other new introduced language feature will significantly reduce the clutter? Don%u2019t get me wrong here: closures are a mighty construct and I like them a lot. But the source of the problem lies elsewhere: the APIs. What?! You will tell me Java has some great libraries. These are the ones that let Java stand out! I don%u2019t talk about the functionality of the libraries here I mean the design of the API. Let me elaborate on this.

Example 1: HTML parsing/manipulation

Say you want to parse a HTML page and remove all infoboxes and add your link to a blog box:

01DOMFragmentParser parser = new DOMFragmentParser();
02parser.setFeature("http://xml.org/sax/features/namespaces", false);
07HTMLDocument document = new HTMLDocumentImpl();
08DocumentFragment fragment = document.createDocumentFragment();
09parser.parse(new InputSource(new StringReader(html)), fragment);
10XPathFactory factory = XPathFactory.newInstance();
11XPath xpath = factory.newXPath();
12Node infobox = xpath.evaluate("//*/div[@class='infobox']", fragment, XPathConstants.NODE);
13infobox.getParentNode().removeChild(infobox);
14Node blog = xpath.evaluate("//*[@id='blog']", fragment, XPathConstants.NODE);
15NodeList children = blog.getChildNodes();
16for (int i = 0; i < children.getLength(); i ) {
17    node.remove(children.item(i));
18}
19blog.appendChild(/*create Elementtree*/);

What you really want to say is:

1HTMLDocument document = new HTMLDocument(url);
2document.at("//*/div[@class='infobox']").remove();
3document.at("//*[@id='blog']").setInnerHtml("Blog");

Much more concise, easy to read and it communicates its purpose clearly. The functionality is the same but what you need to do is vastly different.

  The library behind the API should do the heavy lifting not the API's user.  

Example 2: HTTP requests

Take this example of sending a post request to an URL:

01HttpClient client = new HttpClient();
02PostMethod post = new PostMethod(url);
03for (Entry param : params.entrySet()) {
04    post.setParameter(param.key, param.value);
05}
06try {
07    return client.executeMethod(post);
08} finally {
09    post.releaseConnection();
10}

and compare it with:

1HttpClient client = new HttpClient();
2client.post(url, params);

Yes, there are cases where you want to specify additional attributes or options but mostly you just want to send some params to an URL. This is the default functionality you want to use, so why not:

  Make the easy and most used cases easy,  the difficult ones not impossible to achieve.  

Example 3: Swing%u2019s JTable

So what happens when you designed for one purpose but people usually use it for another one?
The following code displays a JTable filled with attachments showing their name and additional actions:
(Disclaimer: this one makes heavy use of our internal frameworks)

01JTable attachmentTable = new JTable();
02TableColumnBinder<FileAttachment> tableBinding = new TableColumnBinder<FileAttachment>();
03tableBinding.addColumnBinding(new StringColumnBinding<FileAttachment>("Attachments") {
04    @Override
05    public String getValueFor(FileAttachment element, int row) {
06        return element.getName();
07    }
08});
09tableBinding.addColumnBinding(new ActionColumnBinding<FileAttachment>("Actions") {
10    @Override
11    public IAction<?, ?>[] getValueFor(FileAttachment element, int row) {
12        return getActionsFor(element);
13    }
14});
15tableBinding.bindTo(attachmentTable, this.attachments);

Now think about you had to implement this using bare Swing. You need to create a TableModel which is unfortunately based on row and column indexes instead of elements, you need to write your own renderers and editors, not talking about the different listeners which need to map the passed indexes to the corresponding element.
JTable was designed as a spreadsheet like grid but most of the time people use it as a list of items. This change in use case needs a change in the API. Now indexes are not a good reference method for a cell, you want a list of elements and a column property. When the usage pattern changes you can write a new library or component or you can:

  Evolve your API.  

Designed to be used

So why is one API design better than another? The better ones are designed to be used. They have a clearly defined purpose: to get the task done in a simple way. Just that. They don%u2019t want to satisfy a standard or a specification. They don%u2019t need to open up a huge new world of configuration options or preference tweaks.

Call to action

So I argue that to make Java (or your language of choice) a better language and environment we have to design better APIs. Better designed APIs help an environment more than just another new language feature. Don%u2019t jump on the next super duper language band wagon because it has X or Y or any other cool language feature. Improve your (API) design skills! It will help you in every language/environment you use and will use. Learning new languages is good to give you new viewpoints but don%u2019t just flee to them.

This entry was posted on Monday, February 8th, 2010 at 9:38 am and is filed under General, Java, Programming Language, Software Development. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

another java #fail

Posted via web from Bojan Babic

No comments:

Post a Comment