There are certain arguments that crop up repeatedly in programming discussions that really, really get up my nose, because while they sound very authoritative and convincing at first glance, in reality they are nothing but hand-waving, or, as Shakespeare said, full of sound and fury, signifying nothing. These are they.
1. “I’ve never had a problem with it.”
This one usually crops up with proposals that are widely regarded as antipatterns, such as Pokémon exception handling or comparison-based database migrations.
There are several reasons why you might never have had a problem with something like that:
- You got lucky.
- You haven’t had enough experience with it.
- You don’t consider inefficiency, unreliability or inflexibility to be a problem.
- The problems that it caused were outside your area of competence, but affected other team members.
- The problems that it caused were under the surface and only materialised later.
- You did have problems but just thought they were a fact of life.
Someone once said that they always ask candidates in job interviews what their pain points are with their favourite technologies, because that’s the way to tell if someone really understands something and isn’t just fanboying it or CV stuffing. Until you’ve discovered the pitfalls of something, you haven’t really understood it properly, and you are in no position to advise on how to use it safely.
2. “These are the problems you might encounter if you get it wrong.”
This argument annoys me because it is nothing but FUD, and it is possible to come up with similar arguments against everything. It also completely misses the point.
The important question is not how easy it is to get something wrong, but how easy it is to get it right. Very often the people spouting this argument are promoting an alternative technology that fails very, very badly in the “getting it right” department. For example, a few years ago, the Subversion guys were pushing the Git-promotes-antisocial-development line for all it’s worth, yet they had no convincing answers for how to branch and merge properly, or how often you should check in code, or how to recover when
svn update resulted in so many conflicts that you lost an entire day’s work, or what to do when you come to the end of a sprint and some items are done but others aren’t.
Thankfully, you don’t hear those objections so much now that Git has become mainstream and is the second most widely used VCS tool on the market: all the evidence indicates that those fears were unfounded. These days, it’s the anti-CSS preprocessor brigade that trot it out, with all sorts of FUD about bloated generated stylesheets and over-specificity (problems that are not hard to correct), yet they have no convincing answer to the critical questions of how you avoid DRY violations and magic numbers, and often propose laughably bad practices as an alternative.
Heck, a ladder can put you in a wheelchair if you get it wrong. A chainsaw can kill you if you get it wrong. A car can kill multiple people if you get it wrong. But we don’t stop using ladders and chainsaws and cars. We just take more care to get them right.
3. “It’s a leaky abstraction.”
This is another one of those FUD-that-can-apply-to-everything arguments. People are way too glib about dismissing abstractions as leaky, but if you read Joel Spolsky’s original article where he coined the term, he points out that every abstraction is leaky. Even the most elementary data types you work with are leaky abstractions on top of bits and bytes (which is why Steve Yegge categorises bits and bytes as one of the five essential areas of knowledge you should probe in a phone screen). Dates and times are a leaky abstraction. Unicode is a leaky abstraction. Even arithmetic is a leaky abstraction: if you’ve ever encountered overflow or rounding errors, you’ll know what I mean.
To be sure, some abstractions are leakier than others, but the important question about an abstraction is whether the benefits outweigh the problems introduced by the leaks. Another factor is how easy it is to avoid the problems that the leaks introduce simply by being aware of them. O/R mappers are a much debated example these days. People will tell you that if you’re not careful you’ll end up with all sorts of nasty select n+1 performance problems, but in reality, if you know what select n+1 means and why it’s a problem, it’s not hard to avoid it. In this case, the argument is just another example of “these are the problems you might encounter if you get it wrong” — see point 2 above.
The fact that an abstraction is leaky does not mean you need to avoid it. It merely means you need to understand it.