We are not computers.
This is the most important thing to remember when we sit down to engineer. The machine running our code has gigabytes of RAM. It can hold a million variables in perfect suspension without breaking a sweat.
We cannot.
We have a "buffer" of about five to seven items. That is our Cognitive Budget. Every time we write a function that requires us to remember the state of a global variable, a flag passed three layers down, and a loop index... we use a slot in that budget.
When we exceed our budget, we start "dropping packets." We miss bugs not because we are bad at logic, but because we are physically incapable of holding that much context at once.
So, how do we stay within budget? We follow the Golden Rule of Engineering:
A function solves one problem.
But how do you know if you’ve broken this rule? You use The "And" Test.
The Diagnostic Tool: The "And" Test
Read the name of your function aloud. Describe what it does to your rubber duck (or your annoyed cat).
If you have to use the word "AND", you have likely created a monster.
- "This function downloads the file AND parses the CSV."
- "This component renders the profile AND fetches the history."
- "This script cleans the data AND uploads it to S3."
The moment "AND" enters the conversation, you are violating the Single Responsibility Principle. You are mixing concerns. You are creating code that is hard to test, hard to read, and terrifying to refactor.
The Junior Trap: The "Kitchen Sink"
Junior developers often think that packing logic together is "efficient." They create a Variable Soup. They mix "fetching data" with "sending emails" in the same 50-line block.
The Pro Move: The Orchestrator
A Professional knows that we don't want a "Swiss Army Knife" function. We don't want a hybrid tool that tries to be a hammer, a screwdriver, and a wrench all at once. It does everything poorly and is heavy to hold.
We want a hammer. We want a screwdriver. And we want a toolbox (the Orchestrator) to hold them.
The Code: Breaking the Chain
Let's look at a classic example of a function failing the "And" Test.
// Before (The "And" Monster)
Here, the registerUser function is doing two things: saving to the database AND sending an email. If we want to change the email template later, we risk breaking the database logic. This is dangerous coupling.
function registerUser(userData) {
// Logic 1: Save to DB
// We are mixing database implementation details...
const user = db.insert('users', {
name: userData.name,
email: userData.email,
joined: new Date()
});
// Logic 2: Send Welcome Email ...AND email implementation details.
// If the email server changes, this function breaks.
const emailTemplate = loadTemplate("welcome");
const subject = "Welcome to the app!";
mailer.send(user.email, subject, emailTemplate);
}
// After (The Orchestrator)
We split the concerns. The registerUser function is now an Orchestrator. It doesn't know how to save a user, and it doesn't know how to send an email. It just knows that those two steps need to happen.
function registerUser(userData) {
// The main function simply orchestrates the steps.
// It reads like a To-Do list.
const user = saveUserToDB(userData);
sendWelcomeEmail(user);
}
// --- The Tools ---
function saveUserToDB(userData) {
return db.insert('users', {
name: userData.name,
email: userData.email,
joined: new Date()
});
}
function sendWelcomeEmail(user) {
const emailTemplate = loadTemplate("welcome");
mailer.send(user.email, "Welcome!", emailTemplate);
}
Why This Matters
When we split code, we aren’t making "more work" for ourselves; we are organizing our toolbox.
- Testing is easier: I can write a unit test for
saveUserToDBwithout accidentally spamming my own email inbox. - Cognitive Load is lower: When I look at
registerUser, I don't see SQL queries and SMTP settings. I see the flow of the application. - Refactoring is safer: I can completely rewrite the email logic without touching the database logic.
Don't build Hammer-Screwdriver-Wrenches. Build simple tools, and let your functions do one thing well.
Stop writing code just to please the compiler.
This article was an excerpt from my handbook, "The Professional Junior: Writing Code that Matters."
It’s not a 400-page textbook. It’s a tactical field guide to unwritten engineering rules.
Top comments (0)