A Beginner’s Tale of Over-Engineering

Angelo Xenakis
5 min readMar 30, 2020

--

When I first started programming, a senior developer on our team (the most senior developer, to be precise) gave me two pieces of advice that really stuck with me. More on that in a sec, but first, let’s set the stage.

I was a Scrum Master and UX/UI Designer, eagerly trying to break into coding however I could. I asked the engineers for projects that they either did not want to do, or did not have time to do, in order to get them to say yes to letting me thrash around in our codebase. As a result, I was given the glamorous opportunity to write our JavaScript based integration tests in a framework we recently adopted called Cypress.

I knew little about the real fundamentals of object oriented programming, but had a decent grip on how JavaScript could be used to interact with our web app and a few example tests that were written by our front end team. Honestly, I was just really exited to be writing lines of code and pushing them up to a codebase that people were actually paying money to use, and I became pretty enthralled.

That senior engineer would pass my desk to see me spending hours crafting tests in Cypress when I probably should have been organizing scrum rituals or designing specs for the real devs. We were walking out to the car together one evening when he said, “Hey, I can tell you’re really enjoying this. If I could give you any advice, it would be to take your time reading the documentation (because duh), and take the long route to over engineer your code for the problems you’re solving. Your bosses are not going to like that second part, but you’ll learn a lot.” I didn’t really know what he meant at the time, but I was willing to trust that it was good advice. So I filed it away to the “important” folder in my brain, and saved it for a day when I understood what the hell I was doing.

Fast forward a bit to truly digging in and learning Ruby. Like many people learning an object oriented language, you start with basic concepts like variables, methods, and loops; then move into slightly deeper ideas such as class objects, how to create object relations, more complex enumerators, and so on. As concepts started to build on each other, his advice became abundantly clear.

I am aware that this is not an enlightening revelation of Bhagavad Gita level proportion, and most engineers probably understand you should learn how to write a traditional while loop before blasting off Ruby’s built in weapons of choice (and who doesn’t love mindlessly setting the value of i a countless number times?). That being said, we all have tools we become comfortable with, and once you know a path to the solution it is often hard to imagine moving outside of it to find a better way or increase your understanding.

A very, very basic example: as I was getting a handle on the aforementioned iterators Ruby so kindly provides, I grew attached to the .each method. I had projects I was working on in which every individual iterator used only .each, and manipulated the data output after the fact. Good times. I then began to see the power of, and utilize the other usual suspects. You know the gang: .map, .select, .find, etc... With great power comes great responsibility, and I began to go shorthand crazy. Getting ahead of myself with handfuls of functions sans testing, realizing I had been chugging along for far too long without seeing if this thing worked. Finally, I would run my code to find all sorts of banana peel outcomes. The funny thing is, after tons and tons and tons and tons (and three more tons) of troubleshooting, I often found that rewriting my wonky misplaced enumerators with the chunkier and less ambiguous .each (advice point no.2) gave me a much clearer idea of what I was trying to do with my code. That allowed me to read up on the docs (advice point no. 1), and find new solutions that could shrink the weight of my code down once I had executed the desired outcome.

The anecdote above is an example of realizing this lesson in the baby steps of my software crafting journey, but this concept can be applied no matter how complex the problem you’re working on becomes. The “gotchya” is that as our tool belt becomes more deadly and efficient, we depend on it when faced with new and harder challenges. This fact makes the whole “lazy engineer” cliche come to life, and prevents us from over engineering (which will then lead to new ways of thinking and utilization of tools). Our jobs, bosses, peers, and timelines often discourage us from taking this route in the noble and valorous name of productivity, but when you can, take a moment to dive down the over engineered rabbit hole and see where it leads you.

If getting straight to working code is like hopping in a sports car and slamming that pedal into the coarse carpet beneath it, over engineering can be like popping the hood, reading the take apart on how the engine works, and gaining a good idea of when to press that accelerator and when to let off to switch gears. It takes a little more time, but you treat the car better in the end because you have more knowledge. Isn’t that why we got interested in learning how the code worked in the first place?

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Angelo Xenakis
Angelo Xenakis

Written by Angelo Xenakis

Software Engineer, Designer, Artist, Musician, Kickboxer

No responses yet

Write a response