May 9, 2010

Writer versus Constructor

What's the favorite toy from your childhood? For me, both my sisters and pretty much everyone I know that would be Lego. If you could only afford it (and in the times when I was a kid, that wasn't so easy in the post-soviet Poland), there was no greater fun, than the joy of unlimited freedom to create whatever you can only imagine. And the fact, that you had limited resources wasn't a real obstacle. It was a challenge.

Nearly all the programmers I know, fell in love with programming because of the same reason. To be able to put pure ideas to life, to create something meaningful out of nothing. Truth is, no other matter is so flexible, as the stuff we work with.

We are developers because we love to construct things that work. To give soul to the machine. To make it act on our behalf. It's like magic.

That's why it is so difficult for us to understand, that a real software craftsman is a writer, not a constructor.

Uncle Bob is talking about it at the beginning of “Clean Code”. When you are writing code, you are actually reading a lot more. How is that possible? Let's have a look at an example: you have a project going, and you take a new feature from the Scrum/Kanban wall of features. And you:
  1. read the code to find a place where putting some more code will give you the result you seek
  2. read the code to better understand the surroundings, to eliminate potential side effects of your changes
  3. write the test and the code that does what the feature is expected to do

You can start with an acceptance test first, but that only changes the order, not the fact, that the proportions of reading to writing, are always in favor of reading. Big time.

So, if reading takes so much time, how important is to make things readable?

People are working hard to learn how to write faster, how not to use mouse in their IDE, they memorize all the keyboard shortcuts, use templates and so on, but the speed up is not significant in real work. Why? Because we are only writing code 1/10 of our time. The rest is spent on reading and thinking.

A good craftsman is a good writer, because he makes the code readable, easy to grasp, easy to understand. There is a huge shift in mentality, between a constructor and a writer. Above all, the constructor's goal is to make things work. The writer's goal, on the other hand, is to make things easy to understand.

The question is, who are we writing code for? The computer? Hell no. If that was true, we would be still writing in an assembly language (or maybe even in a machine code). The whole point of procedural, functional, object oriented languages was to make it easier for us to understand the code. And that's because we don't write the code for the computer.

We write it for other programmers.

To make the shift in mentality easier, let mi show you the differences in mindsets, between the constructor and the writer.

The Constructor


The constructor is in love with technology for the sake of technology. He likes to “technologically masturbate” himself with new toys. He thinks that simplicity is for pussies, the real thing is always complex. He never removes anything, always adds more. He doesn't care that he cannot understand how his earlier solutions work, if they work why would he want to change them? He creates monsters like EJB1/2, that can do pretty much everything, but nobody is able to handle them. The he writes software to be able to use/confgure the software he has written before, because it's already too complex for anybody (maybe except for him) to understand how to use it directly.

A bigger framework is a solution to his every problem. And even if it's a new problem, he tries to modify his beloved one-to-rule-them-all tool, to be able to solve it. He is dreaming about the day, that he will have a single, big, multipurpose, futuristic wrench that works as if by magic, and does everything, from printing log files to saving the planet.

The constructor works best alone. He gets angry at people that cannot understand his programs in a second. When he works with other programmers, he is always afraid, he doesn't like others to play with his tools. When they try to do pretty much anything, they always blow something else up. Because of unforeseen side effects, a small change can devastate days of work. And it happens a lot. It gets messy, so he hates to work with others.

The Writer

The writer reads a lot, so he wants to make his code as readable, as simple as possible. He learns stuff like DSLs, patterns, eXtreme Programming, to make things easy. Easy is his keyword. He cares less about frameworks. He usually knows a few languages from different worlds, because he believes there is no single silver bullet, and different solutions are better for different problems. His code has few comments, because it doesn't need them. His code is self-documenting. His code is expressive. His code is simple, simplicity is his main value. Brilliant things are simple.

