Arguments against abstraction

You know what is the nice thing about Google Plus? Lack of that pesky character limit of Twitter. You can post a full essay as a status update if you want to. Not that you should. I try not to do that as a rule because no one wants to read long essays in their stream. And, if I posted essays over there, then I wouldn’t have anything to post on here. It does not mean I’m not tempted though.

Take this post for example.

Initially I wanted to just make a short comment on Bozhidar Bozhanov’s defense of Java verbosity. About 500 words later, I realized it probably should cut the status update short, and expand it into a full blog post.

Bozhanov makes an interesting argument but I believe he mistakenly talks about “verbosity” while his examples clearly show that what he likes about Java is the low level approach to things like I/O or http response handling. His is an argument for explicit complexity rather than verbosity per se.

Java has reputation for verbosity for more than one reason. It is low on syntactic sugar and prefers long chains of method calls over symbols. It is also both statically typed and explicit to a fault leading to long list of type declarations that preface any useful code. Finally Java is low on built in abstraction classes. The general language design philosophy is to be as explicit as possible, unless it actually get in the way (and it does – more on it later).

This focus on explicit way of doing things means that there are often no quick and easy ways to do stuff like I/O or HTTP request handling. You have no choice but to dive deep and understand streams and servlets to do just about anything. It also forces you to re-implement the same solution every single time.

Bozhanov is right – you always start by copy-pasting some boilerplate code. Then you understand the boilerplate code. What he forgets is that you then you continue copy-pasting that code for the rest of your career. Why? Because once you find an optimal way to read your files, handle your http responses and etc, then there is usually no need to change it. It will always be the same block of code – copy-pasted across all your projects. You might as well abstract it into your own class, import it everywhere, and just forget about the whole explicit mess it. Or use a third party class/framework to do abstract it for you.

But then you have more code to test against.

He is essentially the same argument that C programmers make about manual memory management. It’s true that you will probably never fully grasp the fine points of C pointer arithmentic and the subtleties of memory allocation and dealocation. But if you are a Java programmer – or for that matter a programmer in any garbage collected, JIT compiled language you don’t have to. That layer is abstracted, and you can concentrate on solving a problem without being distracted by side problems of memory allocation.

Same with Java. Some of the other languages out there use more abstraction – and for the most part that is a good thing.

Hell, Java does it too. The language has been slowly growing abstractions for common tasks, as a response to the broad and unilateral criticism of it’s needless explicit from within of our industry. Let me give you a quick example.

When I was a young undergraduate and was just starting to learn Java, there was no easy way to read user input from the console. The usual programming language teaching tradition says that the second program students ought to learn after “Hello World” is more or less “Hello Bob” – a version that asks the user for their name and then outputs it. Unlike most languages, Java did not have an easy way to do this back then – you had to fuck around with streams and you had to catch an exception this:

String name;
BufferedReader br;
br = new BufferedReader(new InputStreamReader(System.in));
try 
{ 
   System.out.print("Enter your name: ");
   name = br.readLine(); 
} 
catch (IOException ioe) { }

This is all good and great if you want to teach your students about string buffering and exception handling. But chances are that 90% of the time all you want is to get a string from the console without worrying about all the underlying mechanics.

What happened back then was that every intro to Java book on the market shipped with it’s own “Console” or “KeyboardInput” library on a CD or downloadable from the internet that would abstract all of the above to a single call to a static method.

Eventually, common sense prevailed and these days Java programmers can just do:

Console c = System.console();
String name = c.readLine("Enter your name: ");

Can you still do it the old way? Of course you can. Whenever you really need fine grained control over the way stream is buffered in memory, you can work with streams. The point is, you don’t have to. You have an option not to worry about it and use a tested, mature, built-in abstraction library.

For the sake of the argument, both PHP and Ruby also allow you to fuck around with I/O streams. The author of the blog post was never aware of this, because he never actually needed them, until he stumbled upon Java which forced him to master them. I find this very telling.

The fact that he was able to solve problems, and write functional code without deep understanding of these concepts leads me to believe that this understanding was not crucial. I’m not saying you should not know these things – that knowledge does make you a better programmer. But perhaps it is best to cross that bridge when the problem really necessitates it rather than to be forced to solve it as a prelude to a whole different high level problem.

For example, when your abstractions start leaking it may be time to roll up your sleeves and dive into the sea of complexity. But as long as they hold water well enough for the issue at hand, you really don’t need to worry about them.

Abstraction is useful because it lets you look at the big picture. It lets you fit more of problem-specific code on your screen and in your head. Without them, it is easy to miss a forest for the trees sometimes.

This entry was posted in Uncategorized. Bookmark the permalink.



One Response to Arguments against abstraction

  1. icebrain PORTUGAL Mozilla Firefox Linux Terminalist says:

    I slightly disagree. I think one should in fact learn how I/O works before using it, even if you don’t have to – but as a matter of professional hubris¹, not because you’re forced to.

    Where I do agree with you is that you shouldn’t intentionally handicap the language just to make sure people learn about the concepts. A quote from Guido when explaining the lack of private members on objects in Python was “we’re all consenting adults here”, and I think that’s an important rule to follow by a language or library.

    And his solution has a big problem, which is dependency hell; to use sane APIs, he’s essentially forced to either maintain updated a bunch of third-party libraries (and what if they die down?) or homebrew code which is more crud to test and for new developers to be burden with.
    That’s why I like Python’s (and others) approach of “batteries included”, because I know I have a bunch of useful APIs I can use without having to concern myself about whether the people I distribute the code to will have them installed or if they’re being updated.

    ¹ see Larry Wall’s three virtues of a programmer

    Reply  |  Quote

Leave a Reply

Your email address will not be published. Required fields are marked *