Ian Bicking: the old part of his blog

Writing good (dynamic) code

In an article on functional programming (update: link to Reddit copy; for some reason the original is gone). this Python code is declared as bad:

def respond(channel, msg):
    if channel.isValid() and msg.body() == "next":
        return channel.send("A2-B3")
    else:
        return channel.send("bye")

(I've corrected the obvious non-Pythonness of the original code, since that wasn't the point.) The author is unhappy that he doesn't know the value (i.e. implementation) of channel.isValid, msg.body and channel.send. If he knew the type of channel and msg he would know these things. And realistically these types are going to be relatively static, but you can't tell from a localized snippet of code. (Note that type inference doesn't help here at all, since with inference the types will be just as mysterious from simple code reading.)

The problem here is that the code has a language of its own. It talks about things like "channels" and "messages" without specifying what exactly it means. These terms probably are all over the code. And once you become familiar with the code base it is probably obvious what they mean, and tedious to constantly describe them.

This is a common situation in frameworks, though in this case the "framework" might simply be the rest of the code in the application outside of the module or function you are looking at.

It's often a very good tradeoff to ask the programmer new to your code to spend some time familiarizing him or herself with the lay of the land -- the basic ideas that are pervasive in your application, the objects that form the core of it, the words you use to describe its process.

Generally in Python (and elsewhere) we lack good conventions for doing this. Extracted documentation (ala Javadoc) is horrible for this; doctests aren't much better. Interfaces are generally quite good, if you separate the important interfaces from the incidental ones. Narratives and code maps are usually the best. But they often not present, or incomplete, or hidden, or not trustworthy. (Even when documentation is true it may still not be trustworthy.)

We (meaning "we programmers") should try to do better here. We should also be careful about the tradeoff -- adding new fundamental ideas to your code can be a great way to increase the expressiveness and cohesiveness of the code. But it also has a very real cost; it should not be done lightly. It is often better to repeat oneself than to introduce a new metaprogramming construct, a new object type, a subtle polymorphism, or use higher-level functions. I know, it feels cool to do all these things. It makes higher level languages seem justified -- if you are writing code that looks like C, why not write C? It lets you keep from repeating yourself. But it's often not worth it. It's often better to repeat yourself, to write dumb imperative code, to use short statements instead of long expressions, to add extra names to your code, to use lots of vertical space, to use a for loop, to use fundamental types over custom types, to avoid subclassing, to reimplement instead of generalize, to calculate eagerly instead of lazily, to bind tightly instead of loosely, to use functions over methods... all the things that are so often called bad are usually good, because they are usually easy. People overstate their case on these matters because it is hard to keep other people from doing the easy thing when it is the wrong thing. But programming-in-the-small (one function, one line, one simple routine) is best done in the easy way, even if it isn't as exciting.

Created 21 Dec '06
Modified 08 Jan

Comments:

The post you linked disappeared

# Lawrence Oluyede

While it's always been true that the man with only a hammer sees all problems as nails, the man with a toolbag containing a rich collection of function and object-oriented tools can have a tendency to see even the simplest problems as excuses to write a meta-framework that will never be used in any other context.

Or, as people have been saying for a long time now, and in a phrase that I feel could be interpreted as Pythonic:

"Keep it simple, stupid"

This is especially important if we want to enourage much wider use of programming skills.

# Steve Holden

http://yarivsblog.com/articles/2006/12/11/a-general-theory-of-programming-language-relativity/ leads to a "404 not found"

# anonymous

it seems Yariv has unpublished some posts, including the one you mention. But I had read it earlier, and I also raised an eyebrow when he illustrated the "correct" way to write code, which to me just seemed to use slightly longer expression chains with identifier names that i guess were supposed to be more descriptive (they were talking about chess pieces or something). but there was nothing clearer about it at all, if you didnt know those particular names...it did not illustrate any advantage inherent in erlang that couldnt be true for python or most any other language as well.

anyway ++1 on every point you made. when writing code that is to be consumed by others, you have to question every little trick and shortcut you think is cool and/or convenient and insure it has a proper and consistent place in the overall concept. I also try to focus on "narrative" style documentation...since API docs dont say much by themselves. though I do receive some complaints that illustration through example is "inaccurate".

# mike bayer

Doctests can be narratives.

# Michael Bernstein

Google cache link doesn't work for me now.

You can read the original at reddit.

# silly_coward

However, terse-ness has merit in efficiency. We use shortcuts in language all the time. Idioms, contractions (not sure if that's the proper name), et al.

While I agree with the KISS paradigm, sometimes I feel it's getting taken too far in the web-development space. I have no evidence to form an argument, but I do wonder if coding for this level of read-ability will lead to "picture book" code -- code that is overly-simplified to the point of being a hindrance to efficiency.

Maybe I don't have experiences where using OO and "high-level" concepts has been a hindrance, but I do believe that the benefits out-weigh the cost when everyone understands the concepts. I believe there is a sweet-spot of balance between writing complex code efficiently and elegantly while still being readable and maintainable.

Extreme terseness can lead to obfu, but extreme verbosity can also have the same effects on maintenance AFAIK.

It might also be a matter of preference.

Interesting article -- good argument, but I think coding this way is too extreme. Or perhaps I am simply still too perl-ish for the python world, I dunno.

:)

All the best!

# j_king