The writer always thinks about his reader. He walks hand to hand with his readers. He guides them, he cares for them. He never leaves them in the dark. His skills are in communication: he wants his intentions to be understood.

The writer works like a sniper. His changes (whether bug fixes or new features) are minimal, but the effects are exactly as expected. He never does Shotgun Surgery. He doesn't violate DRY. He is a precise man and he works with a scalpel. His code is side-effect free, simple and readable, so he knows where and how to hit. He knows what the effects will be. He keeps accidental complexity low.

The writer is agile. He doesn't set up traps, and he doesn't fall into traps. He works hard to master basic skills. He believes that without those basic skills, no framework can save him anyway.

The writer likes to work with other programmers. He is using pair programming and code reviews to make sure that his code is easy to understand by others. He wants to have another mind watching his back, and catching him when he falls. He is supportive, he is friendly. He understands that no man is an island, and that the quality of his work will be measured by the number of WTFs shouted by other developers.

A good craftsman is a good writer.

And you know what one of the most successful writers of recent times, Stephen King, says?
That he's only a craftsman.

PS: all the pictures are from Fallout games.
PS2: I've failed at giving appropriate credits to the author of the concept of programmer as a constructor. Let me fix that right away: the source of the idea that a programmer as a writer has opposition in programmer-constructor comes from a post by Andrzej Szczodrak that you can find in here

