If someone told you a project you’re working on is “without a deadline, just make sure it’s perfect”, how long do you think it would take you to finish it?
“Depends on a project” is probably what you’re thinking right now, and you’re wrong.
The answer is plain and simple: without a defined due date, you’d be optimizing that code forever.
At first, you’d think they’re doing you a favor by not pressuring you into getting that code over the finish line. When in fact — they just handed you a shovel to dig your own grave.
In its essence, optimization should be a good thing. Still, if performed prematurely or excessively, it can cause more damage than good.
We’d like to take this chance to draw your attention to a few things we’ve realized over the years and warn novice developers of the biggest traps we’ve fallen into over the years.
What is code optimization?
In computer science, code optimization refers to (re)writing code to ensure maximum software performance. The goal of the code optimization process is to use a minimal amount of memory or disk space, reduce CPU time or network bandwidth, or make the best use of additional cores (threads).
In other words, an optimized code is the one that consumes minimum resources for program execution. It is considered a requirement for achieving optimal software quality.
3 most common code optimization myths
Unfortunately, more often than we care to admit, we focus so much on polishing up every aspect of the code that we set ourselves (and the project) up for failure.
From Inviggo’s senior developers to our junior colleagues, here are the three biggest code optimization misconceptions and mistakes you have to stop making right now.
- Less is more
Attention to detail is a much-appreciated trait, but don’t overexercise your ability to pinpoint everything that could benefit from a bit of string cleaning.
Stripping the code down to the bare minimum might prevent one of your teammates from taking over. Quite often, you end up trimming it down to the point where not even you are capable of deciphering the code. A good rule of thumb is to make sure the code is correct and clear enough so that you can easily communicate it to a junior colleague.
And it’s not just about it being too simple to understand; by optimizing one and the same lines of code over and over again, you run the risk of making changes that are so significant that they prevent optimal system execution.
- Perfection is imperative
There are simply too many things to address — coding efficiency, clarity, style, security, and runtime stability, to name a few. Each seems just as important as the next and, quite often, some need to take the hit while others are tweaked to perfection. One thing is clear: perfecting all is hardly an option. That is why the most skilled developers are not the ones who build a 100 percent flawless code; it’s the ones who know how to focus on the most important values.
In fact, some even suggest code optimization should be postponed until the relevant UX is implemented. This should help reveal the exact part of the code that needs your attention and stop you from wasting time on unnecessary edits.
Plus, you need to think about the real-life uses of the software you’re building and set the testing benchmark. Because, if you’re not sure what you expect in the first place, how can you know what needs optimizing and what’s good to go?
- Nothing is trivial
There’s actually something that we in development circles like to refer to as the Law of Triviality. We use the term to refer to all those times we spend discussing insignificant matters that don’t have a direct or immediate impact on the quality of the final result.
Micro-optimizations are put on pause for a reason. Namely, a top-down approach to optimization allows us to gain a broader understanding of the software we are building, detect bottlenecks, and measure them before we even begin to fix them.
Once you know the ‘important’ work is finished, you can redirect your focus to fine-tuning the performance of aspects you labeled as ‘secondary’ in one of the earlier iterations.
What do we do to avoid wasting a disproportionate amount of time on trivial matters? We always optimize the architecture first before moving on to algorithms and data structures.
- Prioritize inlining
Inlining refers to the process of replacing the line of code that calls for the function with the body of that function. In other words, you should put the function in the line of the code, and do it wherever it is possible in advance, ie. before optimizing anything else.
By combining the async and defer attributes on imported JS libraries/code, the browser will no longer block rendering during page loading. In practice, this prevents the ‘white screen’ from appearing the first few seconds after the visitor lands on the website. Ancynchronous or deferred JS gradually presents users with page content, which significantly boosts the UX.
Bonus tip: Include a small amount of CSS and JS code in <head> to load it right away, and keep the more extensive code in .js and .css files, as you normally would.
- Minify the code
As its name suggests, minifying means making the code smaller. Compressing the code helps hasten page load since all the comments, line breaks, and additional spaces will be smaller (and don’t worry, they will still be readable). Plus, minification prevents “dead code”.
- Prevent memory leaks
A memory leak happens when the software or an app doesn’t return memory back to the underlying OS after it stops using it because the runtime still believes you need it. To avoid this waste of resources and maximize performance, you can check if there are any:
- accidental global variables that are not automatically cleaned by the JS’s garbage collector;
- outer-function variables stuck in closures;
- detached DOM references that remained retained in memory even after you removed a node.
Bonus tip: Limit the number of variable calls and see if you can achieve the same result by taking a different approach to writing a function.
- Reduce large DOM trees
Reduce the size of the DOM when optimizing front-end to improve loading, network efficiency, and runtime performance (this will also help with the previous point — reduction of memory leaks). Some of the best ways to trim down a large DOM include simplifying CSS rules, minimizing its references, and/or staying away from complex animations.
- Split the code
By splitting the code into smaller files across functional components, you avoid loading one large JS file. Instead, only what is necessary for a specific function or a feature loads. Don’t worry, there are tools you can use (with Webpack being our personal favorite).
- Test it!
While this one’s a given, the list didn’t really feel complete without saying it. Set the KPIs early on and test the code to see how it measures up with your standards. You could try:
- console.time() to test performance speed,
- JSFiddle.net for bug reporting, demoing code snippets and sharing them, or
- YSlow to compare your code’s performance against industry benchmarks.
Code optimization was the topic of multiple debates; every developer has (pretty strong) opinions on this topic as years of practical work taught them a thing or two about what (not) to do.
We’d like to hear your thoughts on this — any myths you debunked over the years? Skills or optimization techniques you’ve learned and now apply to most projects you’re working on?
We at Inviggo are proud to say that we have built a teaching environment where we often welcome and train ambitious juniors. At the same time, we’re also the ones who always strive to learn new things and advance our skillset.
So don’t hesitate to reach out and start a conversation about code optimization (or any other interesting topic, for that matter!)