# The Law of Loudness: Why Your Code Should Scream, Not Whisper

We have all been there. It is 4 PM on a Friday. You are staring at a stack trace that makes no sense.

The error is the classic JavaScript killer: `Cannot read properties of null (reading 'email')`.

You click the line number. It points to a React component trying to render a user profile. But the code looks fine. The `user` object should be there. Why is it `null`?

You trace the data back. It comes from a helper function. That helper calls a service. That service calls an API utility.

Five layers deep, you find the culprit. A function named `getUser`. It encountered a database error, but instead of telling anyone, it quietly returned `null` and let the application keep running.

This is called **"Passing the Buck."**

It is the single hardest type of bug to debug because the *symptom* (the crash) happens five minutes and ten files away from the *cause* (the database failure).

Today, we are going to fix this using **The Law of Loudness**.

### The Junior Trap: "Zombie Mode"

As Junior engineers, we are terrified of crashing the application. We think that a crashing app is a failed app. So, when we write a function and something goes wrong (the DB is down, the API timeouts), our instinct is to catch the error, sweep it under the rug, and return a "safe" value.

We return `null`, `false`, or `-1`.

We enter **Zombie Mode**. We keep the application walking around half-dead.

> **The Silent Failure**
> When you return `null` silently, you are not handling the error. You are outsourcing the error handling to the function that called you.

Now, every single place that uses your function *must* remember to check for `null`. If even one developer forgets? The app crashes later, and nobody knows why.

### The Pro Move: The Law of Loudness

Senior engineers follow a different rule: **If a function cannot do what its name says it does, it should throw an error immediately.**

This is **The Law of Loudness**.

If I call a function named `getUser(id)`, I expect a user. I do not expect `null`. If you can’t give me a user because the database is on fire, don't hand me an empty box and smile. Scream at me.

We want to **Fail Fast**. We use exceptions to protect the integrity of our data. If the data is bad, stop the factory line immediately.

### The Code: From Silent Killer to Loud Protector

Let’s look at the `getUser` function.

#### The Trap: The Silent Failure
This code looks "safe" because it doesn't crash. But it creates a minefield for the rest of the application.

```javascript
// BEFORE: The "Safe" Silent Failure

function getUser(id) {
  // If the DB is down, we hide it.
  if (!db.isConnected()) {
    console.log("DB is down..."); 
    return null; // <--- Passing the buck
  }

  const user = db.find(id);
  
  // If user isn't found, we return null again.
  // Is it null because they don't exist?
  // Or because the DB is broken?
  // The caller will never know.
  return user || null; 
}

// THE RESULT:
// The caller code assumes it got a user.
const user = getUser(50);
// CRASH happens here, 10 lines later.
console.log(user.profile.email); 
```

#### The Fix: The Loud Failure
Here is how a Professional handles the same scenario. We stop execution the moment we know we cannot fulfill the contract.

```javascript
// AFTER: The Law of Loudness

function getUser(id) {
  // 1. Guard Clause for System Failure
  if (!db.isConnected()) {
    // Stop execution immediately. We know EXACTLY what broke.
    throw new DatabaseConnectionError('Cannot fetch user: DB is down');
  }

  const user = db.find(id);

  // 2. Guard Clause for Data Integrity
  if (!user) {
    // Differentiate between "System Broken" and "Not Found"
    throw new NotFoundError(`User with ID ${id} does not exist`);
  }

  return user;
}

// THE RESULT:
// The crash happens INSIDE getUser.
// The stack trace points exactly to the line that failed.
// We know if it was a DB error or a missing user instantly.
```

### Why This is Better

1.  **Debugging Speed:** When the app crashes, the stack trace points to `getUser`, line 4. You know immediately that the DB is down. You don't waste 3 hours tracing `null` values through the UI components.
2.  **Trust:** When I call `getUser`, I don't have to write `if (user !== null)` every single time. I can trust that if the code execution proceeds past that line, I have a valid user.
3.  **Data Integrity:** You prevent "Zombies"—half-formed data objects—from floating around your state management and causing weird bugs (like saving a user profile with an ID of `undefined`).

### Summary

Don't be afraid of the red text in the console. Red text is honest.

A silent `null` is a lie. It tells the system everything is fine when the house is actually burning down.

**The Rule:**
*   If the error is expected (e.g., searching for a product that might not exist), return a specialized Result type or `null` *only if* `null` is a valid state for your domain.
*   If the error is unexpected (network down, bad configuration, missing required data), **Throw. It. Loud.**

***

**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.

👉 **[Get the Full Handbook Here](https://gum.co/u/citu62p3)**