11 comments:

  1. I can't find words to admire Your thoughtful post, so I put it simple: BRILLIANT.

    This is a deep analysis of the source of most problems in software development.

    And Pipboy pictures - awesome and suggestive illustration of the content (especially headshot:)

    ReplyDelete
  2. Thanks, I'm glad you like it.
    These thoughts are part of the presentation about Software Craftsmanship, that I'm showing to Warszawa JUG on the 1st of June. I've already run a preview at work, and someone asked me to make it public for further reference. I've decided that pictures and bullet points are not going to be informative enough, so I'm turning the most usefull part into blog posts.

    ReplyDelete
  3. http://the-javu.jogger.pl/2010/02/16/real-life-programming/

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. It remembered me mine journey - from constructor to writer. Nice and marvellous!

    ReplyDelete
  6. I've read the article twice or more and can't get it. In my opinion your description of the constructor is unfair. I would call it 'bad programmer' or something like that, but not the constructor. Why someone like you described should be called a constructor? We all (programmers) are constructors at our work. We do different things - some of us focus of inventing things (mentioned EJB 1 or quite good Hibernate), some others just use them to solve some business problems - but in both cases we should care about quality.

    I want to be a constructor but not as you described. When solving similar problem again generally we should reuse previous solution. It looks obvious - we will save a time. Also because it was already done so it's probably known by others. But i think it's always good to think about the problem again, maybe we can provide better solution this time. Of course it should be balanced but its needed. Otherwise we would not move forward in our (software) evolution.

    btw, what i also have found a little misunderstand is readability of the code. There are people which try to make any written code self-speaking, like prose, e.g. they use 'given, when, then' form for any test they create, to be understand by any programmer or even my mom. That's not the point. First of all code should be understandable and not necessary readable in form of prose. Second of all - not for some possible programmer who will look on it but for people who are really interested in it, e.g. we should not try by hard to make some algorithm implementation readable for everyone, even junior programmer. It should be understandable for people knowing required things, like used math or advanced language constructions.

    Anyway, you are right with the description of how we should code, but i think the categorization is inaccurate.

    ReplyDelete
  7. @alider

    Let me explain why the opposition that I've taken from http://the-javu.jogger.pl/2010/02/16/real-life-programming is so valid to me.

    Nine years ago my goal was to create software that worked, and I would sacrifice anything to get there. That made sense to me, my “clients” wanted stuff that did something, after all.

    I was a constructor, because my goal was to write code that the machine would “understand” (execute).

    During next few years I've learned, that working with overcomplicated, puzzling, unreadable software that “just works”, is a nightmare. And it takes forever to add/change anything. My clients had to pay more and more, while my work was harder each day.

    Now I am a writer, because my goal is to write code that other programmers can easily understand and work with.

    The funny thing is, that the more readable the code is for other programmers, the better it runs on the machine (lower number of bugs). It's also waaaaay cheaper for my clients, because it takes less time to do anything.

    Ask yourself: who are you writing the code for? The answer is the difference between a constructor and a writer.

    As for the given-when-then mantra: readability IS the key, the code is always telling some story. Good code looks a bit like good prose, because good prose is also readable. You say that it doesn't matter whether it's readable for “some possible programmer“, but guess what, the code you write today is going to be maintained by “some possible programmer” tomorrow. Why would you make it difficult for him to understand? Remember that you are going to maintain/use/extend someone's code as well. Someone, who right now may consider you “some possible programmer”.

    ReplyDelete
  8. The problem is that your definition of the constructor is quite different then the one here http://the-javu.jogger.pl/2010/02/16/real-life-programming. I would agree with Andrzej and his definition which at the end is positive - i want be like Linus:). Do you really think that Linus fits to your definition of the constructor? i doubt.

    Why a code in form of prose isn't always so good - http://blog.objectmentor.com/articles/2009/12/19/the-polyglot-tester

    I don't what to make my code to be difficult to understand for anyone. I really want something opposite. I've just found that overusing GWT or fluent interfaces doesn't always lead to better, easier to understand code. I've bean working with multithreaded code recently. Java 1.5 provides really cool stuff in this area hidden behind quite specific apis which mostly aren't like a prose. Some programmers in the team when writing a code started to wrap calls to those apis with it's own methods giving them names describing what is going on behind given call. At the end it was really like a prose but i found it not so nice. The code was just unnecessary big. Team members were suppose to known Java 1.5 concurrency related apis really well and for most of them it wasn't needed. Maybe it would be nice for someone not so familiar with those apis, maybe. The code just requires given knowledge and then is really understandable.

    ReplyDelete
  9. @alider: I do not know Linus personally, hard to say who he really is :)

    You know, it's a funny thing that you mention concurrency as an example of things that people want to oversimplify by meaningful names and verbose interfaces. A few weeks ago, at GeeCON 2010, there were two lectures about concurrency in Java using Erlang style (Actors and Agents: Akka Framework for example). Both stated, that 90% of concurrent code in Java works by accident and that the problem of Java is a wrong abstraction of concurrency (the way we think about it). Uncle Bob also spent ¼ of Clean Code just to show the problem. Taking that into account I'd say that you are quite lucky to be in the 10% of programmers that do not need a better abstraction, but you definitely should not expect all your colleagues to be in the group. Remember, you are not your own reader.

    ReplyDelete
  10. Nice post. But,

    Do we really need so much emphasis and give new names for very old problems ? You can be a bad driver or a good driver (responsible one). You can be a bad programmer or a good programmer.

    If a programmer works in a team with any code-sharing practice (pairs, code review) or even has to change someone-else code she will quickly became a dedicated "writer". If not - it probably means she does not have the potential to became a good programmer at all.

    As for the concurrency: this is this kind of stuff you have to understand WITHOUT any technology or language, far before you write concurrent or distributed code. Abstraction should come first. You will probably get funny answer asking programmers for the definition: "what does it mean for two programs to run concurrently?".

    Tomek

    ReplyDelete
  11. An ideal example of a 'constructor' is Linus Torvalds, (the most known Linux kernel programmer). Especially his statements about the 'usefulness' of low-level C and 'uselessness' of high-level languages like C++ are completely ridiculus.
    - http://www.dzone.com/links/r/linus_torvalds_vs_c.html
    - http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918
    - http://warp.povusers.org/OpenLetters/ResponseToTorvalds.html

    IMO, 'constructor' is not a perfect name for these kinds of programmers. 'hacker syndrome' mentioned in one of the links above is a better name.

    ReplyDelete