I hear people comment on Java's verbosity (and other languages) as if it were a bad thing, why? To me it makes code easier to understand. Less typing seems like a really trivial argument.
Because it makes you have to write more code to do the same thing. Both programmer productivity and the number of bugs in your code tend to be a factor of the lines of code that you have.
If you like Java for its verbosity, then you'll love COBOL. [Added clarification] COBOL was the punch line of many 1970s jokes about poor language design. It was allegedly designed so executives could understand programs. However, easy to understand isn't the same as easy to write nor did it engender much love of the language by programmers, rather like how easy to learn UIs don't mean easy to use.
Verbosity can cut both ways. Languages like APL are so terse that they are largely write-only languages: Programmers easily and quickly write APL programs, but are unable to read or understand them soon afterward.
Actually, Java has about the right amount of verbosity, compared to languages such as C and Perl (on one end of the spectrum) and COBOL (on the other end).
What I personally find annoying is the overuse of punctuation tokens in place of words. While it's fine to use {
and }
in place of begin
and end
, using &&
and ||
in place of and
and or
is just syntactic overkill.
Ultimately, it's not a question of how many words or symbols you use to encode a programmatic construct, but rather the amount of mental effort required by others (as well as you) who read/maintain your code to understand it. Abbreviations can help, whereas arcane symbols can hinder comprehension.
Less typing is one thing. Less reading is another. Remember that code is read more often than it is written.
It depends on what kind of verbosity. There are two kinds. Low-level syntax-level verbosity (ex. using extends
instead of :
to denote inheritance or using descriptive variable and class names) doesn't have much negative connotation, at least IMHO. In this case verbosity can often increase clarity.
There are two kinds of verbosity that are annoying. One is when syntax is too low-level and forces the programmer to specify intent for a common operation in a very indirect way. An example of this is being forced to type out the full iterator syntax instead of using a foreach
loop. By allowing intent to be specified more directly, providing syntactic sugar for common operations can both decrease verbosity and increase clarity.
The second kind of verbosity that is really annoying is semantic-level verbosity, the kind that is required to get around language features that don't exist in restricted languages like Java, or to tell the compiler stuff it already knows. For example, making lots of tiny classes and interfaces to make up for the lack of higher order functions is verbose, less clear than higher order functions, and just plain annoying. Similar things can be said for the lack of type inference, closures, etc.
What it really boils down to is that verbosity is good when it clarifies the programmer's intentions, but bad when it just adds noise to a construct that has nothing to do with the programmer's intentions. I believe that Java has plenty of the latter kind of verbosity.
I don't think it's quite that black and white. A language could be a little verbose, or very verbose, or somewhere in between.
Anyway, while people do talk about verbosity, I'm not sure it's what they really want to talk about. I think they're really talking about expressiveness. A given statement should be as verbose as necessary in order to be expressive — to clearly express the intent of the writer to both the compiler/interpreter and to other developers. That's not as easy as it sounds.
I agree with dsimcha that verbosity due to using words instead of more abstract symbols, such as extends
as opposed to :
, can increase clarity and be a net win.
To get specific, one of the aspects of Java's verbosity which can be problematic is the repetition; things like
Logger logger = Logger.getLogger(loggerName);
or
XMLOutputter xmlOutputter = new XMLOutputter();
It's not just annoying to type — it's also a lot of redundant symbols to read. And when we read lots of lines that look like that, we tend to start skimming them, and not really reading them closely. This can lead to the introduction of bugs, and to difficult troubleshooting.
There are two answers here. One is that overly verbose code like Java does not always have the elegance of less verbose languages where the concepts underlying the algorithm may be expressed more simply. Less syntax can mean less extra stuff obscuring the meaning of the code. I suspect that a lot of coders are motivated by the desire for that elegance.
However, clarity for the programmer and clarity for the maintainer are two different things. Languages like Java may be verbose, but by eliminating a lot of syntactical sugar such as operator overloading and properties, etc, Java code may actually be easier to read for those who do not have vast technical mastery of the language and more importantly, do not have the time or opportunity to become very familiar with the code to be maintained.
Operator overloading is perhaps the best example of this. It can make a program incredibly elegant in the eyes of the programmer, abstracting away all sorts of syntactical drivel leaving only the logic at the same time as making the algorithm completely impenetrable to someone who is not already familiar with the code, which is why some companies make using operator overloading a fireable offense :-).
So, the answer, as is usual in this case, is that verbosity is a good and a bad thing, depending on who you are and your situation. Which is why there are a whole bunch of languages out there. Personally, I like the idea that I can read any block of Java code out there and probably understand what's going on without having to understand the whole project. But I do so even as I dream of writing some aesthetically beautiful C# code using all those nifty features that strip away all that syntactic excess leaving almost pure gleaming logic.
Of course, others will weight the advantages and disadvantages of verbosity differently.
There's a rule of thumb: Programmers can write about the same number of lines of code per day, regardless of the language.
According to that rule of thumb, the less verbose the language, the more efficient the programmer is at creating code.
(Note: This rule of thumb might be accurate for creating code. Debugging code is another question, entirely.)
A programmer spends almost none of his time actually typing, and almost all of his time thinking about and understanding code in front of him. Verbosity makes the latter much harder.
Here's what annoys me about Java's verboseness. Let's say I have a simple class with 5 properties. It takes about 60 lines to create that class.
public class VerboseClass {
private String name;
private String address;
private String city;
private String state;
private String zip;
public VerboseClass(String name, String address, String city, String state, String zip) {
this.name = name;
this.address = address;
this.city = city;
this.state = state;
this.zip = zip;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
}
Have a look at the book 'The Mythical Man Month'. There is a chapter about measuring programmers productivity. It shows a study, which concludes that the less code a developer has to write the more productive he is.
I agree with this to some sense. The less code you have to write yourself the less maintenance is involved later (in reading, in debugging etc.). But there is a little caveat: In dynamic typed languages you write less code but you lose also typing information in source-code. But this could also decrease productivity later, because without static typed information you lose the possibility to use automatic refactoring tools, which gained productivity tremendously.
As an analogy, imagine that someone cleans their cluttered desk to just a few essential items.
One might say "there are just fewer items on the desk". But the original person may enjoy benefits far beyond that: focus, clarity, and productivity.
Furthermore, what if we have all been working at the same desk for years? Shouldn't we optimize some things? Why pretend that we are new to the gig?
In Groovy, for example, consider these features:
- java.util.* and java.io.* are imported automatically
- semi-colons are optional
- methods and classes are public by default
- support for properties
Now, these are trite examples: Groovy has so much more to offer. But even for these examples, the argument is more than just "less typing".
Arguments include:
- We have been importing java.util.* since 1996 -- do we really need to keep doing that?
- Except for rare circumstances, what does the semi-colon buy us?
- We already have an understood convention that getters/setters are noise, generated by the IDE, and relegated to the bottom of the file. Why not improve on that convention and make it an innate part of the compiler/language?
This could go much deeper into a wide variety of topics, but the point is: much of the ballyhoo about the verbosity of Java is that we are discovering ways to build on the past, and to evolve our conventions. Why pretend that it is 1996? (especially when the alternatives do not sacrifice readability to the newcomer)
The real problem with Java's verbosity isn't so much the language as it is the API.
For example, to print a line of text you do:
System.out.println("Line of text");
You get used to it, but it's a lot of typing compared to c:
printf("line of text\r\n");
Now, I actually think that makes sense the way it is. You could, for example have the Object class have a ton of built in utility functions like println so that beginning programmers wouldn't need to import all of them. And java now has things like static import so you can do
import static java.lang.System.err;
import static java.lang.System.out;
And then in your code you only need to do:
out.println("line of text");
Some of the worst examples are with XML, though. So if you have an XML document you want to parse, and you don't need any special processing you need to do:
Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream("file.xml");
It would have been easy to create a convenience function that would only require you to do
Document d = XML.readFile("file.xml");
In fact, I have a function just like that in my personal library, which makes things much easier.
On the other had, with the ImageIO library, they did thigns right. If you want to load an image with default parsing, you just call
BufferedImage myImg = ImageIO.read("file.jpg");
And that's it. Much simpler and convenient.
But, a lot of these API annoyances can be taken care of with quick convenience functions of you own. But the real problem is that it makes it hard for beginning programmers to figure out WTF is going on.
- verbosity - the amount of text
- expressiveness - the ability to express complex things shortly
- readability - the ease to understand the code
There is a tension between all 3: highly expressive language can be hard to understand, even though they can convey complex intention in a concise way. More verbosity make things maybe easier to understand, but useless verbosity (e.g. repeating information) does not help neither.
These considerations apply to the language itself, but also the API library and the programmer's code.
Java 1.4:
List list = new ArrayList(); // Integer
...
for( int i=0; i<list.size(); i++ )
{
int val = ((Integer)list.get(i)).intValue();
list.put(i, new Integer(val*val) );
}
Java 1.5 with generics and auto-boxing
List<Integer> list = new ArrayList<Integer>();
...
for( int i=0; i<list.size(); i++ )
{
int val = list.get(i);
list.put(i, val*val );
}
An "hypothetical" Java with default generic type inference and foreach
with counter.
List<Integer> list = new ArrayList();
...
foreach( val : list ; Integer position )
{
list.put( position , val*val );
}
Or in untyped Smalltalk:
list = OrderedCollection new.
...
list apply: [ :val | val * val ].
Which one do you prefer?
I think it comes down to how much stuff your eyes have to ignore when you are reading back a program.
When you are looking at some code you are generally trying to work out what it does, you are looking for the contained logic and control. If that program is something simple then there should not be much to see.
With java, certain patterns lead to a lot of boiler plate code that add little and you really don't want to look at when you are reading the code.
I would love eclipse to have a mode which greys out such code.
e.g.
final int i = 0;
Executor e;
e.execute(new Runnable() {
public void run() {
System.out.println("i="+i);
}
});
could be
final int i = 0;
Executor e;
e.execute([
System.out.println("i="+i);
]);
Also, the whole standard getter/setter stuff. This is such a pain to look at:
static class A {
private int i;
private String a;
public int getI() { return i; }
public void setI(int v) { i = v; }
public String getA() { return a; }
public void setA(String v) { a = v; }
}
vs maybe
static class A {
private int i; // @readWrite
private String a; // @readWrite
}
These are not properly thought out language change suggestions, just simple examples hopefully indicating that the information that the reader is looking for is obvious and there is still enough information for a compiler to imply and generate its own boiler plate later.
It may not look like a big deal but once you have a reasonable amount of code in place it all counts. Plus, without a decent IDE to "type" all this extra stuff in for you, it is a real pain.