Daniel Pitts’ Tech Blog

Archive for November, 2007

Almost Useful: if instanceof

Friday, November 23rd, 2007

While often times if (x instanceof Y) indicates a problem that should be solved with proper use of polymorphic methods, it sometimes is unavoidable (.equals(Object o) implementation for example). A common idiom is:

if (x instanceof Y) {
  Y y = (Y) x;
}

Of course, this makes sense from a utility point of view, you know that it is a Y object, and so you want Y functionality from it. From a programmers point of view though, it is terribly redundant in many ways. In many cases, static analysis can tell the compiler that when you are in the block of that if statement, that x is indeed a Y object, why then should I be forced to cast to Y? Why can’t the compiler figure out the type for me?

This becomes even more useful if we combine the concept with the fully useful Type Intersection (Not yet implemented). If both of these features were implemented, then you could write something like:

public <T extends Comparable<T>> void sort(List<? extends T> list) {
 if (list instanceof RandomAccess) {
    /* list compile-time type here would be List<? extends T>&RandomAccess. */
    sort(list);
  } else {
    /* Other type of sort implementation. */
  }
}
public <T extends Comparable<T>> void sort(List<? extends T>&RandomAccess list) {
  /* Random access sort implementation */
}

This type of static analysis feature could be extended to predict NPE’s and redundant checks. Heck, the IDE I use tells me when I’ve accessed something when it might be null, or when my inner-if statement is a subset of the outer. It even has shortcuts for adding the cast in the if (x instanceof Y) {} blocks.

Almost Useful: Java Type Intersection.

Friday, November 23rd, 2007

First, for my subscribers that celebrate it, Happy Thanksgiving!

I’ve written about it before, but I think its worth revisiting. Type intersection would be a highly useful feature if not for one thing. “It is not possible to write an intersection type directly as part of a program; no syntax supports this.” - JLS (ยง4.9). That seems like a poor excuse to not support a feature as potentially powerful as type intersection could have been.

They were bold enough to add syntax all over the place for Generics. They added new syntatical meanings for ‘?’ ‘<’, and ‘>’. As a matter of fact, they added a syntax within that construct for handling Type Intersections. Would it really be that difficult to reuse that syntax outside of capture conversions and type inference? Heck, maybe even make it reifiable, although that’s not *as* important.

One example others have used in the past where it would be useful to have this type intersection is with the marker interface RandomAccess. While marker interfaces are less useful now that we have annotations, it none-the-less exists, and can be useful for ensuring that the user of an algorithm passes in a compatible list.

For example, its quite possible to do the following, even with the currently crippled implementation of type intersection.
<T extends List<String> & RandomAccess> void foo(T list) { ... }
You know that you’re getting a random access list. The pain point is that you can not do the following:
<T extends List<String> & RandomAccess> T foo() { return new ArrayList<String>(); }
The reason that isn’t legal is quite simple, even if its not obvious. T is any type that satisfies List<String>&RandomAccess, so you don’t know that it is an ArrayList. You might have MyNonArrayList<String> list = foo(); Oops, that would be an incompatible assignment.

The better approach would be to have the return type be an explicit type that is List<String>&RandomAccess. As a matter of fact, my suggestion is to use that syntax exactly, unless there is a compiler-grammar reason not to. So, our T foo() line becomes:
List<String>&RandomAccess foo() { return new ArrayList<String>(); }
So then we can do: List<String>&RandomAccess list = foo(); Actually, we could just use List<String> list=foo() if we don’t care about RandomAccess.

An important addition to make to this would be casting. For legacy support, if I have a List<String>, but I know that it should be an ArrayList (or some other RandomAccess), I should be able to cast: foo((List<String>&RandomAccess)list);

Primitive Obsession II: (Im)mutability and Redefining Primitive

Sunday, November 4th, 2007

Last week I discussed some of the techniques for and benefits of not using simple “Primitive” values to represent your data. This article is all about taking that concept to the next level.

Let’s say that I have a value that represents an angle. I could use a double to represent the radians, or I could create a class called Angle, which internally might use a double to represent radians. If you are trying to avoid primitive obsession, you would use the latter. Now you have value objects of type Angle which can be used in meaningful ways. So, we’re done, right? I say no.

