Code Smell - Premature Optimisation

Code Smell - Premature Optimisation

A common programmer mistake is spending time improving something that isn't needed. This results in wasted effort and extra complexity in the code and distracts the programmer from delivering value to the user faster. Furthermore, most software doesn't benefit from highly optimised code as modern CPU and RAM are powerful enough for general user usage. So instead, better use of time is to write 'OK performant code', focusing on clean and easy-to-enhance code. Then when you identify performance issues, fine-tune them.

"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimisation is the root of all evil (or at least most of it) in programming." -  Donald Knuth, The Art of Computer Programming

Here's an example of premature optimization in C#:

using System;

public class PrematureOptimization
{
    // This method represents bad premature optimization by using a loop unrolling technique to process a list of integers
    public void BadPrematureOptimizationMethod(int[] nums)
    {
        int i = 0;
        int n = nums.Length;
        for (; i < n - 4; i += 5)
        {
            nums[i] *= 2;
            nums[i + 1] *= 2;
            nums[i + 2] *= 2;
            nums[i + 3] *= 2;
            nums[i + 4] *= 2;
        }
        for (; i < n; i++)
        {
            nums[i] *= 2;
        }
    }
}

In this example, the BadPrematureOptimizationMethod uses a loop unrolling technique to process a list of integers in groups of 5.

While loop unrolling can offer some performance benefits, in this case, it is an example of bad premature optimization because it sacrifices readability, maintainability, and clarity for a small improvement in performance. Loop unrolling is an implementation detail that should not be exposed in the public interface of a method, and using it in this way can lead to bugs and errors that are difficult to diagnose and fix.

To rewrite this code for clarity, we can use a regular loop to process each integer in the array one at a time. Here's an example:

public class PrematureOptimization
{

    // This method represents a simpler and more readable implementation of the same logic using a regular loop
    public void SimpleMethod(int[] nums)
    {
        for (int i = 0; i < nums.Length; i++)
        {
            nums[i] *= 2;
        }
    }
}

This implementation is simpler and easier to understand and less likely to introduce bugs or errors. It also leaves room for future optimization, should it be necessary, based on real-world performance benchmarks and profiling.