It’s fun to think of great moments in the history of science, particularly the ones that have a memorable anecdote attached to them. In the 3rd century BC, a naked Archimedes ran down a city street, screaming Eureka, because he had discovered, in a flash, how to measure the volume of irregular solids. In the 1600s, a fateful apple bonks Issac Newton on the head, causing him to spit out the Theory of Gravity. In the early 1900s, another physicist is sitting around, contemplating the universe, when out pops E=MC^2.
These stories all share two common threads: they’re extremely compelling and entirely apocryphal. As such, they make for great Disney movies, but not such great documentaries. Point being, we as humans like stories of “eureka moments” and lightning bolt inspiration much better than tales of preparation, steady work, and getting it right on attempt number 2,944, following 2,943 failed attempts.
But it goes beyond just appreciating the former type of story. We actually manufacture them. Perhaps the most famous sort of example was Steve Jobs’ legendarily coy, “oh yeah, there’s one more thing” that preceded the unveiling of some new product or service. Jobs and Apple were masters of “rabbit from the hat” marketing where they’d reveal some product kept heretofore under wraps as though it were a state secret. All that is done to create the magic of the grand reveal — the illusion that a solution to some problem just *poof* appeared out of thin air.
With all of this cultural momentum behind the idea, it’s easy for us to internalize it. It’s easy for us to look at these folk stories of scientific and product advancement and to assume that not having ideas or pieces of software fall from us, fully formed and intact, constitutes failure. What’s wrong with us? Why can’t we just write that endpoint in one shot, taking into account security, proper API design, backward compatibility, etc? We’re professionals, right? How can we be failing at this?
You might think that the worst outcome here is the ‘failure’ and the surrounding feelings of insecurity. But I would argue that this isn’t the case at all. Just as the popular stories of those historical scientists are not realistic, and just as Apple didn’t wave a magic wand and wink an iPod Nano into existence, no programmer thinks everything through, codes it up, and gets it all right and bulletproof from the beginning. It simply doesn’t happen.
Paralysis By Analysis
As such, the worst problem here isn’t the ‘failure’ because there is no failure. Not really. The worst problem here is the paralysis by analysis that you tend to face when you’re caught in the throes of this mindset. You’re worried that you’ll forget something, make a misstep, or head in the wrong direction. So instead, you sit. And think. And go over your options endlessly, not actually doing anything. That’s the problem.
I’m sure there is no shortage of articles that you might find on the internet, suggesting 6 fixes for paralysis by analysis. I won’t treat you to a similar listicle. Instead, I’ll offer one fix. Solve small problems.
Progress Through Scaling Down
Building an service endpoint with security, scale, backward compatibility, etc, is a bunch of problems, and none of them is especially small. You know what is a small problem? (Assuming you’re using Visual Studio) Creating a Visual Studio solution for your project is a small problem. Adding a Web API project (or whatever) to that solution is a small problem. Adding a single controller method and routing a GET request to it is a small problem. Getting into that method in the debugger at runtime is a small problem. Returning a JSON “Hello World” is a small problem.
If you assembled these into a list, you could imagine a conceptual check mark next to each one.
- Make a solution file.
- Add a project.
- Add a controller.
- Hit controller at runtime with GET request.
- Return JSON from controller.
There’s no worrying about aspects, authentication, prior versions, or anything else. There’s only a list of building blocks that are fairly easy to execute, fairly easy to verify, and definitely needed for your project.
The idea here is to get moving — to build momentum without worry and to move ahead. There are two key considerations with this approach, and they balance one another. They’re also ranked in order of importance.
- Don’t let yourself get stuck — pick a small, needed problem to solve, and solve it.
- Do your best to solve your problems in a non-limiting way.
The first is paramount because you’re collecting a paycheck to do things, not to do nothing. Or, to be less flip about it, progress has to come. The second item is important, but secondary. Do you best to make progress in ways that won’t bite you later.
For an example of the interplay here, consider one of the aspects that I’ve been mentioning — say security. At no point during the series of problems on the current to-do list is security mentioned. It’s not your problem right now — you’ll address it later, when the first step toward security becomes your problem on your list. But, that doesn’t mean that you should do something obtuse in solving your problems or that you should do something that you know will make it harder to implement security later.
For me, various flavors of test-driven development (TDD) are the mechanism by which I accomplish this. I certainly recommend giving this a shot, but it’s not, by any stretch, the only way to do it. As long as you’ve always got a way to keep a small achievable task in front of you and to keep from shooting yourself in the foot, your method should work.
The key is to keep moving through your checklist, crossing off items, and earning small wins. You do this by conceiving of and solving small problems. If you do this, you may never become Disney Archimedes or Einstein, but you won’t have to pull a Steve Jobs magic act during your next performance review to secure a raise against all odds. You’ll already have it in the bag.