Monday, December 15, 2008

Purity vs. Pragmatism

I was being interviewed for a new job last week (yes, I am actively on the market), and had a very interesting, frustrating run-in with one of the interviewers (disclaimer: by mutual acclaim, the role and I decided we weren't right for each other; you'll figure out why shortly) at a large bank.

We Frustrate Each Other
The frustrating part of the interview came when I realized that The Interviewer (we'll abbreviate it to TI, not to be confused with the hip-hop artist T.I.) and I were disagreeing on virtually every point of philosophical substance. But that was just a manifestation of a broader disagreement that I think went to the core of why the two of us must never work together: we fundamentally disagree with the core principle of software engineering.

Let me explain with a few examples of where we differed to try to explain what was going on (no, this is nowhere near an exhaustive list):
  • He believed that checked exceptions in Java are always wrong; I believe that sometimes they're useful and sometimes they're not.
  • He believed that you should only accept or return interfaces (and never a concrete class) from a module; I believe that you pick and choose between interfaces and POJOs depending on the context.
  • He believed that setter-based Dependency Injection is always wrong and that only constructor-based DI should be used; I believe that you pick the right one for the context.
  • He believed that you can only ever use DI with a DI container like Spring or PicoContainer; I believe that it's an architectural principle that can applied with or without DI-specific tools.
  • He believed that you cannot consider yourself a practitioner of agile methodology without rigidly adopting a Formal Agile Methodology (Scrum, XP, whatever); I believe that the whole point of agile methodologies is that you pick amongst the parts that help your team develop better software faster.
What's the major differentiation here? Purity.

Purity
TI's approach to every major difference between the two of us fell down on the side of rigid, unbending application of a principle in the interests of purity. My approach is far more fluid and contextual.

Purity in any endeavor (art, design, architecture, music, religion, software engineering) is attractive because it strips away all thought and all decisions, and in doing so, pushes a concept to its ultimate expression. I can understand the sentiment. When I moved into my flat, every single surface was either white (floors, walls, ceilings, some doors) or gray metal (stairs, shelves, other doors). It's a minimalist, pure aesthetic, and it removes all distraction and makes it very simple to make decisions: there's nothing subjective about additions.

Sometimes, purity is exactly what you want. It focuses you, and allows you to fully explore one concept to its extreme (how white can you get the walls and floors? can you get them the same white even though you have to use different paints for different surfaces? can you keep the floor white even though people walk on it and put furniture on it?). Even the exploration of pure silence has begat its own groundbreaking work.

Purity in Software Engineering
Taking a purist approach to a software engineering matter allows you to nail your banner on the church for all to see: I believe in X, therefore X is always correct; by applying X to every situation, I prove the superiority of X and validate my initial conclusion that X is superior. This comes up a lot, particularly in architectural discussions:
  • Asynchronous Messaging is great! Let's use it for everything!
  • An RDBMS is great! Let's use it for everything!
  • REST is great! Let's use it for everything!
  • Google Protocol Buffers is great! Let's use it for everything!
  • Cubes are great! Let's use them for everything!
  • Lisp is great! Let's use it for everything!
The converse also happens:
  • XML is crap! Let's banish it from the world!
  • RPC is crap! Let's banish it from the world!
  • Solaris is crap! Let's banish it from the world!
  • RDBMSes are all crap! Let's banish them from the world!
  • TCL is crap! Let's banish it from the world!
  • Lisp is crap! Let's banish it from the world!
Purist decisions are easy. They don't require thought. They don't require constant critical evaluation.

And that's why I view them as intellectual cowardice: by limiting your choices intentionally, by limiting the scope of tools at your disposal, by closing your mind off, you reduce the amount of thought you have to put in. But as engineers, as craftsmen, we live by our minds: we are paid to think, and the more we're paid, in general, the more thinking we're expected to do.

TI could replace himself with someone far less experienced by simply writing his own DSL that works on the JVM that doesn't allow you to do any of the things that he thinks are wrong, and forces you to do all the things that he thinks are right. It wouldn't be that hard. Then he can simply hand that off to someone and say "here you are; a language that obeys every one of my edicts perfectly; you are sure to do an excellent job now that I've handcuffed you to my beliefs."

[Aside: if TI's beliefs realy were so universal as to allow him to view me with revulsion for not sharing them, why isn't there already the TI programming language? Are you to tell me that there isn't a programming language which targets some target environment (JVM, CLR, raw x86 machine code) that forces the practices that he likes and forbids the practices that he doesn't? Really? Does that tell you something perhaps? Because it's not like we have an absence of programming languages these days. And it's not like it's that particularly hard to write a language and target one or more existing VM environments, so all the hard work is taken care of already.]

In Defence Of Pragmatism
I'm impure. I'm about as tainted as you can get. And you know what? I think that makes me more effective, rather than less. Because what I get out of a lack of purity is pragmatism. The two can't coexist particularly effectively: I think you fundamentally agree with one or the other.

Pragmatism allows me to look at a problem, carefully consider the advantages and disadvantages to each potential solution, and then determine the right approach to each particular situation.

Pragmatism allows me the flexibility to do things that I know in other circumstances would be wrong, but in that particular one would be right.

Pragmatism allows me to have a bag of tricks rather than one, and pull them out as I see fit.

Pragmatism allows me to gradually refine my beliefs by using both my favored and unfavored approaches in a variety of circumstances so that I have evidence and backup behind me when I express my opinion.

Pragmatism allows me to work with a variety of code written by a variety of people and engage with it constructively as it is, rather than seeking to rewrite it before I'd be willing to touch it.

Pragmatism allows me to decide where to focus development efforts based on what's most important that day: sometimes rushing a feature into production to make more money, sometimes spending time testing the bejebus out of a small change before I make it.

Pragmatism forces me to build software which is easy to maintain and consistent in its internal architecture and clean in its modularization and consummately tested, because that's the only way to maintain a complex system over time. Pragmatism also tells me that if I know the piece of development is only there to run a single time, focusing on all of that is wasted time better spent elsewhere.

Pragmatism allows me to assess the strengths and weaknesses of my team, and the constraints of my customers, before assessing the correct development practices that will result in that unique group of people producing the best software possible with the fewest resources in the shortest possible time. Pragmatism forces me to understand that no one methodology could possibly work for all engineers, all customers, and all projects.

Pragmatism allows me to focus on one and one thing only: getting the job done well. Do what it takes, but get it done, and make sure it works properly. And that's precisely what we're here to do as software engineers: engineer software. And engineering, unlike art, design, music, or any purely creative endeavor, requires getting something done that works. We're not in this business to craft a purist expression of an idea. We're here to build things that work.

The irony is that many purists get that way out of a misguided belief that they're being pragmatic: buy choosing a single technology or technique or methodology, they've chosen the One True Solution and don't have to consider the same decision with over and over. Furthermore, they've made sure that those people working for/with them (particularly the lesser skilled ones) don't do The Wrong Thing. But that means that they've closed their minds off to the chance that they've chosen incorrectly. Or, even more appropriately, that there is no one right decision.

That's why purity and pragmatism can't coexist: purity requires that you ignore the results in favor of an ideological ideal; pragmatism is all about pursuing results for their own sake.

And that's why I think TI and I couldn't work together: I'm a pragmatist and he's a purist. The two of us were bound to clash, and at least we discovered it quickly.

But in the end, I know my approach is right. I'm proud to be a pragmatist.

Except when it comes to TCL. Man, I wish I could banish it from the world.....
blog comments powered by Disqus