Thursday, July 22, 2010

In reply to Structural versus Nominal typing

Let's start with a claim from a wikipedia page:

"Comparison:
Nominal typing is useful at preventing accidental type equivalence, and is considered to have better type-safety than structural typing."

Wow, where did that come from? Well, not everybody knows it but inheritance, one of the core software resuse concepts in object oriented programming, is not a guarantee for sub-typing. In other terms, inheritance, the fact that as a programmer you declare a class (identified by a name) is a subclass of another one (identified similarly) doesn't guarantee that the Liskov substitution principle can be applied. This is due to the fact that one can actually replace implementation of non-final methods in any subclass, changing behaviour of current implementations.

This is probably one of the reasons the makers of the Spring framework have a guiding principle "open for extension, closed for modification"; basically sealling most implementation methods with final.

On the other hand, we are already seeing the world of structural types creeping into the OO space: the introduction of "generics" is nothing but the realization of the OO community that parametric polymorphism - a concept developed within structural type systems, namely those with Hindley-Milner type inference - is a better way to express programmer's intentions. And what's a generic type? Yes, it's a type defined by structure, not by name.

So, what's the obsesion in OO -and particularly in Java- with names?

I agree that names are important. Two tuple types of (double, double), one used for cartesian coordinates and the other for polar coordinates should be named properly so programmers are protected from mixing them up. Yes, naming is important in this context.

But I believe this is not always the case. Enter the debate of closures for example. In java you need to declare (i.e. give a name), to every closure you intent to use, and the programmer has to implement that interface. Since its inception, every knew that this was very verbose.

From a programmer's perspective, I believe that for simple cases we already have a way to tell what's expected: the parameter's name.

So, instead of declaring an interface:

interface ValidItem {
boolean isItemOk(Object item);
}

just to be able to provide something like

class Something {
...
void checkAll(ValidItem test) { ... }
...
}

It should be enough to do it like:

class Something {
...
void checkAll(isItemOk:Object -> boolean) { ... }
...
}

Which is the way you do it in FP (Haskell, Ocaml, Clean, etc).

So, bottom line, in Java the descriptive power of a parameter's name is underestimated.

I'm already hearing "but this is only for simple cases". Well, one of the core principles of maintenable code is simplicity, the overarchingprinciple in Clean Code book. So, this should be sufficient in most cases... well, given that you were able to provide a type signature, which you are not at the moment.


Saturday, June 19, 2010

Null: that little ugly Evil

When Java was created, one of the goals was to simplify C++ for the masses. And it certainly succeed, Java is among the top most popular languages now. In its C++ trimming task, however, one little ugly evil passed under the designers' noses and smuggled into Java: the null value. I can speculate a couple of reasons, but I am more interested in uncovering first its ugly face in the light of programming types.

Null is a value that is assignable to all object types, is a valid object reference in Java. It means that, as value, it belongs to all object types. If you think about this for a minute you will realize that this doesn't make sense: it should be impossible for a programmer to handle a universal value for all types, it's like saying that you could have an object reference that conforms to all possible APIs, type contraints and so forth. It's like putting a god in your program. But of course, such value cannot exist, and instead of a god you are actualy falling prey to a little evil. It promises to be assignable to any type but conforms to it by throwing the program into bottom type, the type that has no values, the type of the failling function types. It ruins it.

What happens every Java, and C# programmer, knows it: a NullPointerException is thrown and the program can safely recover from the impasse - if she or he were careful enough to consider it. So, supposedly, Java programmers should thank the designers when they created a safe programming language that doesn't fall into segmentation fault. Oh, yes, thanks - you just hid the problem by another level of indirection.

Nowadays, you can guess that there are proposed practices and patterns to avoid it. You can read about the Null pattern or practices to avoid null in C#. Could it be solved from start? Well, yes, there are languages out there that don't have a null value, Haskell or Clean to name the ones I know, but they are not popular because they were born in Academia in the area of functional programming. In the object oriented way of thinking probably was too dificult to remove it: can you force programmers to have a valid object reference all the time? Probably not, because those forced object references -say, using a default constructor for example with void implementations as suggested by the pattern mentioned above- would have been unusable anyway, wouldn't it? So why creating objects that are not valid? Inefficient anyway, isn't it?

Well, Haskell and Clean use what's called Algebraic Data Types, which is a funny name given to the ability you had already in type constructors in C, with the caveat that the union was the one requiring improvement and it had it. All wrapped in a coherent type theory... and with no behaviour (at least with OO glasses).

So, one bet is that it was this obsession with behaviour -something on what they also failed- the reason why the language designers continued to use null in the improved version of C++ that they created. But another guess is that this is probably linked to the obsession in object oriented programming with names, but that's a topic for another post.