Home > java > Learning from design mistakes

Learning from design mistakes

While coming up with APIs or a framework, design forms a crucial part of the end result. While a solid design does indeed allow for flexible usage of an API, usability goes hand in hand with the design. What better way is there to create an API, than to learn from the mistakes and successes of other developers first ? Lets take a look at some examples in the java API where things could have been better…

Stack and Properties:

A java.util.Stack provides a standard Stack implementation in the java language. But did you know it extend a java.util.Vector ? Why is this wrong ? Because you can do this

package com.design;
 
import java.util.Stack;
import java.util.Vector;
 
public class StackTests
{
 
    public static void main(String... args)
    {
        new StackTests().go();
    }
 
    public void go()
    {
        Vector<String> vector = new Stack<String>();
        vector.add("first");
        Stack <String> stack = (Stack <String>) vector;
        String peek = stack.peek();
        System.out.println(peek);
 
        stack.push("next");
        stack.push("item");
        String remove = vector.remove(2);
        System.out.println("Removed: " + remove);
        peek = stack.peek();
        System.out.println(peek);
    }
}
 
Output:
 
first
Removed: item
next

There are so many things that are going on there that are wrong.

  1. Vector is a slow DS. Its methods are synchronized and there is no way around this right now since this contract has been sealed. It cannot be changed without changing backward compatibility.
  2. Vector has exposed its own methods to a stack. You should not be able to add() on to a stack.
  3. Typecasting between Vector / Stack is plain weird.
  4. Since the contract methods exposed by both classes operate on the same internal data structure, the outcome can often be confusing.

This is something the API folks got wrong. This is not the only class that should have used composition over inheritance. The java.util.Properties class is another example. It extends from HashTable and now there is no way around that.

Dummy variables:

This one is probably not well known. A HashSet() has a default constructor which takes a boolean variable called dummy. It is never used. So why does it exist ? Its there because a LinkedHashSet (which extends the HashSet) uses this constructor to tell its super class that the backing data structure should be a LinkedHashMap. The advantage of doing this is that LinkedHashSet will have very little code to house into its implementation.

From HashSet.java:

    /**
* Constructs a new, empty linked hash set.  (This package private
* constructor is only used by LinkedHashSet.) The backing
* HashMap instance is a LinkedHashMap with the specified initial
* capacity and the specified load factor.
*
* @param      initialCapacity   the initial capacity of the hash map
* @param      loadFactor        the load factor of the hash map
* @param      dummy             ignored (distinguishes this
*             constructor from other int, float constructor.)
* @throws     IllegalArgumentException if the initial capacity is less
*             than zero, or if the load factor is nonpositive
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap(initialCapacity, loadFactor);
}

It is not a great idea to write a separate constructor just because one sub class might need it. Secondly the javadoc explicitly mentions that only a LinkedHashSet uses this constructor. That message is a little confusing. Does that mean other subclasses are not meant to use this constructor ? Why does a subclass even need to know that ?

The side effect of this decision is not far reaching, as you may have already noted. Had the constructor been protected, the consequences would have been worse.

Usability:

The java community is pretty awesome. When a solution is too complicated, folks come out with a new framework / API to combat it. Take EJB for example. Versions 1 and 2 were pure horror. Version 3 is a little better. JEE6 has also learned a little from Spring.

This brings us to the java Date and its formatting APIs. Usability wise, many deprecated methods and confusing constructors make for a difficult time using the API. Which is why other solutions like Joda time and Apache commons date utils pop up. The ‘Why Joda Time?’ section helps explain what problem the API intends to solve where the JDK fell short.

In general, it will be hard to judge an API / framework without letting a few developers toy around with it first. The methods / constructors may well do what the contract defines them to do, but if it takes 100 steps against 10 to reach from point A to point B, guess which route a developer wants to take ?


In conclusion, these points are not about nitpicking the JDK / Java APIs in any manner. As long as developers learn from these mistakes, they can avoid them in their own code. The JDK is abundant with good usages of design patterns and some of its API are well thought out. Just avoid the bad design decisions whenever possible :D





Categories: java Tags: , , ,
  1. November 7th, 2010 at 14:11 | #1

    … And Sun fixed the Properties class with the Preferences . Ironically, nobody uses Preferences and they all go with Properties (from the projects I know) …

  2. November 10th, 2010 at 14:26 | #2

    @DucQuoc.wordpress.com

    I am not sure preferences can replace properties as such. “Preferences” does not tell you where exactly the data is stored. It could be in a registry or a hidden file. The advantage of using “Properties” is that you can edit the properties file you are loading from. With “Preferences” that is not possible, which I would guess is the reason folks dont use it.

  3. Javin Paul
    January 6th, 2011 at 13:08 | #3

    I like your point on why Stack is implemented using Java , but I am wondering what makes java api designer to go that way , do you see any specific reason why does the designed like that in first place or its simply a mistake.

    Thanks
    Javin

  4. gfdgd
    August 26th, 2011 at 08:25 | #4

    1321321

  1. No trackbacks yet.