Pensieri di un lunatico minore
Other’s muse on the absurdity of those obsessed with speed. Like a meth addict, the use any possible rationale to justify their unhealthy obsession. My favorite is:
“What do you mean my algorithm runs at O(n!)? It’s twice as fast as yours with this small test set”
The number of times I’ve seen someone rant about how fast their new algorithm is—when running on an irrationally small sample—is uncountable. As I’ve said a million times:
- Make it work
- Make it right
- Make it fast enough
- Profit!
Seriously. Don’t put things in the wrong order, or you’ll never get anywhere.
No thoughts
Scott Dunlop writes about the transition of his work from Mosquito Lisp (MOSVM) to Wasp Lisp. One of the thing that I wanted to point out about my interest, though, was that it wasn’t strictly about it being a Lisp dialect. It’s more what that brings with it: flexibility. It’s a tight, very small, and reasonable performing implementation that’s very flexible. It also comes with, to steal a phrase from Python, “batteries included”. This makes developing neat applications nearly trivial.
No thoughts
So today I was trying to debug some code, and for some reason, I couldn’t see what was wrong for a few seconds. Then, I realized that I had been typing lambada instead of lambda. Time to stop coding for the day.
No thoughts
One of the great things about the intertubes is that it allows people of all capabilities and skill sets to shoot off their mouth and make fools of themselves. Recently, Sho Fukamachi demonstrated the truly epic capability to not only miss the entire point, but demonstrate a nearly bottomless lack of knowledge of the area of virtual machine technology and what actually represents “state of the art”. Oddly, it reminds me of me when I was 20. Fortunately, Patrick Collins straightens it out. Oh, and I’m quite aware of object databases in the public eye that are nearly 1PB compressed. There are some in the intel community that even larger and more complicated.
It’s amazing how some communities think that they’ve actually had an original idea. There are almost no original ideas left. The only reason anyone thinks their “idea” is original is that they’re simply oblivious to the decades of work of others.
2 thoughts
It’s amusing as all hell to watch some people blow up about the MagLev Ruby implementation. Personally, while I find Ruby interesting, the performance is embarrassingly bad for a lot of problem domains. That doesn’t mean it’s not useful, it just means it’s not as useful as it could be. I’d like to take a couple comments that Charles Nutter made and just “observe”:
First off, they demonstrated its distributed object database automatically synchronizing globally-reachable state across multiple VMs. It’s an amazing new idea that the world has never really seen…
except that it isn’t. This is based on existing OODB technology that Gemstone and others have been promoting for better than a decade. It’s cool stuff, no doubt, but it’s been available in Gemstone’s Smalltalk product and in their Java product for years, and hasn’t seen widespread adoption. Maybe it’s on the rise, I really don’t know. It’s certainly cool, but it’s certainly not new.
There are only a tiny handful of companies in the world who can show production object environments of that scale. Gemstone and Objectivity being two of the most successful. Both are rooted in the Smalltalk world originally, though offer other products to most of their customers. What I find troubling is the dismissive nature that Mr. Nutter has about the problem domain. The fact that most people worship at the relational temple doesn’t mean that it’s actually a good idea in many cases. Some of the most complex databases in the world are object databases. There’s a reason a huge percentage of Objectivity’s money comes from the intelligence community. Data fusion is everything.
Except that these are results reported entirely in a vacuum. Whether this is fib following the “rules” of Ruby is entirely an open question. Whether this is method dispatch adhering to Ruby’s call logic is entirely an open question. Whether this is a while loop using all method calls for its condition and increment steps is an open quesetion. Because the Maglev guys haven’t started running Ruby tests yet. Is it Ruby?
Well, once someone actually defines what Ruby is we can have that discussion. One of the most frustrating aspects of Ruby is that there is no actual language definition. There is only a language implementation, several at that, and if I recall correctly all have had to reverse “engineer” the language from the implementation. This makes discussing “is it Ruby” a laughable prospect, and Mr. Nutter should know that. Let’s examine “some words of his from just a few weeks back”:
Compatibility is hard. I’m not talking a little hard, I’m talking monumentally hard. Ruby is a very flexible, complicated language to implement, and it ships with a number of very flexible, complicated core class implementations. Very little exists in the way of specifications and test kits, so what we’ve done with JRuby we’ve done by stitching together every suite we could find. And after all this time, we still have known bugs and weekly reports of minor incompatibilities. I don’t think an alternative implementation can ever truly become “compatible” as much as “more compatible”. We’re certainly the most compatible alternative impl, and even now we’ve got our hands full fixing bugs. Then there’s Ruby 1.9 support, coming up probably in JRuby 1.2ish. Another adventure.
So before the stones are cast, perhaps the house should be repaired?
Then there’s Maglev. Like the other impls, I’m excited that there’s a new possibility for Ruby to succeed. A high performance, “scalable” Ruby implementation is certainly what this community needs. But unlike most of the other implementations, it seems like Maglev is pushing performance numbers without compatibility metrics; marketing before reality. Am I far off here?
Here’s the thing. Maglev is a new language on top of an existing VM. One that has over a decade of hardcore production use, something that even Java can’t really claim. There’s a wide gulf between putting a new syntax on top of an existing VM architecture and building a new VM. VMs are intensely hard, and only a few people in the world are truly good at them. Dynamic VMs all derive from Smalltalk, and even Java is having to glue on all sorts of silly doo-dads to try and pretend it can support it without huge cost. Ruby is very much Smalltalk in different clothing, and therefore I would expect Ruby to run at near Smalltalk speeds once you clean up some pieces. I know the great wizard had a Python implementation running on a Smalltalk VM, alas it never got released.
The truth is that not all of these optimizations are kosher right now. Removing the ability to override Fixnum#+ certainly makes it easier to optimize addition, but it’s not in the spirit of Ruby. Removing frames may be legal in some cases (like this one) but it’s not legal in all cases. And of course I’ve blogged about how Thread#kill and Thread#raise are broken, but we have to support them anyway. On and on we can go through lots of optimizations you might make in the first 100 days of your implementation, only to back out later when you realize you’re actually breaking features people depend on.
Features, or design errors? Because if it’s the later, then breaking them is the best thing that can be done. The refusal to fix them in the past is simply a weakness. The totem of backward compatibility is what gave us Windows Vista.
6 thoughts
In my continuing adventures getting back to using Emacs, I was working on tweaking the color theme that I use. While it’s based on someone else’s originally, I’ve made quite a few minor changes. Somewhere along the line, I messed it up and started getting all sorts of strange errors that made no sense. They couldn’t possibly be wrong.
Here’s the old one:
(defun color-theme-charcoal-personal ()
(interactive)
(color-theme-install
'(color-theme-charcoal-gray-personal
((background-color . "Grey15")
...
And here it is, fixed:
(defun color-theme-charcoal-personal ()
(interactive)
(color-theme-install
'(color-theme-charcoal-personal
((background-color . "Grey15")
...
Do you see the difference? No? Look carefully.
It seems that if you name the defun differently than the first element of the first list passed to color-theme-install, it goes wonky. Unfortunately, the debugger wasn’t much help, and it was simply by stepping through a comparison with the original to see if somehow I’d missed something that I found the place where I’d screwed up. Something annoyingly tiny, and a mistake that should have generated a more useful error.
If you want the Elisp code, you can find it here: color-theme-charcoal-personal.el
1 thought
Pymacs was developed by François Pinard, and it allows two-way communication between Emacs and Python. Very cool, except… it breaks my copy of Aquamacs, causing all sorts of things to spit out this lovely error:
Variable binding depth exceeds max-specpdl-size
What, you ask, is causing that? Well, it seems to be tied up with the advice framework (e.g., defadvice) and creating more recursion than Emacs will allow. Specifically, it trips at 600 levels. Very annoying.
No thoughts
I am continually fascinated by how little many people use a debugger1 when they’re trying to understand their code. Today, I watched an otherwise very intelligent person stare at some Java code for 15-20 minutes trying, apparently, to mind-meld with the JVM and understand what went wrong and why he was getting a glorious NullPointerException, something I still find gloriously amusing.
“Why don’t you set a breakpoint and look at what’s going on right there?” I asked. You would think I was talking Aramaic. Even I, arch-hater of Java—and Eclipse—was able to divine the way to do this task and within 15 seconds we had a solution.
Learn to use the debugger, even if you’re working in a dead language like Java. It might not be a live object universe like Smalltalk, but it is 100x better than simply guessing.
1 If you’re cursed with either C or C++, invest your hard-earned money in TotalView if you have to do anything with multi-threaded code. It is unparalleled by any other debugger.
1 thought
In reading an article about SciPy, the author has this gem:
The bottleneck in writing code isn’t in the writing of the code, it’s in understanding and conceptualising what needs to be done.
I mean gem quite literally. This, in the end, is the core difficulty that people seem not to grasp about writing good software. Writing lots of code is trivial; any monkey, or IDE can do it. The difficulty comes in the concept and more importantly the domain knowledge around the problem. For me, that’s 90% of the problem.
This is why I say languages don’t matter that much. Knowledge is language-insensitive.
No thoughts
When I was in TX, I started seeing Senator Clinton’s infamous homage to LBJ: the telephone ad. I almost fell out of my chain, though, as she hasn’t got an ounce of applicable experience to make that decision, which puts her exactly where Senator Obama and Senator McCain are. None have ever been the executive. Dick Morris, never a retiring wall-flower, has some advice for the campaign:
The next time Hillary uses the recycled red phone ad, counter with one of your own. When the phone rings in the middle of the night, have a woman’s voice, with a flat Midwestern accent, answer it and say, “Hold on” into the receiver. Then she should shout, “Bill! It’s for you!”
Because with Hillary’s complete lack of any meaningful experience in foreign affairs, and her lack of the “testing” that she boldly claims, she’ll be yelling for Bill.
I don’t think he should run that ad, as some might see it as misogynistic, even though it’s not. But at the end of the day, the only test she’s had, on the Iraq war, she freaked and picked the wrong answer.
1 thought
Amazon just released a new API and pricing model for their Simple Queue Service. There are two changes that I find especially interesting:
- Data transfer to EC2 is now free. You only pay for transfers to a system outside Amazon’s cloud. This makes it dirt cheap to use for many applications.
- Pricing is now $0.01/10,000 requests, rather than $0.10/1,000 messages. It’s both a change in how things are measured, but also potentially a lot cheaper depending on your application. This means that you can run 1,000,000 requests for a single dollar. Not bad.
Overall, it’s a great change, I think. They have reduced the size of the maximum message from 256kB to 8kB, but I doubt this will affect many people, and you can just shove the larger messages into S3 and send a reference in the message.
No thoughts
So, I’ve switched to using Mercurial for all my version control needs. As a distributed design, it makes it easy to work on a detached machine—say on an airplane—and not lose the functionality of a full version control system. This is in stark contrast to either CVS or even Subversion, which was my previous choice. All is not perfect, of course, but I’ve learned a few tricks that weren’t obvious, at least not to me.
First, Mercurial doesn’t track directories, at least not as such. This is a big change from Subversion. This means that some of my scripts, which set up a uniform directory layout for projects and build that as the skeleton in the repository, no longer work. I fixed this relatively easily by simply putting a file names 00README in the directory which contains a one line description of what the directory is for. Overkill, but it feeds my habits.
Second, I found it a bit annoying when I needed to “push changes”: that I had to specify the location every time. Turns out, you don’t have to, as you can create aliases and you can also create defaults. If, for example, you put the following in the .../.hg/hgrc file in the repository, you just use the default all the time:
[paths]
default-push = <url></url>
Now you can just use hg push to publish your changes, and not have to do anything else. Much nicer.
Lastly, because it’s so easy to create new changesets, and takes almost zero time, I find myself checking things in much more frequently. This means that the changeset is smaller, and therefore easier to find issues should they arise.
No thoughts
Jeffrey Shell writes about moving to distributed version control:
The more I play with the new breed of VCS tools, the more I appreciate them. The older generations (CVS, SVN) look increasingly archaic, supporting a computing and development model that seems unsustainable. Yet most of us lived with those tools, or something similar, for most of our development-focused lives.
When I speak of the new breed, the two standouts (to me) are Git and Mercurial. There are some other interesting ones, particularly Darcs, but Git and Mercurial seem to have the most steam and seem fairly grounded and stable. Between those two, I still find myself preferring Git. I’ve had some nasty webs to untangle and Git has provided me with the best resources to untangle them.
While Jeffrey is using Git, I’m using Mercurial, and I have to agree with him. I see two distinct advantages to distributed VCS:
- Ability to work totally disconnected
- Light-weight branching, etc.
Jeffrey talks a lot about the light-weight nature of things. I can’t even begin to explain how critical the ability work totally disconnected is to how I operate. I spend a lot of time on airplanes—measured in hours-per-week—and the inability to check-in, merge, diff, etc., is a huge impediment to getting work done. Right now, I’m struggling with getting Mercurial to work properly under Windows with SSH as the transport protocol, but I’ve managed to work around it for now.
If you’re doing a lot of work, even if it’s just a single developer, you should definitely be checking it out.
1 thought
Makefiles are evil; automake is a baroque disaster, likely understood by nobody currently living.
Comments Off
I’ve been practicing test driven development on some percentage of my projects for a while now. Something, however, has always felt just a little bit tiring about the whole thing. The biggest thing I struggled with was what to test, and how best to test. I suppose that’s obvious, eh? My biggest failing was that I would often test things that don’t need testing; things like other people’s heavily tested frameworks. This made writing tests boring.
Then, I read Dave Astel’s posting on behavior driven development, and a lightbulb—dim though it may be—went off in my head. The problem with TDD isn’t the idea, but the perspective. Dave makes it clear in the following excerpt.
It’s about figuring out what you are trying to do before you run off half-cocked to try to do it. You write a specification that nails down a small aspect of behaviour in a concise, unambiguous, and executable form. It’s that simple. Does that mean you write tests? No. It means you write specifications of what your code will have to do. It means you specify the behaviour of your code ahead of time. But not far ahead of time. In fact, just before you write the code is best because that’s when you have as much information at hand as you will up to that point. Like well done TDD, you work in tiny increments… specifying one small aspect of behaviour at a time, then implementing it.
When you realize that it’s all about specifying behaviour and not writing tests, your point of view shifts. Suddenly the idea of having a Test class for each of your production classes is rediculously limiting. And the thought of testing each of your methods with its own test method (in a 1-1 relationship) will have you rolling on the floor laughing.
Eureka! Behavior Driven Development. Really what was missing was the context of everything. So, I went searching the treasure-trove that is Google, and came across an article by Luke Redpath that put it in a Ruby on Rails perspective. Specifically, the behavior of Models and how to specify them. That then led me to RSpec, which implements a DSL for writing specifications that is on top of the normal Test::Unit framework. There’s also a Ruby plugin that helps make things work smoothly.
Now, if only ZenTest worked with Specs. The auto_test piece would be very useful.
Updated (21 Oct 2006): Nick Sieger has done this already, apparently using his magical time machine.
2 thoughts
I’ve been using WordPress for a while, and generally am quite happy with it. One thing is is slightly weak on is the comment system. I thought that what I wanted was a hierarchical system—where you can reply to other comments—but after seeing Jack Slocum’s absolutely brilliant work, I want his system.
You really should see it to understand how great it is. It also shows off the Yahoo UI Javascript libraries.
No thoughts
Without comment, from Andy Hunt, comes software engineering in 10 panels:

Indeed.
2 thoughts
In Language Wars, normally rational Joel Spolsky has simply cracked. I don’t know if it’s the pressure of popularity, or what, but he’s simply lost it. Other people have taken him down a notch, but here’s the priceless bit of nonsense:
I for one am scared of Ruby because (1) it displays a stunning antipathy towards Unicode and (2) it’s known to be slow, so if you become The Next MySpace, you’ll be buying 5 times as many boxes as the .NET guy down the hall.
Seriously, this is so amazingly silly that I don’t know where to start. First, if you’re “the next MySpace”, you can afford this problem. But that’s not really the true absurdity demonstrated here. You are not going to become that popular1, so don’t sweat it. You can sweat it if you get that level of success.
Also, you have to be able to move fast enough to get to the position of popularity, unless you truly have a one-of-a-kind idea, for that sort of success. Seriously, this argument is built on the mental masturbation of “what if I was Google?” But you aren’t, so just stop.
Quit sweating the problems that give you a mental stiffy, and work on the problem that are truly hard: ease-of-use, process, transparency, discoverability and the whole use experience.
1 This isn’t absolutely true, but given hundreds of thousands of startups, and the tiny handful of big successes, it’s probabilistically true.
7 thoughts
Andy Matushak takes a look at some of the new things in Objective-C that are coming with the next release of Mac OS X in the developer tools. Some very nice things, though there’s still not too much information on the upcoming garbage collection implementation and what impact it might have on existing code.
No thoughts
Some time ago, I was working at a company on a product that was suffering from some performance issues. It seemed that lookups in a specific data-set were taking too long, so the developers were continually discussing new structures for storing things. Then I asked a question: “Why does it matter? How often are you looking it up?”
Turns out it was being looked up hundreds of times per operation. The answer? Look it up at the beginning of the operation, and just hold a local cached copy. Ta’da, a 100x performance boost without complicating the data structure, and the elimination of a mathematical bug if the value of the query changed during the operation—which could happen, but would break the algorithm.
There ends the lesson.
No thoughts
As a general contrarian and otherwise trouble maker, I’ve always attempted to look at a problem from any perspective except the commonly accepted one. Recently, I was having a discussion with some people about my general distaste for RDBMS and how I think that the collapse of the alternative database architectures1 in the 1980s, along with the hype surrounding object databases in the 1990s contributed to a stagnation in conceptualization of data management. While the general theoretical underpinnings of the relational model are useful, I think the rigid interpretation of the mathematical foundations into implementations has limited people’s ability to think about the problem2 in different ways.
Read the rest
2 thoughts
Greg Luck has a problem with Ruby, or maybe it’s just Ruby on Rails, or maybe he’s just got his tin-foil hat on crooked. I’m not particularly in a mood for a point-by-point deconstruction of his rather rambling attack, but there’s a few points that I pulled out:
Ruby is slow. Yup, totally. Well known issue, and thank you Captain Obvious. It’s all a matter of how slow you can tolerate. My experience is that algorithmic choices have the order-of-magnitude impact on decisions, and that proper profiling will allow just about any language to be fast enough1 for the problem at hand. Performance has been, and almost always is, a red herring from the Complexity Crowd who are upset their temple of worship has been desecrated.
Rails isn’t smart enough when dealing with “real databases.” This is related to handling of views, stored proceedures, connection pooling. All of these are “major issues” in a big enterprise. I’ve never worked in a large integration database that didn’t use all of these extensively. Rails doesn’t support them, and while I might miss them on occasion, it’s also outside the scope of what Rails is trying to solve. I might disagree, but it’s not like DHH hasn’t made his views widely known. Not every tool solves every problem well. Rails is aimed at green field applications, not integration applications.
Rails has no caching. Demonstrably false. It might not work the way some unnamed Java stack works, but it is there, and it works reasonably well in my opinion. Again, scope is everything.
Ruby on Rails took longer than Java would have. OK, without any metrics, or background, who knows. If I took some brilliant Java developers and made them do their first app in Ruby on Rails, I would be shocked if it didn’t take 2x as long to complete. That has nothing to do with Ruby, Rails, or anything but the nature of skill-sets. Second and third projects are the point where it becomes interesting, and without metrics, well, this is just hot air.
He then goes into some bitter vitriol about who is ripping who off. If anyone’s getting ripped off, it’s Smalltalk, not Java. MVC didn’t originate with Java. Java has zero original ideas in it, but then again, neither does Ruby. This will upset people, but both are derivitive languages. That’s fine. Purity comes at a cost, as I have said before. Seriously, a littany of axes is not that interesting.
There are problems with Ruby, and with Rails. Certain aspects of the Ruby syntax grate at me, but that’s true of every language. Unfortunately, the author has conflated Ruby and Rails and allowed his personal axes about Rails’ suitability to projects that may, or may not be within its problem domain, to color his rationality. Seriously, a littany of axes is not that interesting.
As I’ve said so many times, and is so often mis-understood: it all sucks, I just want it to suck less. Doing so requires understanding context and history. Java is a great solution for a certain class of programmer with a certain class of problem. It sucks unbelievably for web applications, in my opinion. This is why a vast majority2 are written in PHP, Perl, Python, VB and Ruby. That doesn’t mean it’s useless, but it does mean that one needs to focus ones energy on more tractable problem domains where strengths and weaknesses are balanced better.
There’s plenty of problem domains for which Ruby, Python and others aren’t well suited. As always, the more tools in your belt, the better you can focus your tool on the problem at hand.
1 Something I learned in the Lisp community is that everything starts out as a list for a data structure. Some form of list, maybe a property list, but something simple. Only after the design is done is refactoring kicked in to figure out if it’s fast enough, and if not, where the speed is needed. The performance bottle neck is not where you think it is.
2 My POOMA-validated statistics say that this is 96.325%
2 thoughts
Most people would consider me a passionate person. I defend my ideas, and those I believe in with a veracity that sometimes borders on religion. Having said that, however, there is a moment of dispassionate analysis needed to understand something that seems to escape some of the smartest people I’ve ever known: why nobody cares about Lisp and Smalltalk.
Whether it be the purity of Lisp’s data-is-code-is-data theology, or the absolute object-oriented construction of Smalltalk, both languages exist as beacons of origin for many of the most powerful ideas in computer science today. Nearly every language steals from them, either conceptually or in actuality, whether acknowledged or not, and it is nearly impossible to design a language today without their influence. And yet, they are irrelevant to most people.
Eric Raymond wrote, in “How to Become a Hacker,” that:
LISP is worth learning for a different reason—the profound enlightenment experience you will have when you finally get it. That experience will make you a better programmer for the rest of your days, even if you never actually use LISP itself a lot.
And why, we wonder in our towers, is it that nobody uses Lisp? Why was Smalltalk abandoned for some bastard child of C++ running on a bondage-and-discipline VM? The answer is simple. We want the answer to be technical, because it will allow us to patch up and “fix” the problem, but it is instead derived from the very nature of talent.
Lisp and Smalltalk, along with a few other tools in the technical world, are amplifiers. They make whatever you do more so. If you are a talented developer, they are like a paintbrush in the hands of Michelangelo. If you have vision, they help you write without constraining your expressiveness.
If, on the other hand, you aren’t those things—and most people aren’t—then they are the paintbrush in the hands of the high-school art-student: tools of exceptional mediocrity. At their worst, though, it’s like handing a scalpel to a blind man and asking him to perform surgery. Sure, it might end well, but the probability is pretty low.
In situations where the guarantee of talent is minimal, it is in the best interest to have tools which protect us. Sure, I might be able to get to work faster in Michael Shumacher’s Ferrari Formula One car, but I’m more likely to get myself killed—and maybe take some other people out with me. The same is not true if you give him a Ford Taurus. Sure, he won’t set any records at Monaco, but he’s likely to get things done faster than anyone else.
The trick comes in this: if Michael Shumacher can drive a Taurus around a racetrack 25% faster than anyone else, just think what he can do with a real tool. The same is true of a real developer. It simply depends on the certainty you have in their talent. When you have no certainty, the Taurus is a safer (i.e., better) choice.
Now, some might read this as a death knell for things like Lisp and Smalltalk, but instead, I think they are seeing a resurgence of sorts. First, there are freely available versions of both that are of exceptional quality, and this sets the stage for availability to experiment. Second, the nature of applications and solutions is changing. No longer is it delivered on the desktop, but instead via the server. Users don’t care what you write it in, they only case what you can do for them.
And so, Lisp and Smalltalk will continue to be marginalia, just as Federico Fellini is marginalia in the annals of cinema when measured by popularity. So too is Miles Davis, and any other great thing. This does not devalue them, but simply reinforces that popularity often has little to do with quality, and more to do with psychology.
4 thoughts
When I read Adam Conner’s post on Ruby and what he dislikes, primarily compared with Lisp, I was reminded of a tendency that I have: perfection über alles. It’s an admirable thing to keep a healthy skepticism about the real-world nature of things versus what could be, but it’s also necessary to be realistic sometimes. I wanted to take his points in turn.
First, he speaks of “more than one way to do it,” which is a valid but specious point. All languages have multiple ways to do things. It may be true that some languages encourage more strict approaches—certainly Python attempts to provide only one way to do things, or certainly one preferred—but even in those cases, there are multiple ways. Lisp actually has a nearly infinite way of doing things, especially when you include all the things you can do with macros and other functionality.
The argument actually touches a tangential truth: that each way be obvious when read. One of the primary complaints about Perl is its obfuscation factor. This is actually not about having multiple way to do something, but instead that almost all of them are potentially unclear when read months later. So far, I’ve noticed that Ruby code written by others is almost always more readable than most other languages1. The one place where that falls completely apart is in meta-programming, but this is no worse than trying to reverse analyze a Lisp macro.
Second, he refers to some of the more baroque syntactic constructions, like the use of $-variables. I hate these with a passion. I can’t even begin to explain how much I hate them, but there they are. Fortunately, the English module solves a lot of this. I use it on all of my code, and I wish others would as well. There have been rumors that it may become standard facility, so you don’t have to include it yourself. This would be a huge step forward, and would likely introduce zero backward-compatibility issues.
Next, he brings up a lot of things adopted from Perl, such as ranges, which are not the most beautiful things in the world, but I actually find quite readable. It really depends on how you use them. Here’s one use that I dislike, taken from the Pickaxe book:
while line = gets
puts line if line =~ /start/ .. line =~ /end/
end
To me, that’s not really that readable. There are better ways to express it, as well. There are other times that ranges are wonderful, such as for their use as Intervals:
kind = case year
when 1850..1889 then "Blues"
when 1890..1909 then "Ragtime"
when 1910..1929 then "New Orleans Jazz"
when 1930..1939 then "Swing"
when 1940..1950 then "Bebop"
else "Jazz"
end
This I find actually clearer than most people’s writing with bizarre if/case constructs. This to me is very clear, which is the ultimate goal of all programming for me. I don’t deny there are some bizarre ways to write things, but then again, there are in every language. Whether you use them or not is your decision.
The next complaint about the significance of whitespace is a bit of a red-herring. Every language I can think of, except Lisp, has some bizarre whitespace significance. Lisp gets around it through the use of the S-exp notation, which is both its strength and the single thing that is intimidating to most people. I like it, but it is something that breeds religious behavior. While he takes a side-swipe at Python, I think that the significance of whitespace2 is actually a benefit for languages
Another place that seems to confuse the author is the idea of constants not being actually “immutable.” I think this is a mistake often made with dynamic languages, including Lisp. Many things in Ruby are immutable, just as they are in a lot of languages. Variables are not immutable, they are simply names for a reference to an object. What the author seems to want is a one-time assignable variable, which might be interesting. I find the behavior of warning based on convention to be more than suitable for the nature of my development. Even the DEFCONSTANT form can be defeated if you’re an idiot.
He has a few other complaints, which I won’t go into, but this is what it comes down to:
But it’s not Lisp. I came to other languages before the conversion experience; Ruby falls afterwards. Sure, the Lisp community is dysfunctional, and its libraries and toolchain have issues. Utterly impractical yadda yadda ya. But Lisp is the culmination of a certain line of thought, and Ruby is just a waypoint. Where Lisp exposed me to first principles, Ruby has some clever syntactic hacks. It isn’t that I despise all other languages. But if you’re going to go for dynamic languages, why settle for 80% of what can be done when you could have 100%? Lisp is a tough act to follow. It changed my expectations.
Indeed, it’s not Lisp. And Lisp isn’t Smalltalk. We could go into the issues with CLOS for hours, and the inanity that exists with certain intensely baroque elements of Lisp, but it too is an imperfect language. I love Lisp for its purity of concepts—mostly—but other than a few specific places, it is even less practical a choice than Smalltalk for most organizations. If I were developing a huge NLP system, Lisp would be my first choice. If I were modeling some amazingly complex real-world system, like financial markets, I’d use Smalltalk. For most other projects, languages like Ruby—and strikingly, even Java—are actually more practical.
The author admits that the libraries and toolchains for Lisp are lacking. This is an understatement, especially when discussing the free community. Franz has some amazing tools in Allegro Common Lisp, but the free world, while having some great Lisp compilers, has a pretty atrocious collection of libraries. Like Smalltalk, it seems everyone ends up re-inventing everything every time. This is unfortunate. As much as I love writing Smalltalk, I always feel like I’m having to write a lot of things that I shouldn’t have to write.
For me, Lisp and Smalltalk are my “secret weapon,” to be pulled out for pleasure and for truly hard projects. Most projects aren’t hard.
1 Smalltalk is the one exception to this, however Smalltalk is more explorable largely because of its environment, not the language itself. While I prefer the syntax of Smalltalk, it’s not an order-of-magnitude better than Ruby.
2 This is a “within reason” caveat, of course. FORTRAN is absurd in this regard, at least in its early punch-card derived nature. Python only cares about relative whitespace, not absolute whitespace.
No thoughts
Perhaps that’s too harsh, but after reading one of Glyph’s posts about how Penny Arcade is going down the tubes, I can’t help but think of a horribly bastardized version of something form Edsgar Djikstra: You can write horrible code in any language.
Basically, I think what you’re seeing is poor programming skills being amplified by a framework that allows you to be efficient. Unlike most of the enterprisey world, which is hell-bent on holding your hand, foot, and every other dangling body part—lest you hurt yourself—Rails and Ruby are quite easily used to shoot yourself in the foot. This is also true of Lisp, Smalltalk and a lot of other tools that are extremely powerful.
This is slightly tongue in cheek, though: it can’t possibly all be Rails’s fault. It wasn’t anything to write home about in PHP either. How do they manage to consistently screw this up? It’s a web page with a paragraph of text and a single image, updated at most twice per day. It’s not rocket science; it’s not even computer science. It’s barely a shell script.
With great power comes great opportunity: to screw up. I actually have no idea why it’s going wrong, but as Glyph observes, this site isn’t rocket science, and there’s a lot of very cool and amazing sites written in Rails (and Python frameworks, like Twisted), so it’s likely to be the people. And in the end, it’s always the people.
2 thoughts
Dave Thomas has written a post entitled The Glue that Doesn’t Set that discussing the nature of Ruby compared to Perl, but specifically the nature of two things: readability and the nature of web applications as “glue points” in the world.
Now Ruby is also a glue language. Just like Perl, Ruby works and plays incredibly well with external data, resources, and programs. I can do everything with Ruby that I used to do with Perl—I can use it to integrate all kinds of stuff just as easily as I used to be able to with Perl. But, there’s a major difference. I’ve discovered that, over time, my Ruby programs stay malleable and easy to change. Ruby is the glue that doesn’t set.
This isn’t particularly unique to Ruby, as I think Python also maintains this readability that Perl quickly loses1. This is not to say that one can’t write Perl in any language, or write readable code in any language—even assembler, but as a bit of a corollary to the Sapir-Whorf hypothesis, some languages push us in certain directions and constrain our ability to say stupid things sometimes.
I think that dynamic languages cater especially well to this issue for a few reasons. First, they do not muddle your code with non-core expressions. This means that 80% of my code isn’t spent making the compiler happy, or doing its job for it. The code that I write is focused purely on the problem domain that I’m trying to solve. This means when I go back, or anyone else does, there’s less time spent trying to understand why I marked something as final and more about what the logic does.
Second, I believe that dynamic languages, whether it be Smalltalk, Ruby, Python, or even Perl, allow the programmer to get to a point of functional software faster, and therefore allow more time for rewrites that always occur, and testing, which is often ignored. Often, with more bondage-oriented languages, I find people sweating every algorithmic choice before even knowing where the bottleneck might be because coming back and fixing it is always seen as a chore.
Refactoring assists in the clarity of your code, not just by doing it, but by being able to do it and not having the fear of what it will take. The more you fear refactoring, or any changes to your existing code base, the less you are willing to take a chance with an idea. The less you are willing to take a chance, the less risk you will take, and risk is where greatness comes from.
1 Once, many years ago, I was a rabid Perl programmer, and looked down on a lot of people who complained about its baroque syntax. Then I went back to try and read some of my “works of art,” and realized the error of my ways. Programs are read more than they are written.
No thoughts
I just saw this quote by Don Roberts and it sums up everything I believe about the absurd belief that bondage and discipline gives you more power in a programming language:
Static types give me the same feeling of safety as the announcement that my seat cushion can be used as a floatation device.
Please place your seat backs and tray tables in the upright position, it’s going to be a bumpy few years.
2 thoughts
Marc Abramowitz observes that sometimes you can write programs that truly do look like line noise. Seriously, I think I remember my Hayes 300 baud modem spitting this stuff out.
I think it’s important to say that I wrote quite a bit of Perl code back in the mid 90s, before discovering the error of my ways. That was realized when I went back to change some nifty code I’d written and realized that I had no idea how it worked 2 years later. While you can write FORTRAN in any language, Perl present a whole world of opportunities for obfuscated code.
6 thoughts
So, when I’m working on a project, I do a lot of work in OmniOutliner—specifically the Professional version—and I’ve developed a tiny template that I use for writing out vision statements, stories and then the tests associated with them. I find this to be very productive for me, and figured I’d just throw the darned thing out there for others.
So here you go.
If you’re using the Professional edition, you can use Templates (I don’t think the regular one can), and you can place it in:
~/Library/Application Support/OmniOutliner 3/Templates
If you’re not on Pro, you can just double click it.
No thoughts
Computer geeks are a strange lot. Often, they take two diametrically opposed ideas and confuse them for each-other. Take complexity and abstraction. They’re just simply not related. In my experience, simplicity is often the result of proper abstraction. For my first example, witness this awe-inspiring stack-trace, which contains 100 lines, maybe more, since I ran out counting and it keeps going off the bottom of the page if you look closely.
Now, to me, this seems like a huge level of needless complexity masquarading as “flexibility and power,” the two watchwords that we geeks use to justify our Rube Goldberg contraptions. Absurd is what it is. What’s even more laughable is the reaction to this—something which should horrify many:
To me this diagram shows the success of Java. We have abstracted away the machinery of moving data and can create code that focuses on the one valuable thing; the business logic. And that single bit of valuable code that the business actually cares about is small – that is a good thing. (From the comments section.)
Seriously. Time to pull our collective heads out of our collective orifices, and understand that while much of this might be solved by JIT technology—and a lot of people say it is, when in fact it’s just hand-waving—it’s not the performance I care so much about. It’s the absurd level of complexity when something goes wrong.
And people, something always goes wrong. There’s a trade-off between proper encapsulation, decomposition and re-factoring, and some of the absurd levels of complexity that come with these “enterprise frameworks”. I read through this, and I see lots and lots of things going through a lot of hoops to handle the programmer’s idea of the 1% case.
[via Ned Batchelder]
No thoughts