General

Goh Ling Yong : Treating My Anxiety Like Legacy Code - Goh Ling Yong

Goh Ling Yong
9 min read
0 views
#treating#anxiety#legacy

The first unhandled exception occurred on a Tuesday, on the 8:14 AM train to the city. There was no warning, no pop-up dialogue box asking if I was sure. One moment, I was scrolling through morning emails, a perfectly normal input-output cycle. The next, the system crashed.

My core processing unit—my brain—was suddenly consumed by a single, recursive loop: get out get out get out. My cooling system failed, and a hot flush cascaded from my chest to my fingertips. My primary display went fuzzy at the edges. The audio input became a garbled roar, the gentle clatter of the train tracks turning into the sound of grinding metal. I was experiencing a full-blown kernel panic, trapped inside a chassis of skin and bone, with no access to the command line and no option to reboot.

I stumbled off at the next station, a stranger's platform in a town I didn't know, and stood gasping on the concrete as if I'd just surfaced from the deep. The system eventually stabilized, the processes slowly returning to their normal, idle state. But a critical error log had been written somewhere deep in my firmware. This wasn’t a random glitch. This was a bug in the source code. My own source code.


For years, I treated my anxiety like a programmer treats a legacy system they inherited but don't have time to fix. I knew it was there, humming with a low-grade inefficiency in the background. It was written in a language I didn’t fully understand, with no comments and zero documentation. When it threw an error—a sudden jolt of panic in a crowded supermarket, a sleepless night spent debugging a social interaction—I’d apply a quick, dirty patch. A beer after work. A weekend spent avoiding people. The classic // TODO: Fix this later.

But the crash on the train was different. That wasn't a minor bug; that was a catastrophic failure that brought the whole application down. It was a sign that my patchwork solutions were no longer holding. The system was becoming unstable. It was brittle, unpredictable, and the technical debt was finally coming due.

I realized I had to do what every engineer dreads but knows is necessary. I had to stop shipping new features and start refactoring the old code. I had to treat my own mind like the most complex, critical, and poorly-documented legacy project of my life.

Reverse-Engineering the Black Box

The first step in dealing with any legacy system is to figure out what the hell it actually does. My anxiety was a black box. Inputs went in—an email from my boss, a party invitation, the train being five minutes late—and a chaotic, unpredictable output came out. To understand it, I had to start logging.

So, I started a new kind of journal. It wasn't for prose or feelings, not at first. It was a log file.

Timestamp: 2021-03-15 14:32:05
Event: Received calendar invite for 'Project Phoenix Post-Mortem'.
Output: Heart rate increased. Palms sweating. Immediate thought: "They're going to find out I missed that edge case."
Severity: 4/10

Timestamp: 2021-03-17 19:03:11
Event: Phone rang. Unknown number.
Output: Did not answer. Felt a wave of dread. Spent 20 minutes worrying about who it might have been.
Severity: 6/10

For weeks, I just collected data. I was an archaeologist of my own dysfunction, dusting off fragments of panic and trying to piece them together. The initial patterns were nonsensical. There was no obvious if-then logic. The triggers seemed to be a random collection of completely normal life events. It was like discovering a bug that only occurs when the server's CPU temperature is a prime number. It felt arbitrary, shameful, and deeply, personally broken. Why was my code so uniquely flawed?

But as the log files grew, a faint pattern began to emerge from the noise. The triggers weren't the events themselves, but the uncertainty embedded within them. The post-mortem meeting wasn't the problem; it was the unknown scrutiny. The phone call wasn't the problem; it was the unknown caller with an unknown agenda. My system wasn't crashing on definite threats; it was crashing on a null pointer exception—the possibility of a threat, the risk of a negative outcome I couldn't predict or control.

Finding the Original Commit

With a vague map of the buggy behavior, I knew I couldn't go further alone. I needed a senior developer, someone who had seen this kind of architecture before and could help me read the assembly code. For me, that was a therapist.

In our first session, I described my anxiety in the only language I had: "It's like there's a background process that occasionally spikes and consumes all the CPU, and I don't know how to kill it."

He didn't laugh. He just nodded, and for the first time, I felt like I was talking to someone who had the schematics. Therapy became a process of spelunking through my own commit history. We scrolled back, past the recent check-ins, past my adult life, and into the earliest versions of my operating system: my childhood.

There, buried deep in the initial commits, we found it. A core module, written when I was about seven years old. It was a piece of code designed for survival. As a quiet, sensitive kid in a loud, demanding environment, I learned that the best way to avoid negative feedback—the "bugs"—was to anticipate every possible failure state. I became a master of preemptive debugging. I would run every social interaction through a mental simulator, testing for all the ways it could go wrong. I would over-prepare, over-analyze, and over-think everything.

This code, this Perfectionism.dll, worked beautifully for a while. It helped me get good grades. It helped me avoid trouble. It was a feature, not a bug. It shipped with every version of me. But code that works in a simple, controlled development environment often fails spectacularly in the complex, messy world of production. The module that was designed to protect a seven-year-old was now consuming all the resources of a thirty-year-old. Its dependencies were tangled everywhere. It was, I realized, the source of the crash.

