As a developer, I love optimizing performance. Learning efficient algorithms makes me feel like a software engineer. But performance is not the only developer concern, nor should it be the first or second. David K. Piano recently pointed this out on Twitter, offering up a suggested framework:
Make it work
Make it always work
Make it work for everyone
Make it right
Make it fast
David's suggestion expands on a well-known programming maxim attributed to Kent Beck, Make it work, Make it right, Make it fast. What does that mean? I want to take some time to expand on each layer.
Making working code is the first concern. This step may seem obvious, but there are a few things to consider as you make the code work.
First, consider a test-driven development approach. At the very least, wrap your code in tests as you write. This will make the rest of the process faster and ensure you don't break core functionality.
Second, don't worry about writing pretty code. If you find yourself debating what to name a variable, call it
thing1 and move on. Use formatting tools like Prettier to avoid thinking about white space and semicolons.
Finally, try to go fast here. You only need working code. If you hit a roadblock, start over. Writing sloppy code at the beginning can help you arrive faster at a better solution.
Now we shift our attention to edge cases, cases involving less-common or unique data sets. These are the areas where bugs tend to show up. Here are some scenarios you might want to consider:
- No data
- A single piece of data
- The maximum amount of data
- One less than the maximum amount
- Bad (malformed) data
If your code involves asynchronous calls:
- Rejected promises
- A promise that never resolves
- Slow responses
- Immediate responses
Again, take the time to write tests. Whether you follow test-driven development or write tests after the fact, they will be invaluable as you move up the layers of concerns.
There are two approaches to supporting multiple environments: progressive enhancement and graceful degradation. Both involve detecting feature support, but progressive enhancement adds functionality while graceful degradation removes functionality.
Both approaches are viable in different scenarios, and which you use depends on the context of the functionality.
The next layer of focus is making the code right. Right means making the code readable and maintainable. All of the tests written up to this point pay off by giving you confidence that functionality remains.
Developers read code much more than write it, so taking the time to make your code readable will help your colleagues and your future self. Readable code is more maintainable and extendable. The small cost of refactoring now can have an exponential impact on future project development.
Focus on small changes that make a noticeable impact. Use domain-specific variable names, ensure your functions are in the correct scope, use comments as indicators for creating functions. I recommend reading Martin Fowler's excellent book Refactoring for more specific guidance and practical advice.
After we've made the code work, considered edge cases, added fallback support, and made the code readable, we finally optimize performance. Maybe.
The first rule from the Rules of Optimization is don't optimize. If you must optimize, however, there are a few things to keep in mind.
First, make sure you are testing production code. Many frameworks bolt-on functionality and tools that help the development process but hinder performance. Production builds exclude this extra functionality, so ensuring you are testing in the right environment keeps you from optimizing performance unnecessarily.
Next, you need to get baseline measurements. These will ensure that your optimizations worked. If possible, emulate slow internet connections and throttle CPU speed, two features Chrome's devtools offers.
One thing to keep in mind as you optimize is how your optimizations may affect the readability and maintainability of code. Usually, the most optimized solution is nowhere near the most readable. Always favor readable code.
Performance optimization makes sense to developers because it's something that's easily measured. Optimizing code may be a more attractive goal than finding edge cases or making code more readable but should be avoided until the end of the process. Optimizing at the very end forces developers to focus on writing working, maintainable code.
So, thanks for making it to the end! If you found this helpful, please let me know by liking this article on DEV Community and following me to know when I post a new article. And ask me all the questions you'd like (preferably about this article, but no judgment) on Twitter.
Until next time!