Jul 13, 2008

Contrasting Programmers

Peering through my RSS feed today, I read an article by Jeff Atwood titled "Monkeypatching for Humans", where Jeff talks about monkeypatching in languages. While I agree with some of his points (namely that people will come up with nasty stuff), he does seem to think that monkeypatching is some demon from hell sent to destroy all of our coding projects. His quotations talk about Ruby monkeypatching, but his descriptions talk about PHP (a language I don't consider capable of monkeypatching, especially when you compare it to Ruby), so there is a bit of inconsistency that indicates Jeff doesn't really know much about either language.
Then I get down to the R's, and read Reg Braithwaite's predicted1 response to Jeff's post: My analyst warned me, but metaprogramming was so beautiful I got another analyst. Here, Reg states that things like monkey-patching and programmers being allowed to tweak their tools results in many failures, but in some successes. Basically the successes brought to us from the freedom are well worth the failures.

I've written on this dichotomy before. In Reg's post, he draws a parallel between this and the Renaissance-age church vs. science debate. Another example from more recent history is the comparison between Soviet authoritarianism and Western capitalism. Jeff takes a more conservative, communist style approach that allowing people to do what they want is bad, and that we should be given orders (or guidance, depending on how you look at it) from up high (aka language designers, super smart computer scientists). Reg takes the other side and says that given the freedom, people will write horrible things - but people will also write beautiful and useful things.

The idea that change is bad, leaders should be the one's taking charge, etc. is an excellent short-term solution. The people who know what they're doing can take charge and lead the rest of us to a good end, provided we just shut up and follow. If you look at history, Stalin accomplished wonders using this approach with the two 5-year plans from 1928 to 1937. He took charge and turned the USSR from a backwards farming nation to a world superpower in 10 years.

Of course, none of us remember Stalin for that.

We must remember that although the people up high are smart, they are still human. They are subject to the problems that come along with being human, like being prone to errors.

The free market outlasted the Soviet's block. Why? I am no historian, but my guess would be that giving people the freedom to pursue what they want, without telling them how to do it allows for a society that is much more adaptable to the change.

The same parallel can be drawn back to programming. Lisp and COBOL came out at roughly the same time. Where is COBOL now? As legacy software on machines for companies too stubborn to get it re-written with something more modern (I'll say with good reason, since they'd probably just use Java or C# or something that will be obsolete in 20 years). Nobody learns COBOL nowadays, unless they have to. Where is Lisp? Being taught to first-year undergrads at one of the most well-respected technical institutes in the world. It seems that the more flexible language has outlasted the not-so-flexible one.

We can lock programmers in boxes all we want, but they will constantly find ways to work around it. They come up with improvements, or replacements, and that is how things evolve. You think we would be doing object-oriented programming if we just kept listening to the up-highs? You think we'd even be using higher-level languages? One thing I like about Ruby is it gives you the opportunity to explore new things, to experiment with new ideas.
Sure. People will come up with bad ideas. Even really smart people. Remember that last time you went out drinking and thought it would be a good idea to keep drinking more? Probably didn't seem like such a good idea the next day.
The bad ideas will usually get ignored, and fade into time. By telling programmers that they probably won't be able to come up with good ideas and shouldn't bother trying, then you are dooming them to a life of programming mediocrity. But if they try something new and fail, and you just "tousle their hair and encourage them to keep trying", then who knows? They may come up with something neat.

The good things however, produced by the nobodies of the computer world (who ever heard of David Heinemeier Hansson or Bram Cohen before they put out their good ideas), that help better the rest of us. There are lot's of things out there that are produced by famous people, however I think that with the vast majority of cases, the good idea is what brings them out of the masses (ie. all of us) to stardom. What's keeping the rest of us from doing the same?

1As I was reading Jeff's post I was wondering what Reg would think of this if he read it.

14 comments:

jc said...

I believe Atwood's point in bringing up PHP wasn't that monkeypatching as it exists in PHP--which is to say, nonexistant--is a bad thing, but a musing on what would happen in the PHP community if monkeypatching did exist.

Given that PHP does seem to be the land of bad hacks more often than not, his conclusion that monkeypatching in that environment would lead mostly to bad stuff seems valid.

Whether the rest of his conclusion is valid or not is debatable, but I don't think his reference to PHP is a valid means of determining that he doesn't know what he's talking about.

Rob Britton said...

You have an interesting interpretation of his article, and while re-reading it, I can see why you would interpret it the way you did. I found myself seeing it the same way.

Until I got to this paragraph:
"You might say that PHP, sans the fundamental dynamic language ability to monkeypatch, is just another crappy Blub language. But there's also a ton of incredibly useful PHP code out there. So it seems to me that the ability to monkeypatch doesn't stop people from producing a huge volume of useful code, even in a kind of.. horrible language."
The first bit is a bit ambiguous. I can interpret that as either "PHP is a crappy Blub language without the ability to monkey-patch" or "PHP would be a crappy Blub language if it weren't for the ability to monkeypatch". The first time I read it, I interpreted it as the latter, the second time the former.
It's the second half of the paragraph that seems to suggest that PHP indeed has the ability to monkeypatch and it doesn't stop people from writing useful code. This is why I think Jeff Atwood doesn't know what he's talking about, as PHP doesn't really have the ability to monkeypatch.

Your comment does get me thinking though, that if PHP had the ability to monkeypatch, would it still be the land of bad hacks? Perhaps the bad hacks were a result of the language not being able to express what the programmer had in mind.
Then again, it could just be the land of bad hacks (although it's shared with other languages too, C and Perl come to mind...) and you are completely right in that giving PHP programmers that kind of power could result in chaos.

Anonymous said...

Nice spamming there, "Kenneth". Too bad blogspot uses REL="nofollow" on all outgoing links.

vwdiesel said...

I think what direction that I lean here is context sensitive. There is always value in my mind in bringing something new to the table or certainly experimenting with an idea to change how certain work can be done. Reg brought this thinking to me when i was working with him at Big Co. I think that there is also value in doing it "carefully", i.e. you may not limit it to a select few, but if you don't then you should make sure that you can isolate the work to prevent adverse effects on other things that you may not intend.

I also think that Jeff is correct in saying or pointing out the monkey patching might introduce some really VERY VERY hard items to debug (it may not have been jeff directly - but one of the follow up comments to his original post).

Like most things that involve great power - with GREAT power comes GREAT responsiblity to use it wisely.

Steve Cooper said...

Lisp and COBOL came out at roughly the same time. Where is COBOL now? ... Where is Lisp?

I believe there's more cobol out there than lisp, and more demand for cobol programmers. Lisp certainly doesn't seem to have whupped cobol's ass.

Worse, both languages are in very small demand; the argument is comparable to 'who has the stronger economy? Liberia or Nigeria?' Both of them are struggling, and it's obvious when you zoom out and compare them to the bigger languages. For every lisp programmer, there is one cobol programmer, 50 java programmers, and 40 C programmers.

I'm using the TIOBE index for these numbers, and I know there are big methodological problems with it, but if it even roughly represents reality, then you have to account for the two orders of magnitude between the lisp economy and the java economy.

Rob Britton said...

> I think what direction that I lean here is context sensitive.

Well it's certainly not a black-and-white issue. There are times when structure is a good thing. In addition to Ruby, I'm also a big fan of C++ (especially when you give it a garbage collection library) for when I have a bigger project to work on.

For a production project, it would be better to work with tools that provide much more structure and discipline, to keep programmers from hurting themselves. We are human after all, and no matter how good a programmer you are, you will still make mistakes. These languages help you fix those mistakes much more easily.

However, if you have a cool idea for something, a language like Ruby is much more likely to let you mess around and try your neat new idea. You could write your own programming language to try this new idea, but it might be a lot easier to just test it out using a language you already have.

So there are places for both camps. My post was to point out that things like monkeypatching and the like are not always bad, even in the hands of people who won't use them properly.

@Steve Cooper: Sure, if you look at it from a purely economic perspective for what is high in demand in 2008, then you're completely right. Knowing Lisp probably won't get you a job unless the interviewer is a closet Lisp lover or something.
For anything other than economic reasons (like getting a job, # of programmers using it, amount of code written with it), Lisp has most certainly kicked COBOL's ass. Why would anybody learn COBOL nowadays? Most likely for their job to maintain legacy software. Why would people learn Lisp? Because Lisp still has amazing features (like their macro system) that let you think outside the box. New programmers - myself included - still crack open Lisp books and go "oh my god" at what it can do.

Steve Cooper said...

Sure, if you look at it from a purely economic perspective for what is high in demand in 2008

But economics may be a good way to judge programming languages; it represents the ability to deliver useful working systems on real machines for real purposes. Stuff you can sell. Lisp doesn't sell; that suggests it's not good at delivering real systems.

I do agree that it's much better for a programmer to learn lisp than to learn cobol, from the point of view of learning new techniques.

On the other hand, it's not an either/or proposition.

If you want to use common lisp to learn, say, functional programming, I think you're better off with a real functional language like Haskell or F#, which support features like automatic function currying and type inference and easy partial application.

Or, in terms of delivering real systems, again I don't think lisp beats either static OO/functional hybrids like C#3 or scala, or a well-designed and supported dynamic language like python.

I've found the only thing CL does that other languages don't do is macros; scheme has continuations. But I never quite figured how these give you a big advantage.

Rob Britton said...

> But economics may be a good way to judge programming languages; it represents the ability to deliver useful working systems on real machines for real purposes.

I'll agree with you there.

> On the other hand, it's not an either/or proposition.

Again, I'll agree with you, but for the purposes of my article I wanted to compare two very old languages.

> a real functional language like Haskell

Careful there. I wouldn't want an angry Lisper to start flaming all over my blog! I think the word you're looking for is "pure".

> But I never quite figured how these give you a big advantage.

Continuations, not sure. Then again, I haven't worked with them enough to answer that.
I can see macros as very powerful. It's basically the essence of my original post, it provides the programmer freedom to tinker with the language itself.

Steve Cooper said...

[of lisp] I think the word you're looking for is "pure".

Nah, I meant to say 'real.' ;) What I really meant was, there are languages that seem to go further in the pursuit of functional goodness. (I sorta want to say 'functionality', but I hope you know I mean.)

It seems to me that common lisp doesn't really require you to be functional or pure. You can write very procedural lisp; looping and counters and setting variables all over the place.

Sure, you can also write lambdas and pass closures about and such, but so can almost everything else out there. We live in a world where even VB has closures and lambda expressions. (along with ruby, python, C#, and javascript.) Lisp's ability to support functional programming isn't much better than a lot of other languages.

It provides the programmer freedom to tinker with the language itself.

Yeah, the language tinkering is pretty sweet, and I like the way that you can add new paradigms with enough macro-fu; stuff like CLOS. Having a language that can _become_ object-oriented after years being otherwise is pretty nice.

I guess the key idea is that you want to be able to write the next version of your language in the current version. So given language X, you can write language X+1 using mixins or monkeypatching or hijacking the parser or whatever. Cobol was never gonna give you than, and lisp's had macros for a long time.


Are there languages that have succeeded with this? Are people taking these patches and folding them back into the core language? I think lisp's problem is that they aren't. The common lisp standard hasn't been updated for nearly fifteen years. Common lisp isn't evolving.

I think for languages to evolve, in the Darwinian sense being discussed here, you need two things. The first is random mutation; monkeypatching and macros certainly allow that. This allows us to write lots of little rubies, or lots of little lisps. The second essential piece of evolution is ruthless destruction of the unfit. That's the part that's needed to get actual evolution, rather than a million unfit mutants.

Behold languages with 83 different ways to create a GUI, every one of them incomplete and badly documented, or fifteen different string classes, or your choice of four slightly different regular expression engines...

Rob Britton said...

> It seems to me that common lisp doesn't really require you to be functional or pure. You can write very procedural lisp; looping and counters and setting variables all over the place.

Yup, that's what happens when it's not a pure functional language. Things like loops and counters are side effects of having side effects.
You can also write very procedural code in Java or Ruby or Python, yet we still call those "real" object-oriented languages. Being able to use another paradigm with a language doesn't necessarily destroy it's "real" status as another paradigm. Simply makes it impure. Which is why I suggested you use the word "pure" instead of "real". Also I don't think a Lisp programmer would take it very well if you said that Lisp wasn't a "real" functional language.

> Lisp's ability to support functional programming isn't much better than a lot of other languages.

And I guess since all those languages you mentioned also support things like inheritance and polymorphism and all that other OO-goodness, we can't call Smalltalk a "real" object-oriented language anymore.

Steve Cooper said...

Lisp certainly allows you to write in a functional style. Things like creating closures, assigning them to variables, passing them as parameters to other functions, and lambda expressions. I'm happy to accept that as a definition of a real functional language.

The point is, that also means you have to say 'Visual Basic, Perl, and Javascript are real functional languages,' and I didn't think that was what you were trying to say. It sounded like you were suggesting that CL had _more_ language features supporting a functional style than those languages.

I think lisp had an early lead, but the state of the art has moved on somewhat; languages like Haskell have raced on ahead, and older OO and procedural languages have had functional additions bolted on, catching up with lisp.

So I think there are now three groups;

- top-of-the-range luxury functional programming languages with pure functions, lazy evaluation and tail recursion, like Haskell.

- the middle-of-the-range languages supporting closures and lambda expressions, like common lisp, VB, Perl, Python, Ruby, C#, D.

- the laggards like Java, C, C++, and PHP.

Does that sound like a reasonable split?

Rob Britton said...

> It sounded like you were suggesting that CL had _more_ language features supporting a functional style than those languages.

Not sure where I said that. I was under the impression I was comparing Lisp to COBOL (Lisp certainly supports FP better than COBOL, I think we can agree on that). Seems like we've deviated from that quite a bit.
I did mention that Common Lisp can still make you go "wow", but that's simply because it's macro system is really cool.
Yes, I compared Lisp to Haskell on the notion of purity, but I think we were agreeing on the same idea and using different words for it.
I didn't however, compare Lisp with any other programming language based on its support for functional programming, though from experience I find that it's easier to program in a functional style in Scheme than it is in Ruby.

> Does that sound like a reasonable split?

Sure, if you want to view functional purity as a goal. Not sure why you're viewing things as a race though - I came to this conclusion since you're using words like "luxury", "laggards" and "catching up". This is an accurate goal from the perspective of a Haskellian (is that the right term?), but not necessarily from other viewpoints. We could change the goal to how much security a programmer has (which I suppose is another goal for Haskellians). Java is definitely up there on that one. Or we could look at it from a freedom perspective. Surely Common Lisp and Ruby are far ahead on that one. Or an efficiency perspective: C and C++ are still kings there. So basically everyone is running in different directions on a very multi-dimensional grid, we probably shouldn't be comparing them on a single axis. On a side note, I'm still not certain what PHP is good at, maybe being a middle ground?

My original post was simply talking about how freedom allows for creativity to flourish. Whether that's happening in the Lisp world is irrelevant - I do know that it's happening in the Ruby world, just read Reg Braithwaite's blog. And whether it's something that companies want is also irrelevant. I was just saying that people like Jeff Atwood shouldn't demonize the freedom in languages simply because it allows people to do nasty things.

Steve Cooper said...

Hi. Yeah, I think we're basically in agreement about the way things are. Sorry if I read the wrong things into your posts. I blame the internet. ;)

I think the discussion about freedom is the more interesting one, too...

I suppose the monkeypatching debate rests on a question of whether it will provide a net benefit over the long haul, or prove a hinderance.

Can we see lisp's macro system as an analogue for ruby's monkeypatching? If so, does the 50-year history of lisp have any lessons for ruby?

Rob Britton said...

> Yeah, I think we're basically in agreement about the way things are. Sorry if I read the wrong things into your posts. I blame the internet. ;)

Darn those internets. No worries ;) I was just a little confused at some points as to why you were saying what you were saying.

> I suppose the monkeypatching debate rests on a question of whether it will provide a net benefit over the long haul, or prove a hinderance.

It might be a hindrance if you're using it for production code, where failure to full understand the impact of your monkeypatching can have drastic effects.
On the other hand, if you're monkeypatching on other stuff just to mess around, I think it would be to people's benefit.

> Can we see lisp's macro system as an analogue for ruby's monkeypatching? If so, does the 50-year history of lisp have any lessons for ruby?

That's a good question, and not one that I have an answer for. I guess we'll find out ;)