When Is It Okay to Reinvent the Wheel in Programming?

One of the most common pieces of advice to new programmers is to not get “not invented here” syndrome and to not reinvent the wheel. Like most general rules of thumb, context is everything. While it’s pretty common sense to say don’t reinvent the wheel for the sake of reinventing the wheel, where do you draw the line between doing something the same but different enough to matter, and where do you draw the line between academic exercise and inertia?

Every programmer is going to end up trying to reinvent the wheel at varying levels. In the beginning, you’ll most likely learn your new language by copying. As you advance, you will recreate code from similar examples until you internalize the concepts enough where something like a programming cookbook is a good reference (but not strictly necessary). The problem shows up when you try to make something from scratch which serves no real purpose.

Why Reinvent the Wheel When Programming?

There are only two good reasons to remake something when coding: to learn something, and because you can do it better. Luckily though, they’re very broad. Unfortunately, they’re also very broad.

Where do you draw the line between really learning and just writing code for the sake of writing code when you’re new to a language or programming in general? When does it help to copy code to remake something, and when is it a lack of understanding of the process or algorithm? Is copying something from a book or a tutorial helping you or is it an excuse to write the method and shape it because you don’t understand the steps? I could find the best excuses to copy something out to do something instead of admitting I didn’t know what I was doing and had gotten lost. Sometimes sitting and waiting is best.

How can you tell when you can do something better without actually trying? What happens when there are n standards? Someone tries to write a new one to unify them all and now there are n + 1 standards. Why do some win out and others just become competition to the existing ones? It all boils down to trying to define what constitutes the concept of “better”.

Both of these can be valid reasons to reinvent the wheel. It can help to learn a new skill (even if you’re going to fail at it). If nothing else, trial by fire teaches you what’s hot and what isn’t. When trying to change the fundamentals to make the whole process more efficient, a scientific approach is the difference between disappointment and deduction.

Reinventing the Wheel to Learn

It’s perfectly fine to reinvent the wheel to learn, but make sure you’re working on the right parts to get something out of the process. It’s a waste of time and effort to work on parts which you can get cheaper, use more easily, and get more out of from elsewhere. It might be worth rewriting quicksort, but is it worth rewriting a basic language feature which is more minutiae than meat? Probably not.

The first step to determining whether you’ll learn something is to try and plan out what you get from the given piece. A given task is going to have differing amounts of value depending on the learner’s level. If we look at quicksort, we get a potential for it to be a rote coding exercise for something like a job interview, to it being a good, general purpose sort implementing recursion at an intermediate level. Beginners will probably just copy code since it involves understanding data structures, Big O notation, algorithm use cases, recursion, and divide and conquer among other things.

You can also treat this as a standard distribution bell curve of skills. You have a specific level where you get the most gains for a given task, and then standard deviations of skills away (both more advanced and less) which dip drastically. Teaching multivariable calculus isn’t going to do much for an elementary school’s math class except confuse them. The same is true of technical challenges. Too easy is just busy work, but too hard and the eyes just glaze over.

Assessing Difficulty

I may write a JSON parser, but I’ll never try an XML parser (again). The failure from working with XML showed me what my limitations were and taught me how to better identify when a task is difficult. Though I got very little out of the coding except redundant experience with error handling and an insane level of conditional spaghetti, I learned just how hard XML was.

You can’t really know how to assess difficulty without learning better where you stand. What do you know and what don’t you? How hard is what you’re trying to do? Why can the computer figure out how to plot a graph like it’s nothing, but having it make sense of “The dog is brown,” is the holy grail of AI?

The earlier in the learning process you are, the less sure or less accurate you will be about where you are. You deal with a good bit of uncertainty one way or another. The only way to break through is to just try. You need to identify how to delineate what you know, and what you don’t know if you know or not.

Just like the difference between static and strong typing, we’re dealing with two axes which usually end up conflated. The two are similar, but the subtly is that between a night and an evening. The sooner you can differentiate them, the sooner you can focus on deciding whether a task is working for or against you.

