A Story About How Engineers Think, Not Just How They Code#
Written for Self-Taught Developers, Career Switchers, and Curious Recruiters#
Most people think programming is about knowing syntax.
It is not.
Programming is about how you think when the syntax is not there.
This article explains a very small JavaScript problem in a very intentional way. Not to show cleverness, but to show clarity of thought.
If you are a beginner, this will slow things down for you. If you are a recruiter or senior developer, this will show you how I reason.
Why I Am Writing This#
I come from a non-technical background. Before web development, my academic training was in the arts.
That background taught me how to break ideas into structure, observe patterns, and explain complex things simply.
Ironically, those skills are exactly what programming demands.
This blog is written the way I wish programming was explained to me when I started. It is a demonstration of method, not just knowledge.
The Problem Looks Small, But It Is Not#
The question is simple:
❝Find the smallest number in an array.
Most tutorials solve this in one line. That approach hides the most important part: the thinking process.
Inside this small problem live concepts used in real production systems: validating inputs, making assumptions explicit, comparison logic, iteration, and the separation of logic and UI.
Understanding this deeply once makes many other problems easier later. This is the power of foundational thinking.
Step 1: Understanding the Question Like a Human#
Before writing code, I stop and ask: What is really being asked?
From a computer perspective: input is an array, output is a number.
From a human perspective:
Do I actually have a list?
Are the values all comparable numbers?
What should happen if the input is empty?
What should happen if the input is nonsense?
Good code does not start with typing. It starts with good questions.
Step 2: Translating the Problem Into Real Life#
I always remove code first. Imagine this:
You recently moved to a new city. You are tracking daily expenses to control spending. Your notes look like this:
[120, 80, 200, 50, 150]
Each number represents money spent in a day. Someone asks: "Which day had the lowest expense?"
You do not think in terms of loops or algorithms. You scan, you compare, you remember. That natural, efficient reasoning is what our code should mirror.
Step 3: The Thinking Pattern the Brain Uses#
When observed closely, the brain follows a simple, optimized pattern:
Assume the first value you see is the smallest (or assume a very large number).
Look at the next value.
If it's smaller, update your assumption.
Repeat until the list ends.
Programming is not about inventing new logic. It is about making this invisible, intuitive process explicit and unambiguous for a machine.
Step 4: Validation Comes Before Logic#
Before comparing anything, we must check if comparison even makes sense. This is where robust software begins.
Case 1: The input is not a list.
Real-world meaning: You have one receipt, not a list. There is nothing to compare.
Code response: Return an error signal (e.g., false).
Case 2: The list is empty.
Real-world meaning: No data was recorded.
Code response: Return null.
Case 3: The list contains non-numbers.
Real-world meaning: Numbers and text cannot be compared meaningfully.
Code response: Return an error signal.
This validation step is where many beginner solutions quietly break. An engineer thinks about these edges first.
Step 5: The Core Logic in Slow Motion#
Let's walk through our expense list with human reasoning:
[120, 80, 200, 50, 150]
Assume smallest: Start with a very large mental placeholder (Infinity).
See 120: 120 is smaller than Infinity. New smallest is 120.
See 80: 80 is smaller than 120. New smallest is 80.
See 200: 200 is larger than 80. Ignore. Smallest is still 80.
See 50: 50 is smaller than 80. New smallest is 50.
See 150: 150 is larger than 50. Ignore.
Final result: 50.
Notice: we track only one value. We never look back. This is efficient, linear thinking, and it directly informs our algorithm.
Step 6: Translating Thought Into JavaScript#
Now we mirror our reasoning in code. No UI, no framework. Just pure logic.
Step 7: Why This Code Is Intentionally Boring#
Every line has a direct correspondence to a step in our thought process:
Array.isArraycheck -> "Do we have a list?"lengthcheck -> "Is there data?"Validation loop -> "Is all data comparable?"
let smallest = Infinity-> "Assume a very large number."forloop -> "Compare each item."return smallest-> "State the conclusion."
There is no clever trick here. That is the point. Readable, predictable code is maintainable code.
Step 8: Why Infinity Is the Correct Assumption#
In real life, if you want to find the shortest person in a room, you might start by looking at the first person. But in code, starting with Infinity is like imagining a person taller than anyone who could possibly walk in. The first real number you see will always be smaller, cleanly initializing our logic. It's a guaranteed, foolproof starting point.
Step 9: Separating Logic From UI#
In real applications, logic is reused. If we mix it with buttons and inputs:
Testing becomes difficult.
Bugs are harder to isolate.
Changing the UI risks breaking the logic.
Our findSmallestNumber function knows nothing about the DOM, React, or Tailwind. It simply takes an array and returns a result. This separation of concerns is a hallmark of mature software design.
Step 10: Turning Logic Into a Usable Interface#
Now we build something visible. The user enters numbers, clicks a button, and gets a result. The core logic remains untouched, proving its reusability.
Step 11: React + Tailwind Implementation#
What This Exercise Actually Demonstrates#
This article was never about finding a minimum value. It was a case study in my approach to problem-solving:
Clarify First: I dissect the question before writing a single character.
Reason from First Principles: I translate the problem into a real-world analog.
Validate Assumptions: I explicitly handle edge cases before implementing "happy path" logic.
Separate Concerns: I isolate pure logic from presentation.
Prioritize Communication: I write code for the next person who will read it.
These are transferable skills across any stack or framework.
A Note for Recruiters and Senior Developers#
This is the thinking pattern I bring to unfamiliar problems. I value:
Clarity over cleverness.
Robustness over speed.
Maintainability over shortcuts.
I am not just looking for a solution; I am designing a system, even for a problem that fits in one line. This mindset scales from a simple function to a complex application.
Closing Thought#
My background in the arts taught me to slow down, deconstruct, and find the underlying narrative. Programming, it turns out, is not about speaking to computers. It is about structuring human thought so clearly that a computer can execute it.
If this article made sense to you, then you already understand more than syntax. You understand how engineers think. And that is the hardest, most valuable part to learn.