Pragmatism Over Purity

What the last 20 years of programming frameworks has taught me.

One of the best things about running D4 is the sheer number of different projects we get to work on. While some projects allow us to choose our technology platform, others require us to get to grips with something else. Sometimes it’s something new that we haven’t used before.

Since the early days of my writing C64 BASIC in my bedroom (and dreaming of writing the next ‘Civilization’ game) I’ve used a massive variety of different technologies, with varying degrees of intensity. My technical career history looks roughly like this:

My career history: in languages & frameworks

Here are some things I’ve learned along the way…

Things that helped a lot…

Automatic Memory Management

I used to work in a team of C++ programmers. We laughed at the VB guys. We thought they were wimps for writing code in a “beginners” language. We understood pointers, which made us macho.

The thing is, they got a lot more done than us, and the business loved them for it. The reason:they weren’t doing the whole “are you going to allocate some memory or shall I?” dance every time they wanted to call an API.

A Package Manager

In the beginning there was C, and C had a set of libraries that you could call. And that was your lot. If there’s wasn’t a standard library API for it, you had to write your own function.

Then one day people started releasing libraries and the notion of “DLL hell” was born.

But then Perl came up with CPAN, and Ruby had GEMs, and we saw the light. Languages that let me install a library and have it just work, with one command, make it easier to get things done.

Duck Typing

I really don’t care about strong typing. I have a thing here and it quacks. And you have a function that needs something that quacks. And that’s all that should matter.

Seriously: without duck typing, you end up with interfaces, and then you write code against interfaces, and suddenly, I can’t do right click, “go to definition” in my IDE any more because I just end up at the interface not the actual thing. And that may sound trivial, but it really makes a difference to me getting things done.

Generics / Templates

If I can’t have duck typing, at least let me have compile time variables. So I can write code once, that works on for multiple types.

Database Migrations

Before frameworks came with migrations, I used to implement them myself. Because software development is not just about me sitting at a desk and writing code, it involves managing multiple environments, multiple version, sometimes multiple branches, and coordinating between multiple developers, who each need a database on their local machine. And being able to pull code from source control, run a command and get a working database, is a huge win.

Things that don’t matter


Assuming you have a learnable and consistent way of writing a function, a function call, an if, a loop, an expression, and a package import, I’ll be ok.

Object Orientation

VB made you way more productive than Visual C++. Why? Both had drag and drop visual designers. Both had access to the Windows APIs. The syntaxes weren’t all that different. VB didn’t have object orientation. But it did have automatic memory management. That’s what made the difference.

Excessive Magic

ASP.NET WebForms tried to hide the stateless nature of the web from the developers. It failed. Then when Ajax came along they invented this thing called the UpdatePanel that tried to hide a bunch of Ajax callbacks from the developer. And things would sort of work for a while, until one day you did something simple like add a button on the page, and suddenly everything went crazy and broke and you had no idea why.

Angular is the same. All that dependency injection, template loading and clever conventions-based behaviour. It’s all so pure and minimal, until something strange happens and you’re tearing your hair out trying to figure out why.

Unix had the right idea. Do one thing well. Fit in with everything else. Don’t be a smarty pants.

Micro Services / Service Oriented Architecture

So you’ve decided to solve a problem with a service, and what you’ve done there, is take what should be a function call, and given it its own server. Which is fine, I guess. I understand what you’re trying to do. It’s all about separation of concerns, and scaling, and so on. But that server has to be deployed to, and versioned, and monitored, and secured.

If you’re Google and you have a gazillion users, there’s a justification for that. But really, you’re not Google, just make it a function call.

Weak typing

Dynamic typing is ok. But not weak typing. Why would I explicitly not want the compiler/interpreter to tell me that I’m treating an Integer as a Date? What benefit would not telling me bring?

Favour pragmatism over purity

Frameworks are often opinionated. In the sense that they are built with a particular mental model for how software development should be done in mind.

In the case of Java, Steve Yegge says it better than I ever could. To summarise, Java naturally leads you towards lots of layers, and lots of classes with “Manager” and “Factory” in the name. Java sees this kind of object orientation as the way to enable lots of people to maintain the same code effectively.

Python opinions are explicitly published, for which I respect it greatly.

Rails was built by the Basecamp team. A small group of very good developers who favour a particular form of simplicity.

These opinions matter. Because they affect the kind of trade-offs that the technology makes between learning, developing, deploying, maintaining, and supporting it. To butcher a famous quote: We shape our frameworks, thereafter, they shape us.

One particular trap that developers often fall into is to mistake conceptual purity for usability. Git is the perfect example. I use Git every day and I love it. But I learning it was hard work. I understand that conceptually it’s quite clever and pure but I don’t care, and I don’t believe it helped me learn it.

I just memorised a set of commands that mapped to real world tasks that I needed to get done:

  • Remember this particular version of the code: git commit -am “Description”
  • Send this code to everyone else: git push
  • Get other people’s code: git pull

I guess you could sum up a lot of my opinions about frameworks as “Favour pragmatism over purity”. I have no time for technologies that try and slow down the process of learning, developing or deploying the code because it didn’t seem neat and tidy to the original developers.

We are here to ship features to users, that is all.

Daniel is managing director at D4, a software studio in Birmingham, with clients all over the UK and further afield.

As well as producing software projects for a wide range of clients from enterprise through to startups, we also have our own in-house products; QueryTree — a visual reporting tool for product managers, and SQLizer — a database migration tool for developers.

Topics of interest

More Related Stories