Learning to Reinvent the Wheel

Intermediate learners tend to benefit the most by reinventing the wheel (at a non-trivial level). Beginners copy and learn by imitation, advanced learners learn theory and work through application to internalize it. When you learn a foreign language, you follow a similar pattern, but it’s much easier to test your input and output with a human who thinks like you and can provide instant feedback. A computer doesn’t think, it does. Why’d that operation fail? You need to figure out which part failed and how to make the computer volunteer that information.

A learner needs to get past the point of Dunning-Kruger at the intermediate level to really test the water. Where do you lie in your path towards the language and towards coding in general? If you know a bunch of languages, but can’t get past spaghetti code, you might be advanced for language features but stuck for actual computer science. If you only know one language and use the same few structures to implement even the most complicated ideas, you might be stuck with the language but more advanced.

Reinventing the wheel and being mindful of the process will tell you which you’re at if you average out to “intermediate” for a given task in a given language. Are you good at the language or good at the problem solving? How do you know? Learning is an iterative process, reinvent the wheel to learn if you’re stuck at the actual woodworking or putting the pieces together.

Reinventing a Better Wheel

Sometimes, it’s worth reinventing the wheel when you can do it better. Tires basically haven’t changed for a century, but there are people who want to use new materials to make airless tires. The process costs more and lacks the efficiency of standard pneumatic. Are they better or worse?

No one knows until they iron out all of the kinks for producing them. No one knows until we see where the technology goes and how it holds up in real world usage. You don’t push your program to a beta until you have someone testing it, likewise, you can’t tell when something is better until it faces a real test.

This process works on smaller scales as well. Can you build a better mouse trap? You won’t know for sure until you try, but at the same time you can also look at what others have done which has failed. Why did one succeed and the others fail?

You have to understand what makes the original work in the first place to have any chance of improving the design. A square wheel is a waste for virtually any scenario. It might be common sense to see why the square wheel doesn’t, but it can be a lot harder to figure out why your new cryptographic algorithm is weak.

Time Versus Time Wasted

Failure is a painful lesson. You learn something, but you tend to walk away without much to show from it but experience and wisdom of what not to do. Knowing my goal isn’t due east doesn’t mean it isn’t northeast or southeast, and doesn’t help figuring out whether it’s north or south let alone west. I’d rather someone else did the painful legwork and build off of their success.

A failure which is taken in stride can still be valuable, but I’d much rather aim for success. When I write, I don’t base my work off of my failures anymore. I base it off of what succeeds unless I have a constant string of failures (but this goes into the knowing what you know and what you don’t). Look for the commonality of what works versus what doesn’t.

When you sit down with an algorithm, or a module or library, is it worth your time to reinvent the wheel? What went wrong with previous versions? Why are you doing it? You need to be able to answer all of these or you are just spinning your wheels. While I technically can write an XML parser at this point, I’m not going to do it better than the current solutions (or solve a new problem), and I’m not going to learn anything of particular use from the process. That makes it a dead end in all respects and a waste of time.

Moving Forward

Both of these factors are essential to make reinventing the wheel more than an exercise in futility. It’s rare when both overlap, but it can happen. You have to know what you’re working with, and what you’re missing in order for this to work out however.

When you’re learning, where are you (objectively), and where are you going? If you can’t answer this, how can you get to where you can? It’s useless to know you need to go west if you don’t know where the roads go and what direction you’re facing.

Don’t reinvent the wheel without a plan to figure out what makes a good wheel or without knowing where you stand in the industry. Dreams can take you far, but you don’t jump off a building because you dreamt you could fly. Be honest and realistic with your goals. If it’s going to teach you or prove productive, reinvent the wheel, but don’t do it because of a misguided attempt to improve something without understanding how it works.

Feature image by Susanne Jutzeler, suju-foto from Pixabay