This was the most profound insight of the entire process. My anxiety wasn't a malicious virus. It wasn't a sign that I was fundamentally broken. It was a piece of code written by a younger, less-experienced version of myself, with the best of intentions, to solve a problem that no longer existed.

Refactoring, One Function at a Time

You can't just delete a core module from a running system. If I tried to rip out Perfectionism.dll, the entire application would fail to compile. The only way forward was to refactor it, slowly and carefully, one function at a time.

My therapist gave me a name for this process: Cognitive Behavioral Therapy. I called it writing unit tests for my own brain.

The old, buggy function looked something like this:

function handle_social_event(event) {
  var potential_failures = simulate_all_negative_outcomes(event);
  if (potential_failures.length > 0) {
    trigger_panic_alarm();
    return;
  }
  attend_event(event);
}

This code was hopelessly inefficient. Since potential_failures was always greater than zero in the real world, it almost always called trigger_panic_alarm().

The refactoring process involved introducing a new concept: exception handling. Instead of trying to prevent all possible errors before they happened, I needed to learn to handle them gracefully when they did. The new code looked more like this:

function handle_social_event(event) {
  try {
    // Assume success, proceed with caution.
    attend_event_with_awareness(event);
  } catch (error) {
    // An error occurred (e.g., awkward conversation, felt out of place).
    // Don't crash the whole system.
    log_error(error);
    execute_coping_strategy(); // e.g., deep breaths, step outside.
  }
}

Putting this into practice was terrifying. It meant intentionally walking into situations that I knew might throw an error. The first unit test was small: go to a coffee shop and order a drink. My old code would have simulated every possible way this could fail: I could spill the coffee, my card could be declined, I could forget what I wanted to order. The new code just said: "Go. And if something goes wrong, you have a catch block."

So I went. I ordered. My card worked. Nothing exploded. The test passed.

Slowly, I increased the complexity. I made a phone call I’d been putting off. I went to a party and planned to stay for just 30 minutes (a "timeout" condition). I submitted a piece of work without checking it a fifteenth time. Some tests failed. I had awkward conversations. I felt the familiar hum of the anxiety process starting to spike. But this time, instead of letting it take over the CPU, I had my catch block. I would take a deep breath. I would step outside for a minute. I would remind myself that an error is not a fatal crash.

It was messy. Refactoring always is. Sometimes the new code introduced new bugs. But with every small, successful test, the new, more resilient pathways in my brain grew stronger. I wasn't deleting the old code; I was just making it so the compiler would choose the new, more efficient function instead.

The New Documentation

The final, and perhaps most important, part of the process has been writing the documentation. For decades, I was running on instinct, with no insight into my own system architecture. Now, I understand it. I know which modules are flaky. I know what inputs are likely to cause issues. I know which situations require more careful error handling.

This documentation is a form of self-compassion. I look back at the original commit, the one written by that seven-year-old developer, and I don't feel anger or shame anymore. I feel a sort of fond, professional respect. He did the best he could with the tools he had. He wrote a program that ensured our survival. It’s not his fault he couldn’t have anticipated the scaling issues we’d face decades later.

My anxiety isn’t gone. The legacy code is still there, deep in the codebase. I don’t think I’ll ever fully delete it. On a bad day, under heavy load, it can still get called and cause a familiar spike in my system resources. But now, I have the documentation. I have the tools. I know how to debug it. I know how to lower its process priority, manage its memory leaks, and prevent it from causing a system-wide crash.

I’ve learned that the goal isn’t to become a perfect, bug-free application. That’s impossible. The goal is to become a patient, skilled, and compassionate systems administrator of your own mind. It’s to know your own code—its elegant strengths, its frustrating bugs, and its legacy modules—and to learn how to keep it running, not perfectly, but well enough. And on most days, that’s more than enough.



More Stories You'll Love

Connect with Me

Follow for more stories and updates.

Thank you for reading! If you found this helpful, please share it with others.


📖 Read on Medium

This article was originally published on Medium. You can also read it there:

Read this article on Medium

If you enjoyed this article, please consider giving it a clap on Medium and following for more content!

Related Articles

General

Goh Ling Yong : The Grammar of a Shared Kitchen - Goh Ling Yong

Learning my grandmother’s dialect not through words, but through the silent rules of salt, fat, and heat.

9 min read
General

Goh Ling Yong : The Digital Hoard I Inherited in a Single .zip File - Goh Ling Yong

My father left me no property and no money, just 78 gigabytes of his life. Unpacking it felt like an archaeology of the man I barely knew.

8 min read
General

Goh Ling Yong : The Day I Became Fluent in a Language That No Longer Exists - Goh Ling Yong

An elegy for the shared shorthand of a team that was, and the slow, quiet grief of a startup's end.

8 min read