It's tempting to write imperative code because it can be easier to understand and write, especially for those who are new to programming. But let's be real, who wants to be a newbie forever?
Here are some reasons why you should avoid imperative code, even when using classes, object-oriented programming (OOP), or functional paradigm.
Just because you're writing in "hipster functional" languages or "old school" OOP languages, people will always find a way to add imperative spaghetti code. It's kind of amazing, really.
Imperative Code is Harder to Maintain and Debug
Imperative code often relies on a lot of explicit details and state changes, which can make it difficult to understand the overall flow of the code. This leads to more, harder-to-fix, bugs.
Debugging imperative code is like trying to find a needle in a haystack, except the haystack is on fire and the needle is actually a piece of spaghetti. Good luck with that.
Imperative Code is Less Flexible and Reusable
Imperative code often focuses on how to accomplish a specific task, rather than on the overall logic and abstractions. This can make it harder to adapt the code for different use cases or to integrate it with other code.
Trying to reuse imperative code is like trying to fit a square peg in a round hole; it might work for a little bit, but eventually, it's going to cause more problems than it solves.
A Better Approach: Declarative Code
Declarative code focuses on what the code should do, rather than on how to do it. Declarative code is often easier to understand, maintain, and reuse because it relies on abstractions and high-level logic.
Hey, let's be real, the problem is not really using imperative code, sometimes the brute force solution is the best... first solution. After it works, you then refactor it to make it better. (And maybe/probably before that, you would test to make sure you're not breaking anything.)
For example, rather than writing code that defines every step in detail, mutating variables and states, you can use higher-order functions and immutable data structures to define the logic of your code.
Here are some examples of imperative and declarative code using TypeScript:
Imperative code:
function findMax(arr: number[]): number {
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
console.log(findMax([1, 9, 5, 3, 7])); // 9
Declarative code:
function findMax(arr: number[]): number {
return arr.reduce((acc, cur) => (cur > acc ? cur : acc), -Infinity);
}
console.log(findMax([1, 9, 5, 3, 7])); // 9
Let’s compare
And I'll first start with the declarative one, and please do disregard the small detail of it being only one line. If you understand what reduce
does, then you know it starts with the lowest number
possible (minus infinity), and then you check which of the accumulator
or current
is larger and return the larger one.
Yes, you need to know a lot more beforehand; it's an upfront investment, and then you can easily read, understand, and debug the code.
(And yes, you could simply use Math.max
, but where would be the fun in that?)
Meanwhile... the imperative one. You start with a number, you loop through all of them, if it is bigger you change the max
variable, and when you are finished you return max
.
It's straightforward, it works, but wait... why did the loop start at index 1
?
Go read it back, I'm waiting...
Ah... We already started with index 0
at the max
variable.
See? Even in this short example, you have to pay double the attention. Now, check your most recent push for this type of spaghetti and beat yourself with your keyboard if you find any. You can also pester your pasta chef colleagues for the same, I hear mechanical keyboards make a nice sound when hitting heads (Yes, I tested and I know you will too. Please send videos.).
I can’t stress enough how much I hate imperative code
In conclusion, you write code once and read it every time after that. Not only that, I might be the one reading it and I don't really want to see what was in your head at that moment just to understand that piece of pasta code.
So, let's do us all a favor and just not use imperative statements, okay? Just remember that declarative code is like a well-oiled machine. It may take a little more effort to set up initially, but it will pay off in the end.
Cover Photo by Christine Sandu on Unsplash