What is Optimization?
Before going into details, it makes sense to ask what is Optimization? Let's understand this through an example.
Let's say you have a hundred heavy bricks down in your driveway, that need to be moved in to the back yard.
The way you do it now, you walk out, pick up one heavy brick, carry it to the back yard, drop it off, and repeat that step 100 times. It gets the job done, but it's time-consuming and takes a whole lot of effort.
How can you optimize this process?. Suppose you spot a wheelbarrow in the garage, and decide to use that instead. Push the wheelbarrow to the bricks, put all 100 bricks in the wheelbarrow, push the wheelbarrow to the back yard and drop them off.
You've accomplished the same goal, but by optimizing the process with the wheelbarrow, you've done it in less time and with much less effort.
Same idea is applied to computer code. Find places in the code that are not working efficiently (doing multiple loops through the same data over and over and over and over again), and re-write that little bit of code so that it is able to do the same thing in less time with fewer resources.
When and Where to Optimize?
Every optimization has a cost. Generally, this cost is expressed in terms of code complexity or cognitive load -- optimized code is rarely simpler than the unoptimized version.
As a programmer, your time is valuable. There's the opportunity cost of what else you could be working on for your project, which bugs to fix, which features to add. Optimizing things is fun, but it's not always the right task to choose. Performance is a feature, but so is shipping, and so is correctness.
This makes us rather question. Should you even optimize?
Yes, but only if the problem is important, the program is genuinely too slow, and there is some expectation that it can be made faster while maintaining correctness, robustness, and clarity."
-- The Practice of Programming, Kernighan and Pike
Just because something is easy to optimize doesn't mean it's worth optimizing. Ignoring low-hanging fruit is a valid development strategy.
How to Optimize?
1. Make your code work
Never worry too much about performance while you are writing code. Get it working first.
If it is too slow, then measure it to find the slow parts. You can use profiling tools for this, or just insert print statements with a timer variable.
Once you identify the sloth, you can decide what to do with it. This is the first step to optimizing your code. You can use language specific profiling tools to measure the execution of the code.
2. Functional decomposition
Functional decomposition helps us to divide a problem into several smaller problems. Every function solves a particular small task, and we can combine them to get the desired results.
If a pattern of code repeats several times, we know it's a sign that we need to move it into a separate function.
Another reason to apply function decomposition is readability and it helps test the program more conveniently.
3. Keep It Simple, Stupid (KISS)
KISS stands for making the code simpler for better understanding.
When developing software, creating a website or writing a block of code, strive for simplicity.
How do you do that?
- Functions should only do one thing.
- Variable and Function names should be descriptive.
- Good spacing (you have infinite space to work with, so no reason to bunch everything together).
- Write good comments, again there’s infinite space.
- Look at your code again in a few weeks. If it’s still easily understandable, pat your back you did a good job :)
4. Optimization Workflow
With today's computing power, performance can be dealt with by improving the organization's hardware.
Code should be primarily written for:
- Readability, which can be obtained by the KISS methodology.
- Testability, and it can be managed with Functional Decomposition.
- Maintainability, readability and testability of the code play a key role here. Additionally, the variables and functions should be named adequately.
Design Principles
There is no one design principle to follow when designing your program. Why? Because as your program grows, it becomes more complex. You will need to familiarize yourself with different approaches to help manage your program through different kinds of complexities. To make the path to our goals smooth, we can rely on Design Principles.
Design Principles help you to organize your code in a way that any other developer familiar with these principles can use and extend it. Applying them, you make your code more structured and clean, so it doesn't look like a maze anymore.
Summary
To make a high-performance program that we can easily maintain for months or even years, we should think about its design and optimization.