Angle is now its own form of primitive. Just as an Integer object is an abstraction of a numeric value in a specific set of reals, an Angle instance is an abstraction of a geometric/trigonometric angle. This means that it can be the building block for other more specific types. For instance, a 2 dimensional vector can be represented in “polar form” as an Angle and a Magnitude. In a physical simulation, a Magnitude is often a Distance, so we’ll assume that case for this article.

So, we can create a Vector interface (not to be confused with the java.util.Vector class). We can then create a PolarVectorImpl class which uses Angle and Distance. We can even create a CartesianVectorImpl which uses two Distance objects to represent the vector. Whats more, is these can both be used by anything that expects a Vector, with no extra work in the client code. We can easily create a rotate(Angle) method, or any other useful methods.

Another important and related concept that we haven’t touched on is mutability. If an object is mutable, that means that the apparent state of the object can change over the lifetime of the object. If an object is immutable, the apparent state of the object will appear the same throughout the lifetime of the object. This means that any invocation of one method on that object will always have the same outcome as any other on that same method. Also, any object that is returned from those methods must either be immutable themselves, or be distinct instances. Why is this important? Immutable objects have some benefits.

  • Immutable objects are inherently thread safe.
  • Immutable objects are easy to reason about.
  • Immutable objects are easier to debug.
  • Immutable objects can be passed around freely without defensive copying.

On the down side, immutability makes a pretty boring universe. If you’re object is expected to do different things depending on what has happened to it in the past, that object must be mutable. It must have state.

What does this have to do with primitive values? Its common to create immutable value objects. If we design the Angle class to be immutable, then we can safely say that one instance represents exactly one angle throughout its lifetime. All of our Angle objects are value objects. They are utility objects and reusable in many projects. On the other hand, if we’re doing a simulation of sorts, it might be useful to have a mutable angle, something that we can adjust over time. Lets call this class Heading. What’s in a Heading? An Angle, of course. Now here’s where things get interesting…

Since an Angle is a measurable thing, its easy to compare two values for equality. For Angles specifically, they are equal if their values represent the same geometric angle. Once equality is established, those objects are equal for ever. Not so with Heading. A Heading may represent the same angle at one moment in time, but at another moment they represent very different angles. For this type of object, equality only makes sense for the identity. A Heading instance is its own object, and can be queried/manipulated by many other objects/methods within the project.

The benefit of this design, is a manipulator/querier need not know who “owns” the Heading instance. A Robot might have a Heading, and a SteeringServo might manipulate that Heading. You can create the Robot and the SteeringServo objects independently of each other. The SteeringServo doesn’t even need to know its the Heading of a Robot. Once the Robot and SteeringServo both have the same Heading instance, they become connected without being coupled. This is huge goal for Object Oriented designers/programmers. The correct functioning of a SteeringServo isn’t dependent on the correct functioning of a Robot, or even of a Heading, only on itself. Similarly, a Robot’s correct functioning isn’t dependent on the correct functioning of the SteeringServo. The program as a whole may not work if there is a bug, but it easier to look at one class and ask yourself “Is there anything wrong with this code,” than it is to ask the same question about the whole project.

If you think all of this abstraction is unnecessary or unhelpful, think about all the layers beneath our Heading class. Lets have some fun and break it down into its most primitive parts.

  • Heading instance is an identity value containing an Angle and representing a direction at a point in time.
  • An Angle is an equal-comparable value containing a double and representing a direction.
  • A double is a equal-comparable and order-comparable value containing an ordered set of bits and representing a real number.
  • A bit is an equal-comparable value containing a memory cell representing true or false.
  • A memory cell is often times a capacitor that is either charged or uncharged

If you had to think about the implementation details of a bit every time you used a double, it would make the mental weight of programming so immense that no useful programs could be written. Heading can now be used very easily without adding the mental weight of how its implemented. SteeringServo can be implemented without the mental weight of what it is steering. Overall, the practice of this kind of decoupling will make your program easier for the most important source-code interpreter. You.