Get weekly top stories updates!
Several recent discussions with both reasonably intelligent developers and with a couple zealously evangelical folks (with respect to a language I won't name) has given me some impetus to think about the way stuff gets done; why choices are made the way they are, and what choices are appropriate for given scenarios.Specifically, I'm talking about programming languages and considering them in such a way as to not think of any of them as holy grails or having unquestionable infallibility. This is the stuff of holy wars and long, stupid flame wars that have no measurable or useful outcome, other than perhaps a contribution to the ever increasing entropy in the universe in terms of the heat given off both by the contributors and all the machines built to enable their wasted communication. Frankly, I'm bored with that (and in fact, if a flame war should erupt out of this document, I refuse to participate), and I don't care what someone's favorite programming language, editor, email client, citrus fruit, web browser, operating system, or barnyard animal happens to be. [smalltalk, vi, pine, oranges, mozilla, freebsd, sheep]
Many development organizations are faced with a need to meet tight deliverable schedules with minimal resources. They need to manage large teams to develop complex yet reliable applications. The rest of this document should be taken in the context of such an organization, which in the modern business world almost certainly means leading some kind of object-oriented programming methodology. We're not talking about mailing a webmaster with the output of an HTML form here. We're talking about lots of people working on hard stuff that has to work right in a short amount of time.
That having been said, we should be able to look at languages and platforms in an agnostic, detached sort of way, as we'd look at a box of our playthings that we enjoy throwing at our kid brothers or sisters. Or, in the case of those who may have had the unfortunate circumstance of growing up, a box of tools.
In my toolbox, I have a disorganized mish-mash of tools I've used at one point or another to work on my current and former car. Now, I'm a Ford owner, so naturally some tinkering from time to time is required. In my toolbox, I have hammers, screwdrivers, Torx drivers, wrenches, an interocitor, and a specialized tool for removing a 1986 Mustang LX's thick-film ignition module.
The great thing about these tools is that they're not only useful for working on my Mustang. When something breaks inside my condo (oh, they joys of home ownership), I can bring some tools into the house and go to work at making things far worse than they were to begin with before giving up and calling a professional. The screws that hold my vertical blinds up above my patio door can be turned with the same phillips screwdriver that I used to unbolt the bracket that holds my air filter in place.
But another interesting thing about a tool assortment is that some tools just won't work at all for a given situation. I cannot use a ratchet wrench with a 7/16" socket to unscrew my blinds.
Even more interesting is that there are some tools that aren't intended for the task at hand that can be adapted or outright forced into doing the job. I can take a tiny flathead screwdriver and jam it into a phillips screw, and if that screw isn't terribly tight, I can turn it loose. I've done this before, because as I say, my toolbox is terribly disorganized and sometimes I can't find the right tool.
Futher, there are some tools that are quite similar to what I need for a job, but they're not going to work because they're too big or too small.
Programming languages and their supporting platforms are a lot like these tools in my toolbox. There is a time and place for practically everything in my toolbox, or I wouldn't have bought the tool to begin with. There is a time and place for assembly code and machine code. There's a time and place for LISP. How you choose a tool depends on how closely it fits the task at hand. I CAN use that flat screwdriver to unscrew my blinds, but I'm going to have to hold onto it so hard it's going to hurt my hand, and chances are pretty good it's going to slip and I might cut myself or strip out the screw.
I CAN force a square peg into a round hole by beating on it relentlessly with a hammer until I shred off the corners and jam it into place.
So it is with development. Why don't most of us write our CGI scripts in C++? Because it doesn't make sense. C++ has fairly good OO support, and we like OO. C++ is fast, and we like fast. But C++ takes a long time and much greater skill than we can easily hire for at our respective companies and recruit for our various and sundry projects.
Something similar can be said of C. It's even faster than C++ in most situations. But why don't I do object oriented programming in C? I CAN do it. It IS possible. I can create a struct with some function pointers and some data members and write a preprocessor macro to implicitly create a "this" pointer into each function call. If you're a C++ coder, you're reading this and thinking I'd have to be off my rocker to want to do this. I assure you I'd never want to do this. My code would become unreadable in short order, and I guarantee you I'd be mallocing the wrong amounts of memory and forgetting to free pointers, or freeing at the wrong times and causing myself all sorts of trouble.
Both C and C++ could take advantage of Apache's CGI environment, and there are libraries to parse up the environment and stdin to give easy access, but we almost never do this. Again, I'll summarize the reasons why:
In my opinion, a lot of this extends to perl as well. You CAN make perl do OO. Guess what: you do this by making a hash with some function pointers and some data members. Sound familiar? Some preprocessing happens to implicitly pass you a "this" pointer. See what I'm getting at? Worst of all, the language does not enforce any OO requirements.
Why do you suppose it happened that C++ came along when C was out there and was more than capable of doing OO tasks? Like I said earlier, you can make C do OO for you with a struct. You could be very careful to make sure that you never violated any OO rules with your own code. You could be even more cautious to make sure you didn't read any data members that were meant to be private, and you might well succeed.
But how much easier is it to succeed with a phillips screwdriver than a flathead one when you're turning a phillips screw? When I screw up (no pun intended) writing C++ code, and I often do, the compiler complains quite noisily about it (in fact, often over several pages if I'm using the STL). It won't let me do things I'm not meant to do. I can now divert those neural pathways I was having to use to be super-cautious not to break any of the rules I set down for myself to doing something useful, like developing code or watching porno.
When I read a data member of a perl hash that I'm not meant to read, what happens? Absolutely nothing. I get to read it. If I forget that I'm supposed to shift off a "self" pointer and use that to call a member of my object, what happens? I spend half an hour trying to figure out why I didn't get a value out of my assignment before realizing my stupid mistake.
When I try to read a data member of an object that I'm not meant to read in Java, what happens? It won't even compile. The compiler gripes that I'm trying to read a private member of an object for which I don't have security. I don't have to worry about shifting off a "this", and in fact, if I forget to call this->foo, and call foo instead, it doesn't matter, because this-> is implicit, as I am a real object, not a reference to a hash.
I'm not going to bore you to tears with linguistic comparisons, because that's not my point at all. My point is that there are languages and platforms for tasks and circumstances.
Many organizations are facing serious trouble scaling development. While some developers have godlike powers for writing code, and do have the ability to watch their structs, we must deal with the reality that not everyone out there is as clever. This fact becomes painfully obvious almost every time I'm asked to interview someone. To think that an organization can go on, always hiring at one single skill level- Zeus, Wotan, Odin, or Jupiter- is not practical or realistic. Even among my peers, we're not all Zeus, although I like to think of myself as a Wotan because I think "Wotan" has a nice ring to it. Wooooooooh-Tannnnnnn.
Organizations need to make their efforts scale if they wish to succeed. Has Alan Kay ever taken over the universe all by himself? Of course not. Has Larry Wall, Linus Torvalds, Kirk McCusick, Jordan Hubbard, Steve Jobs or Bill Gates taken over the universe single-handed? Nope. Yet, some of these guys are Odins and Thors, are they not? To the extent that they have taken over markets and microcosms, they have done it with the support of scalable teams comprised of folks with different backgrounds, skillsets, functions within the enterprise, and interests.
I've seen teams that had groups with entry-level folks, some mid-level folks, and a few Jupiters here and there. Why aren't there entry-level folks in every organization? Because they can't be hired. They can't be hired them because they can't ramp up to Mount Olympus environments without their having the ability to make lightning and thunder with their bare hands.
And why is that? Because while Zeus is strong enough to unscrew my blinds with a nail file, I don't have a screwdriver I can hand to a mere Hercules (or Xena if you prefer). And what happens as a result? Zeus has to answer a gob of emails and handle his own quick fixes that could have been shouldered by a simple Grecian.
How do organizations get themselves out of this bind? Look at the circumstances and consider the tools. Suppose we want to build a scalable infrastructure with maximum code reuse, high reliability, and rapid development time to produce a product or potentially contribute to the open-source community. We also want to let Zeus and Thor get together and figure out the impossibly complex problems while Xena and Hercules can hack out some reports and fix Wotan's sloppy code.
The thing about Hercules and Xena is that they're both pretty strong and can kick a rendered monster's ass pretty readily, but they're really not quite as bright as Wotan. And that's ok, because after all, they're just human. They're gonna make some errors from time to time, so we want some built-in fault tolerance and quick feedback when faults are introduced.
And you think we want to do this in perl? In my opinion, that's as crazy as doing OO development in C. I don't want Hercules and Xena to have to think about function pointers in hashes, although it comes more naturally to me with my assembler programming background. I don't want to trouble Hercules with thinking about program counters. I don't want to take Xena away from her ass-kicking to make her think about shifting off self references and remembering to dereference them to use the right function pointer to make sure that the right part of the hash is being accessed to ensure that the correct data members of the hash are used. Yes, I can do that. Do I like using an awl to turn a screw? Hell no.
I'm secure with the fact that I could code up a CGI in Sparc assembler if I really had to. I have an analytical mind and I'm a quick learner. I could do it in C++ or C. I can do it in php (like this site for example). I can do it in perl. I have the powers. I can make thunder and lightning with my bare hands. It is an excellent party trick.
But if I don't HAVE to do it that way, even though I'm certain I CAN do it that way, why should I? Why jump through hoops and get a pair of pliars to get more leverage on that flathead screwdriver just so I can use it instead of going back out to the garage to get a phillips like I should have done in the first place?
I believe the right development direction for the circumstances I outlined above is Java. Period.
Java is the phillips screwdriver to unscrew my damned blinds. It's been sitting in my garage buried underneath a socket wrench and a crowbar for a while, waiting to be picked up and used. Java will tell me when I'm wrong. Java is OO by design. Java is not a hack using function pointers in a struct. Java is not a hack using function references in a hash and passing in implicit elements in a list to reference those function references. It is an object oriented language. It was born that way.
And more important than its relative merits by design- by far the most important characteristic of all- is that this is the tool that fits the circumstances. This is not a flathead screwdriver. If I had a flathead screw in my blinds holding them up to the wall, then a flathead screwdriver would be appropriate. But that's not the situation.
We need to scale development. We need to do something about support. We need to be able to quickly handle out-of-plan one-offs. We need to be able to hire at different skill levels to scale. We need to let Zeus, Wotan, Odin, and Jupiter work on the hard stuff- the core components- so that Hercules and Xena can use those components to kick ass. We need something that tells Nick that he's a bonehead when he tries to do some form of illegal operation. We want a solid object-oriented foundation where it makes sense. We want to leverage a large base of existing components. We want maximum code re-use. We want reliable unit testing. We want exceptions that force you to handle them. We want black boxes that work easily into an XP model.
From my chair, the pathway is clear and obviously pointing toward Java as the right tool for the job and circumstances.
Having said that, I am fully aware that many organizations have a huge existing base of code in other languages, and they will be in need of developers and code maintenance for that code for years and years to come. I'm not suggesting you go off and completely get rid of perl, C, or C++, period, end of line. At some point, though, you have to ask, "do I continue on using this flathead, or before I move on to that next screw, do I go out to the garage for a phillips?"
I think we need a phillips.
That is all.
---Nick
HTML generated using XSLT for type-5 browser (HTML 2.0; text-only; no tables; Lynx compatible)