The Clean Code Blog

by Robert C. Martin (Uncle Bob)

Make the Magic go away.

06 August 2015

I’ve been looking at rxJava. It’s a nice little framework that helps you to create and manage observers. The design philosophy seems to be that everything can be observed and therefore everything ought to be managed by callback.

Of course this is an old idea that dates back to data flow languages, functional languages, and other declarative languages. The idea even had echoes in the late ’90s when the GOF book was first published. Those of you who were programming back then may remember that, for a few months, everybody thought that the Observer pattern was so cool. We saw lots of observer based designs. Then that stopped because those designs were too indirect; making them too hard to trace and debug. (Tests anyone?)

I’m not saying that rxJava is a bad idea. Like I said, it looks pretty cool. It’s just that it’s not a really a hot new idea. And, after all, what is?

The Never Ending Quest

The authors of rxJava, and of Spring, and JSF, and JPA, and Struts, and [put your favorite framework here] are all searching for the same thing. These frameworks are born out of frustration with the language; and are an attempt to improve upon that language.

Every framework you’ve ever seen is really just an echo of this statement:

My language sucks!

And so we write frameworks to compensate for the lack of features that we wish were in our language. And if that doesn’t work; then, like James Gosling, Bjarne Stroustrup, Alan Kay, Brad Cox, Dennis Ritchie, Rich Hickey, and so many, many, others, we write a new language.

A new language! Golden! Pure! Perfect! A new language to solve all ills. A new language that supersedes all the others. A new language that answers all the complaints, addresses all the weaknesses, and settles all the disputes. A new magical language that is expressive, safe, dense, flexible, disciplined, and, and, and, — perfect!

Bzzzt! Wrong answer!

Of course there is no such beast. There is no perfect language. And, lately, all the “new” languages we have seen, are just rehashes of the same old … same old … same old stuff. I honestly don’t think there has been a new idea in computer languages since the late ’70s or early ’80s.

I mean, once you’ve programmed in Assembler, FORTRAN, C, Pascal, C++, Smalltalk, Lisp, Prolog, Erlang, and Forth, you’ve seen it all. Oh, I suppose you could toss in languages like Snobol, ML, Cobol, and XSLT (retch, puke). But most of their ideas were really covered in the previous list.

The same goes for frameworks. When is the last time you saw a framework with a truly new idea in it? For me, it was the Inside Macintosh framework, written in Pascal, in the late 70s and very early 80s. And that was really just a rehash of the Smalltalk framework from a few years before that.

What’s new in software?

For the last thirty years: Nothing much.

Santayana’s Curse

So why do we keep on writing new languages and new frameworks? I think the answer to that is very simple:

Those who do not remember the past are condemned to repeat it.
__Jorge Agustin Nicolas Ruiz de Santayana y Borras

In other words every new batch of programmers to come along are destined (condemned!) to rewrite the same old languages, and the same old frameworks. Oh they’ll look a little different, and they’ll have a slightly different twist. But they won’t be new in any meaningful sense.

And some of those languages and frameworks will gain a certain notoriety and become popular for awhile – as though they were something new and magical; but that’ll just be an illusion based on a near term perspective. The proponents of those “new” languages and frameworks will make soaring claims about how much faster you can code, and how much easier it is to build systems, and how much better the designs of those systems are. But in the end, the programs will be written at the same speed as before, the difficulty will be just as great as before, and the designs will still be just as bad.

Magic!

Why does this happen? Why are people always hunting for the next new language and the next new framework? Why do we go around and around on this merry-go-round of frameworks and languages in hopes that we’ll see some different scenery on the next spin? Why do we hope for the magic?

We hope for the magic, because we believe in magic. We’ve used languages whose behavior seems magical. We’ve used frameworks that do magical things. And, in our naivety, we trust that if we can just muster a little bit more of that magic, then the perfect language, or the perfect framework, will suddenly appear on the next turn of the merry-go-round.

No Magic

But there is no magic. There are just ones and zeros being manipulated at extraordinary speeds by an absurdly simple machine. And that machine needs discrete and detailed instructions; that we are obliged to write for it.

I think people should learn an assembly language as early as possible. I don’t expect them to use that assembler for very long because working in assembly language is slow and painful (and joyous!). My goal in advocating that everyone learn such a language is to make sure that the magic is destroyed.

If you’ve never worked in machine language, it’s almost impossible for you to really understand what’s going on. If you program in Java, or C#, or C++, or even C, there is magic. But after you have written some machine language, the magic goes away. You realize that you could write a C compiler in machine language. You realize that you could write a JVM, a C++ compiler, a Ruby interpreter. It would take a bit of time and effort. But you could do it. The magic is gone.

And once the magic is gone, you have a different perspective on things. You look at a language like C or Java or C# as just another expression of machine language. You look at a line of C code, and you can “see” the machine instructions that it generates. You look at a line of Java code, and you can visualize the machine instructions being executed by the JVM. There are no mysteries. There are no secrets. There is no magic. You know, if you had to, you could write it all in machine code.

It’s the same with frameworks. If you’ve ever written a web server – no matter how simple that web server might be – if you’ve written the code that listens at a socket, unpacks an HTTP Request packet, generates HTML and packs it into an HTTP response packet, and then writes that response back out the socket; then the magic is gone. You know how to write a web server. And that puts a whole new perspective on any web framework you might be tempted to use.

If you’ve ever written a simple dependency injector, or a simple XML parser, or a simple observer generator, or a simple query generator, then you’ve driven that magic away. You could write a framework if you needed to. Or you could just write the code in your application if you needed to. You don’t need someone else’s framework.

And that puts the framework in a whole new perspective. You don’t need it. And if you don’t need it, it can’t have any power over you. You can look at that framework for what it is: just plain old code – and probably a lot more code than you actually need.

Now you can judge whether the cost of all that code is worth the benefit. Perhaps there’s a simpler framework that will do just as well. Perhaps you don’t need any framework at all. Perhaps – perhaps – you should just write the little bit of code that you need, instead of importing thousands and thousands of lines into your project. Lines that you didn’t write. Lines that you don’t control. Lines that you probably shouldn’t be putting a whole lot of trust in.

My Advice.

Never buy magic! Before you commit to a framework, make sure you could write it. Do this by actually writing something simple that does the basics that you need. Make sure the magic all goes away. And then look at the framework again. Is it worth it? Can you live without it?