Over at the O’Reilly Ruby blog, Derek Sivers has an intestesting post up, describing what he learned from his decision to revert to PHP for the complete rewrite of his cdbaby.com site, after spending two years trying to do it in Rails.
In a nutshell, those two years of Rails development (with very expert help) got the project less than halfway to completion before Sivers pulled the plug and rewrote the whole site himself, in two months, complete with all the architectural advantages (MVC and DRY) that he was aiming for in the first place.
On one level, it’s a pretty simple point that Sivers is making — one that perhaps shouldn’t have been so painful to discover: the choice of programming language per se is largely irrelevant to accomplishing the goals of good software design. It’s certainly not nearly as relevant as things like good design principles, development skills and domain knowledge. Or as Sivers puts it: “Is there anything Rails/Ruby can do that PHP can’t do? …(thinking)… No.”. Plug in your two favorite languages, be honest, and you’ll probably get the same result.
On another level, there is a subtler lesson here about how exposure to a language that uses abstraction to enforce good design patterns can dramatically improve one’s use of a language that doesn’t, or doesn’t do so to the same degree. If you think about it, this makes perfect sense: Languages that enforce a higher level of abstraction involve a trade-off of efficiency for risk because, as Joel Spolsky classically put it, all non-trivial abstractions leak. But if you construct your own abstractions to emulate those efficiencies, and do so in a language that you know well at a lower level, then it stands to reason that those specific abstractions are going to leak of lot less often and, when they do, the leaks will be much easier to patch. I think this is what Sivers is driving at in saying that Ruby was a great “teacher” for him — it didn’t work out at all for the project, but wrestling with it taught him how to write better-quality PHP, which in turn suited the project requirements perfectly.
Sivers draws several additional lessons from his experience with Ruby, but I think these two are the big and generally-applicable ones. I also think there are at least two others that he doesn’t call out explicitly, but that are strongly evident in his story. Both have to do, not specifically with Ruby or PHP, but with software abstractions more generally:
1. The evolution of ignorance applies. The evolution of ignorance is an idea from the history of science: When a new methodology replaces an older one, raising the level of precision or rigor that is deemed acceptable in a discipline or domain, the price for that is that a lot of what was known or adequately handled before becomes, at least temporarily, unknown or problematic. (When European maps of Africa got much more precise about the shape of the coasts, they simultaneously lost imprecise but useful information about the interior.) It takes some time for the new way to catch up on all fronts with the achievements of the old way. The prior (PHP) version of cdbaby.com may well have been, architecturally speaking, something of a Big Ball of Mud, but there was, no doubt, a lot of domain knowledge and technical problem-solving packed into that ball — so much, in fact, that two years of architecturally-correct Ruby on Rails development couldn’t encompass even the half of it. This suggests that part of Sivers’ efficiency gains from reverting to PHP for the rewrite may have come, not so much from changing languages (again), as from the luxury of taking a second crack at the redesign, having failed to get it right the first time.
2. The Pareto Principle (aka, the 80/20 rule) applies. The usual application of the Pareto Principle to software engineering takes the form of “80% of the resources required to run the program are consumed by the execution of 20% of the code.” Sivers’ run-in with Rails suggests a slightly different application of the principle: 20% of a higher-level software abstraction gives 80% of the benefit to be gained from adopting it. This is actually a generalization of one of Sivers’ own lessons, namely, not to want what you don’t need. Effectively, by writing his own abstractions in PHP, rather than relying on the whole package provided by Ruby on Rails, Sivers was able to implement abstractions only where they made sense for his project goals, without taking on the deadweight (and hidden complexity) of unneeded, but necessarily leak-prone abstractions (remember Spolsky’s Law!). He thus got the lion’s share of the benefits of MVC/DRY architecture, with a fraction of the downside risks associated with migrating existing, working software to higher-level abstractions.
Those seem like valuable lessons to keep in mind, no matter what language you are using, or thinking of using, for that next top-to-bottom rewrite.
[photo under CC by flickr user andrew*]