Frameworks of Failure

As programmers, we are always seeking to match great problems to elegant solutions. We want to solve a problem in a way that solves it forever. The larger the problem is, the greater our need to find that permanent solution. This thinking is what leads us to create hulking pieces of software that try to solve every problem but solve no problem well. These frameworks we create aim to be general enough to apply to an entire category, but lack the concrete details to be applicable to any specific need.

We build these frameworks because building them is more interesting than the actual problem we have to solve. Who wants to write the software to track auto parts in a warehouse when we could write a framework that maps relational data to object workflows? We could use that framework on any problem like that. We just need to add tens of thousands more lines of code tightly coupled to our framework. Too bad all we end up writing is a giant framework and a giant business logic layer to... track auto parts in a warehouse.

We mean well. It's not that we just want to complicate things. We actually intend to make things easier with a framework. We try to decouple the solution from the problem. We see a pattern and we wrap that up so we only deal with that once. Until we find out that the pattern wasn't really quite the pattern we thought it was. Maybe it wasn't even a pattern at all. We can just adjust the framework, tweak a few things, and now it works again. No problem, right?

We are trained to spot the patterns by everything that brings us into software development. We should spot patterns in mathematics. We should spot duplication in code. We should even group people based on similarities such as appearance or political opinion. We should see the pattern in everything because how can we live if we ever have to do the same thing twice? I've actually heard a developer ask a client, "But what is the general problem?"

Customers don't know what the general problem is. There may not even be a general problem to have. They may truly want something that is only used one way. Then the next day they may discover they need to use that something a completely different way. But until the next day, they don't know.

Customer problems are emergent. They are discovered in the course of business and cannot be enumerated on the first day. Internal and external factor drive their needs from moment to moment. Because the problems are emergent, our solutions should be emergent as well. We need to design the code in such a way that we can transform it to the next form it needs to be.

I've even fallen into this myself. The client asked me if I could put a message on their home page wishing visitors a merry Christmas. This was on a bit of short notice, two weeks before at most. I took this as a problem in need of a general solution, a framework for displaying message widgets on the site on any page. It was a clever framework, pulling in widget configurations for different message widgets. After all, there were so many holidays, and there might even be other types of messages to display. By the time I got it done in January, though, it didn't matter how clever it was. And I never had to display another message.

The simpler solution was to just edit the page content and put it in there. When it was no longer needed, I could simply remove it. I got caught up in a framework frenzy. I eventually removed the whole thing in a later code reorganization. I also learned to stop and think before I jumped to building another framework.


Popular posts from this blog

The Timeline of Errors

Magic Numbers, Semantics, and Compiler Errors

The Cone of Code Uncertainty