Is this problem hard, or am I trying to solve the wrong problem?
Before I had my first programming job, two friends and I wanted to build a start-up-style, I have an idea for an app lets buy a domain name, kind of business. Long story short, we had a good time, but didn’t really get anywhere. I’ll leave most of the details out, since they’re not pertinent to this story, but I’ll share one episode.
I had bought a book about building your own website (I think it was focused on LAMP stacks, and we were using IIS because one of us knew C#, but anyway), and this book had mentioned something about sign-in cookies and not storing cleartext passwords. It was good advice, but I completely missed the point. After I read this book, and we wanted to build a mobile app, I started trying to write, from scratch a system for letting people sign into websites. In .NET. Pretty recently.
No, that’s a hard problem. But it turns out, I was trying to solve the wrong one. The problem I was trying to solve wasn’t the general, “how should we make difficult to guess cookies” and “how should we store salted, hashed passwords.” It was actually just, “how do we tell the .NET framework, which was built by smart people who already know how to do these things, that we want a website where users sign in.” I was reinventing the wheel.
I have learned a little bit about building websites since then, but that instance of reinventing the wheel seems to me like an instance of a pattern I see a lot: Making your life hard by solving the wrong problem. But what do I mean by “the wrong problem?” I mean, if I’m solving the wrong problem sometimes, having a procedure for converting wrong problems into right problems would be pretty simple.
Eric Lippert wrote about this too, in a less direct way. (Note: I’m about to spoil the punchline of a 5 part blog series. If you want, read the series first and then come back. I’ll wait.) Anyway, in this series, Eric proposes a simple programming problem, a game where we have wizards, warriors, swords, and staves. Basically, a wizard and a warrior are both types of player, and a sword and a staff are both types of weapon, so we go off and start building our object hierarchy. Then Eric asks, quite reasonably, “how do we represent the rule that a wizard can only use a staff and a warrior can only use a sword”? Mr. Lippert then shows us a half dozen increasinbly perilous and clever attempts to make C# represent this rule, but because all the attempts are centered around the type system, they all amount to “A player wielding a the wrong weapon will throw an
InvalidCastException, or something like it, at runtime. That’s not much help, because the whole point of having a compiler is that it keeps us from making certain runtime exceptions. So how does Eric propose we resolve this:
The fundamental problem is my initial assumption that the business rules of the system are to be expressed by writing code inside methods associated with classes in the business domain.
I wonder if his explanation for why the poor people implementing Wizards and Warriors are on the wrong track has anything in common with why my first attempt at building a web start up was on the wrong track.
I think that what the two situations have in common is that they both have someone trying to solve a problem while working under a mistaken assumption that actually makes the problem harder to solve. I was trying to solve the problem of letting people sign into my website, and working under the mistaken assumption that I had to write all the relevant code myself. When the poor (imaginary) team on Warriors and Wizards was trying to get their application to run, they were working under the mistaken assumption that all the rules had to be on classes that were named after physical objects in the game.
So, the next time you’re working on a problem that seems hard, or it seems like the tools don’t fit, ask yourself “what assumptions am I working under, and are they valid?”
Till next week, happy learning.