Early in my career at the EdTech AI startup Titanom Technologies, I had the opportunity to sit down with the CTO during my onboarding. Excited to dive deep into coding, I asked him for his best advice on becoming a better software engineer. His response, casual yet incredibly impactful, has stuck with me ever since: If you keep your functions small, you'll become a 200X engineer.
At first, that number sounded like a joke. However, as I began auditing various codebases in search of tricky bugs, I soon realized I was quickly becoming mentally exhausted. Oddly, the fatigue wasn’t due to complicated logic; it was something simpler yet strangely overlooked — readability.
Intrigued (and admittedly a little annoyed), I started exploring what exactly made some code visually exhausting and mentally draining. It turned out that visual complexity, more than anything else, was the primary cause of this cognitive overload.
Today, I would like to share the results of that investigation with you. By the end, we’ll identify three observable properties that developers of any language can use to boost the readability and maintainability of their code significantly.
Let us take a step back in time to when the challenge of software complexity was as pressing as it is today.
#Halstead Complexity Metrics 🏆
In the late 1970s, Maurice Halstead developed an innovative method for measuring the complex of source code — what we now refer to as Halstead Complexity Metrics. The cool thing about Halstead’s approach is that it’s pretty universal, meaning it doesn’t matter which programming language you’re using; the metrics apply just the same. Rather than diving into the intricacies of the underlying algorithms, Halstead focused on something simpler: how clear and efficient the actual code appears.
Halstead built his system on four straightforward counts:
-
Number of distinct operators (
n1
) -
Number of distinct operands (
n2
) -
Total number of operators (
N1
) -
Total number of operands (
N2
)
From these basic numbers, Halstead created a handful of interesting metrics, such as program length, volume, and difficulty. He linked them through a set of simple equations, and his ambitious goal was to use these numbers to estimate the number of bugs that might be lurking in your code.

Of course, these metrics aren't perfect—after all, they were developed in the 1970s and have faced some criticism since then. Still, they provide a helpful starting point. Intuitively, the more operators involved, the more challenging it becomes to manage interactions mentally. Similarly, when there’s a larger number of operands, keeping track of how data flows through the program becomes increasingly challenging.
#Halstead Complexity: A TypeScript Case Study
Let’s see what Halstead’s complexity metrics look like with some real Typescript code. We’ll take a simple function and write it in two different ways—one very straightforward and the other a bit more “clever” with extra moving parts. This simple example will help us see how the numbers for Volume and Difficulty change based on how we write our code.
The first function is more straightforward, resulting in lower volume and difficulty scores. The second function, while functionally equivalent, introduces additional constructs that increase its complexity metrics. This comparison illustrates how different coding styles can impact the cognitive effort required to understand code.
#Halstead Complexity Takeaways
Keep your functions small and your variables to a minimum—code is just easier to read that way. If you’re adding extra variables for no good reason, you’re trolling anyone who has to read your code later.
Avoid overusing language-specific operators or complex syntax tricks. Every extra construct is just another hurdle for the next reader. (If you don’t believe me, try making sense of someone else’s old Perl or Ruby scripts.)
Use functional constructs—like map, reduce, filter, or endless lambdas instead of imperative loops for mroe apparent intent and cleaner code. However, moderation is key. Excessively chaining or nesting these constructs might seem clever and concise at first glance, but it quickly becomes cumbersome to follow. This pattern is notably prevalent in JavaScript, Rust, or when Python enthusiasts get overly ambitious with itertools.
For a humorous yet insightful take on code complexity, I recommend A layman's guide to thinking like the self-aware smol brained, which distills many of these principles into practical, memorable advice.
