Verbose, concise and how Java relates to that
Often when reading a forum discussion somewhere about the verbosity of Java and conciseness of some language X we meet people trying to convince us that Java is good as it is, because “I want to express everything clearly, and when reading I want to see what I get. No crypticts, no implicits”.
And when debating about that opinion, it often comes to productivity, which is then answered with the hint to “good IDEs”, so that Java expressions are typed almost as fast as code in more concise languages.
So what is this thing about expressiveness and conciseness?
Let’s have a look at other formal languages, say: mathematics.
Imagine the following term: 5*4*3*2*1
This is more than a chain of multiplications. It is a chain of multiplications starting from a given number (here: 5) counted down to 1 with stepwidth 1. And this concept has a specific name: faculty.
So “faculty” is an unambiguous, single word for the concept descibed above in more verbose words.
Likewise in symbolic language, you write this concept as: 5! (say: five faculty)
That this symbol is far better than the multiplication expression, can be easily seen when trying to write 100! in long form.
Now consider writing mathematical formulas without the symbolic abstraction of faculty, always only expressing it as multiplication chain. You can argue, that you can easily grok the pattern 5*4*3*2*1 as being faculty by reflex. But be cautious. Could you really always and immediately say, that it is faculty five?
Or isn’t it too easy to mistake it with 5*4*3+2*1 (as typo when writing, but more often when reading it in a more complex context)? Here you have a pattern-mismatch mistake.
The same now works for programming languages. When saying, that one wants to “express everything clearly”, it seems natural to write:
public static final
Indeed, it could be abbreviated to omit typing and “verbosity”, e.g. to:
pub sta fin
Easier to write, only slightly more cryptic to read.
Much more concise would it be, when we would introduce symbols, such leading to a more formal symbolic language.
Imagine + for public, ^ for static, _ for final, then the modifier chain above could be: +^_
Write this on a paper and read it three days later. You remember what the symbols mean?
So: Symbols are much more concise, perhaps even more precise, but maybe more cryptic for a reader, especially when trying to learn a language. You must not only learn the concepts behind public, static and final, but also their symbols.
But here it comes. The muttering about Java being to verbose is not about abbreviations or introduction of symbols. It is much more about abstraction of concepts.
Look: Combination of symbols construct patterns. And such patterns express more abstract
concepts .
So when seeing the above pattern (+^_) you can immediately think of it as a “word” with unknown letters, and understand it as the concept “constant”.
And here we are! Faculty is a higher order concept, compiled and expressed by lower level terms. Always using the lower level constructs (the “How-to”) instead of the concept is not as easily grokkable like having a symbol for the concept itsself.
Likewise, when reading public static final in Java, you always have the effort to transform it to the implicit higher order concept of “constant”, much easier expressable by, for example: const .
This is what this verbose vs. concise debate is all about.
Could you imagine to write always “Small house with big entrance to shelter cars” instead of “garage”?
That’s what Java obliges you to do. And regarding IDE support: I do not believe you really want to advise a template+shortcut enabled word processor as the best solution to write texts, instead of creating better words for things.
In the end, Java expressions are not napkin-able, and are not suited for whiteboard development.
I’ve seen very different mail forum posts about this or that algorithm, and it was always PITA to read Java code out of an email, perhaps wrapped at 80 characters.
Not so in really expressive languages!
Coming back to the pattern mismatch mistake above:
I detected this problem when I refactored a good bunch of code from Java pre-5 while loops to the Java 5 foreach loop. In many many cases it was easy to exchange the loops. But I detected more than one place, where the loop construct was slightly different, and replacement did not work.
The point is: I was not aware of this differences, because browsing over the code, all loops seemed equally expressing the standard iteration concept of get iterator, while hasNext, elem = next.
Only the refactoring revealed the locations where the looping concept indeed differed.
Expressive? Or truth hidden by word flood?
So when talking about Java’s verbosity and new concepts for Java 7 or 8 or whatever, first remember the faculty example and cogitate if the new ideas don’t express abstract concepts more explicitly and thus clearer than the verbose forms, you considered being more “clear and directly” before.
An little pattern trap
A little trap I recognised to fall in quite often in Grooy is about GStrings.
Groovy has a special String syntax which allows to put in variable parts, making it a simple form of templates.
So you can work for example with a variable ‘name’ this way:
def names = ["Zaphod", "Ford", "Trillian"]
names.each { name ->
println "The name is: $name"
}
In the String printed out the variable $name is replaced by the current value of the parameter ‘name’ of the iteration.
That technique makes it also quite convenient to generate some html :
names.each { name ->
println """<font color="red">$name</font>"""
}
This pattern to write out a variable wrapped in additional text in a GString is so common, that I often enough forget that a variable can be printed out directly and so find myself writing such lines:
println "$someSting"
(Some people considered me being a formalist when they read such code of mine, trying to develop patterns as generic as possible and applying them in every and all cases.
Well, I’m not! It’s simply too less active thinking, too much reflex
)
Do you know of other patterns often applied too mechanically?
Types: Static, dynamic and the quirks of velocity
Until shortly I was someone who felt often annoyed by the verbosity of Java and the restrictions of the type system, which much too often seemed to stand in the way of fluid development.
Even Generics seemed at a first glance to add to this pain, and not alleviate it.
I blamed the principle of strong and static typing as well as the edit-compile-run cycle for that and so oftentimes called for a dynamic language, best to all interpreted, to gain more development speed and flexibility.
But recently I stumbled over the flaws of dynamic typing, interpreted code and multi-language mixup in our codegenerator.
It began with a method which returned a Collection (and I must say, that everying worked somehow before I laid hands on). Porting some code from 1.4 iterator syntax to the new for-loops and thus introducing type parameters revealed a design failure: A method in a subclass of a hierarchy shadowed a superclass’ method far up in the hierarchy with the same name but different return value. Well, indeed only different for the compiler after parameterising the returned Collection, so it was some sort of “duck typing” before.
This flaw was never detected as the methods were called in different contexts, each expecting the type of items in the Collection which it indeed got. But after parameterising the Collection with the respective types, the IDE/compiler immediately uncovered the shadow-problem.
Now, in an IDE renaming a method is a simple refactoring step. Much too easy, so with no effort done even far at the end of a development timeline.
Unfortunately I was not aware that this method was called from within a good bunch of velocity templates, and the IDE was indeed not aware of the dependency between this templates and my Java class.
As velocity templates aren’t compiled but interpreted, there was no way to detect that mismatch during build time.
The application, as I just mentioned above, was a codegenerator, so the problem first occured on test runs, now in some classes generating lesser code than before (what generally is good, but not if happening without intention
).
Tracing the phenomena made me feel a bit … weary.
It was easily detected to be caused by my renaming action. The template code called the method under its old name, but instead of the expected collection it got an empty one. This was, because after the renaming refactoring, the actually called method was the one from the upper class.
This returned (un-)fortunately an empty collection, otherwise some other template code would have called the items in a way impossible for the type actually carried by that collection, and an exception would have thrown.
But so, simply this code was bypassed due to the empty collection, resulting in a lack of output.
What to do? Well, the calls to the method using its old name had to be changed.
Unfortunately there was no way to determine where in the templates this method was called, other than doing a dumb grep.
After changing the mass of templates, all seemed well at a first glance.
So building the codegenerator again, deploying it and doing the next test run.
But what surprise! Even more files changed, missing parts of formerly generated code!
It took now a good while to detect what was going on.
The template was used in different contexts, where it produced the same lines of generated code.
But to do that, it called the mentioned method on a reference, expecting the retrieved Collection to always contain the same type of items. Only that the type of the objects on which the method was called was not always the same! The template was also used in a context, where another type of objects was referenced, its class not being in the hierarchy mentioned before, so not sharing a common type. A typical case of duck typing: As long as it responds to my message and I get what I want, all is fine. Forget about TYPES!
So what happend so far was:
- Class One: renaming the method after getting compiler errors due to
- Templates: renaming the method calls after detecting that mistakenly the superclass’ method was called, leading to misbehaviour.
- Now: getting even more misbehaviour due to wrong method calls on other types.
The latter misbehaviour resulted from the fact, that velocity does indeed not complain if in code like the following the Dependencies property cannot be found.
#foreach ($dep in ${element.Dependencies})
So the all in all consequence:
- Duck Typing works by intentionally doing the right things at the right time. Knowing that, it becomes part of your development process.
- You can do it easily in Java too, simply use Object and the raw type Collection whereever you can. In this way: Don’t know why people rant against Duck Typing. They did it in the pre-Generics era anyway.
- When intending to work with typing to get the most from the compiler, interpreted code and dynamic typing can stab you in your back, especially when your interpreter does the favor to silently ignore incorrect method calls and the like.
At the end more seriously: After I had to maintain and first of all refactor some … ahem … not so well written foreign dynamic script code, and after getting in contact with Scala, I start to rethink my animosity against strong static type systems and compilers.
I recognise, that it mostly was driven by Java’s verbosity and implementation details than by principles.
Things changes, me too.
Java: why the heck compiler doesn’t check ?
Well, why do we use typing in our coding? To get typechecks by the compiler, I thought.
But the compiler indeed has to know, what we want or expect. So we give even more type information, namely by casting and parametrisation (Generics).
But why the heck is this “fine” Java compiler not able to detect such a simple typo?
Collection<AssociationEnd> lChildViews = lView. getChildViews();
for (AssociationEnd iFacade: lChildViews) {
WidgetAssociationEnd lFacade = (WidgetAssociationEnd) lChildViews;
Well, indeed the assignment should take and cast the reference in iFacade, not in lChildViews.
The code above resulted in a nice ClassCastException … at runtime!
Now I am working with so much type information, and the compiler is not able to check that WidgetAssociationEnd is no subtype of Collection? What the hell is this??