Fatal abstraction: A bottom-up view of high-level languages

Modern languages prize ever higher levels of abstraction, but at the cost of flexibility

I've been writing a lot of code recently, more than your normal internal IT tools and widgets. Sizable LAMP apps and API development have been filling my plate, alongside technical project management for several significant development efforts.

During the course of this work, I've had a chance to reflect on a number of items related to software development, and I've become even more entrenched in my predilection toward lower-level languages and development frameworks. This may come off much like someone shaking their fist at the clouds, but it is what it is.

I've been surrounded by Python and Ruby/Rails code, and I'm doing most of my own development in Perl, PHP, and Python. Having spent more time with Rails lately than ever before, I've been both amazed by and concerned about the level of abstraction afforded by that framework. It truly does make certain things "easy" as long as you drink the Kool-Aid and conform to a strict set of rules. Python is not as lockstep as Rails, but it's definitely not a "more than one way to do it" language. Instead, Python implies that there should be only one way to do something. This, fundamentally, is where I bristle.

I may haveĀ questioned Perl's future now and then, andPerl certainly doesn't have the presence it once enjoyed, but the strength of Perl has always been its flexibility. You can do pretty much anything with Perl, and you can do it in a wide variety of ways. Perl's core revolves around the idea that there's always more than one way to do it. In fact, there may be dozens of ways to do it. PHP shares a similar trait in that it gives you a large set of tools and leaves the construction up to you.

Ruby, and especially Rails, is the opposite, and Python definitely leans more in that direction. Essentially, it's the difference between building a chair from raw lumber and assembling one from IKEA. This isn't to say there's anything wrong with assembling from parts, and clearly Ruby and Python are very capable and strong languages. However, they're not my cup of tea.

Rather than trust some mysterious underlying code to handle database migrations and other extremely sensitive tasks, I'd much rather do it myself. I'd rather write that nitty-gritty code and know that I'm not shooting myself in the foot by relying on a general-purpose abstraction. Perhaps I have trust issues.

Fundamentally, I think that this stems from a lifetime spent building and maintaining server and network infrastructures. Working at a very low level is intrinsic in that arena, and trust in software and hardware is tough to earn. Even once that trust is earned, verification is mandatory. You don't push out significant changes to network hardware lightly, and if you use orchestration software to do so, you test the hell out of it first because of the vast damage that an ill-formed or ill-received change can create.

Anyone who has worked in data centers knows there's no way that you can manage and maintain hundreds or thousands of servers by hand. You need automation and orchestration tools or an army of sys admins. But those tools should be part of the puzzle, not the only management method. The further we abstract control over hardware from the shell, the more problems we ultimately create -- and the trillions of lines of code that have been written to address these problems have also exacerbated those very issues. Perhaps all of this has bled over to my views of software development.

A good friend continuously crows about how amazing Rails and Capistrano are. I see how assembling all sorts of test harnesses, deployments, and code management tools has streamlined his development process while also reducing bugs and test code before deployment. I get all of that, and I can see the benefits.

But hitting that deployment button and watching all kinds of abstraction layers do scary things to production databases still gives me the willies. If and when it breaks, the many layers between the developer and the low-level code complicates the troubleshooting process. When I write a database modification function, at least I know exactly what it's going to do, down to the queries themselves. If it breaks, I know exactly why, nearly instantly.

I'm not a developer, though I write more than my share of code these days. Ultimately, I think that languages like Ruby and Rails have their place, and they certainly have their fans. But they're not right for me.

When it comes right down to it, I need to know exactly what my code is doing. I'm going to keep an open mind and spend more time on the other side of the fence in the short term. Perhaps I'll be won over, but it won't be easy. Trust issues are complicated.

This story, "Fatal abstraction: A bottom-up view of high-level languages" was originally published by InfoWorld .

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more