Chapter 3: Flow Like a Function

“Life is a series of natural and spontaneous changes. Don’t resist them; that only creates sorrow. Let reality be reality. Let things flow naturally forward in whatever way they like.”
— Lao Tzu

The best code I ever wrote took about forty minutes. The worst code I ever wrote took three weeks.

They were the same feature.

The first attempt was a mess. I was under pressure, behind schedule, and convinced that if I just pushed harder, I could force the solution into existence. I wrote code the way you dig a hole in frozen ground: every line was effort, every abstraction felt wrong, every test broke something else. After three weeks, I had something that technically worked but that I hated looking at. The pull request sat open for days because even I couldn’t explain what I’d built.

Then a production incident in an unrelated system gave me an unexpected week away from the feature. When I came back, I deleted everything and started over. This time, the code came easily. I wasn’t smarter. I wasn’t more skilled. I just wasn’t fighting anymore.

That experience taught me something I’ve had to relearn many times since: the quality of your code reflects the quality of your attention, and attention that’s been forced is rarely good attention.


The Shape of Resistance

You can feel when you’re forcing. There’s a particular tension in your shoulders, a tightness in how you’re holding the keyboard. You’re not thinking clearly; you’re thinking loudly. The same three possibilities keep cycling through your head, and you keep rejecting them, and you keep coming back to them anyway.

When I’m in this state, my code shows it. Variable names get lazy. Functions get long. I start copying and pasting instead of abstracting because I don’t have the mental space to see the pattern. Comments appear that say things like “TODO: fix this” or “this is ugly but it works.” The code becomes a transcript of my frustration.

I used to think this was discipline. I was pushing through. I was being professional. Real engineers don’t stop just because something is hard. But pushing through resistance and pushing through confusion are different things. Resistance means there’s something you’re not seeing. Confusion means you haven’t looked long enough. I was treating both the same way, and it cost me.

The Taoists had a term for what I was missing: wu wei. It’s usually translated as “non-action” or “effortless action,” which makes it sound like passivity. It’s not. Wu wei is what happens when you stop fighting the current and start moving with it. A river doesn’t force its way through a landscape; it finds the path that’s already there. The water still moves. It just doesn’t struggle.

I think of wu wei every time I catch myself forcing. It’s a signal that I’ve stopped paying attention to what the problem actually requires and started paying attention to what I want the problem to be.


What Pure Functions Know

There’s a reason functional programming appeals to a certain kind of mind. A pure function is a small promise: given these inputs, you will always get this output, and nothing else will change. No hidden state. No action at a distance. No surprises.

When I write a pure function, I feel calmer. The scope is bounded. The contract is clear. I can hold the whole thing in my head, test it in isolation, and trust that it will behave the same way tomorrow as it does today. The function doesn’t struggle. It just transforms.

I’ve started to think of this as a model for how I want to work. Not that all code should be purely functional, but that the clarity of a pure function reflects something worth pursuing: a kind of mental cleanliness where inputs and outputs are obvious and side effects are acknowledged rather than hidden.

The opposite is code that surprises you. Functions that read from global state, or write to databases in the middle of a calculation, or depend on the time of day in ways that only show up in production. That kind of code isn’t just hard to test. It’s hard to think about. It fights your attention instead of rewarding it.

I’ve noticed that when my thinking is muddy, my code develops these symptoms. Hidden dependencies creep in. Functions start doing two things instead of one. The boundaries get blurry. It’s not a moral failing; it’s a signal. The code is telling me that my mind isn’t clear enough to write something clean.


Stepping Away

The insight I needed during those three miserable weeks never arrived at my desk. It arrived in the shower, three days into my unplanned break. I wasn’t thinking about the feature. I was thinking about nothing in particular. And then, without effort, I saw the shape of the solution.

This has happened enough times that I’ve stopped treating it as coincidence. The pattern is reliable: struggle, step away, return with clarity. The struggle seems to be necessary, like your brain needs to load the problem fully before it can work on it in the background. But the stepping away is necessary too. You have to give the background process room to run.

I think of it as compilation. When you’re actively writing code, your mind is in editing mode, focused on the line in front of you, the syntax, the immediate error. But the big picture, the architecture, the elegant simplification, those require a different kind of processing. You can’t force your way to insight. You can only create the conditions for it and then wait.

This is hard to do when you’re under deadline. It feels irresponsible to step away when there’s so much to do. But I’ve learned that an hour of clear thinking is worth more than a day of muddy effort. The code you write when you’re clear is the code you won’t have to rewrite. The code you write when you’re forcing is the code that becomes next quarter’s tech debt.

The difficult part is trusting this. Trusting that the answer will come. Trusting that stepping away is actually the faster path. Everything in our industry optimizes for visible activity, and stepping away looks like the opposite of that.


The Two Programmers

I used to sit near an engineer who worked differently than anyone I’d seen. She would read a ticket, sit back, and do nothing visible for what felt like an uncomfortable amount of time. No typing. No scrolling. Just sitting. Then she’d lean forward and write code in a continuous flow, barely pausing, until she was done. Her PRs were small, clear, and almost never needed revision.

At first I thought she was slow. Then I started watching her ship velocity and realized she was consistently faster than I was, despite all my frantic typing. She wasn’t slow; she was thinking before she acted. The typing was just the last step in a process that was mostly invisible.

I asked her about it once. She said she didn’t like starting until she could see the whole shape of what she was building. “If I can’t explain it to myself in a sentence, I’m not ready to write it.” She wasn’t describing some mystical practice. She was describing something more like patience: the willingness to sit with a problem until it revealed its own structure rather than imposing a structure onto it.

I’ve tried to learn from this, with mixed success. My instinct is still to start typing immediately, to think through my fingers, to iterate my way toward a solution. Sometimes this works. More often, I end up with code that reflects my confusion rather than transcending it. The PRs are messy. The abstractions are wrong. I spend more time fixing than I spent writing.

The discipline I’m trying to develop is the pause before the keystroke. The moment of asking: do I actually see this, or am I just hoping it will become clear as I go?


When Flow Arrives

You know it when it happens. Time compresses. The gap between intention and implementation disappears. You’re not thinking about the code; you’re just writing it, and it’s coming out right.

Flow state is fragile. Interruptions shatter it. Context switches drain it. Even a Slack notification can be enough to break the spell and send you back to effortful, conscious coding. This is why so many developers guard their focus so jealously. The difference between flow and not-flow is the difference between work that feels like play and work that feels like chewing gravel.

I can’t summon flow on demand. Nobody can. And frankly, most of the job isn’t flow. Most of the job is showing up, writing the test, fixing the bug, reviewing the PR. Ordinary work done with ordinary attention. That’s fine. That’s the job. The danger isn’t the absence of flow; it’s forcing your way through the parts that actually require clarity. That’s where the damage happens.

But I’ve learned some of the conditions that make flow more likely when the work calls for it. A clear goal helps. A codebase I understand helps. Time without interruption is essential. And there’s something else, harder to pin down: a kind of relaxed alertness, where I’m engaged with the problem but not clenched around it.

The forcing I did during those three bad weeks was the opposite of this. I was clenched. I was trying to squeeze the solution out through sheer effort. And effort, past a certain point, becomes its own obstacle. You can’t grip your way to flow. You have to let it arrive.


The Current

There’s a current beneath the work. You can feel it when you’re aligned with it and feel its absence when you’re not. The code that emerges from alignment is different: cleaner, simpler, more obvious in retrospect. The code that emerges from fighting is tangled with the fight itself.

I don’t mean this mystically. I mean it practically. When you’re seeing clearly, you make better decisions. When you’re forcing, you make defensive decisions, designed to get the problem off your desk rather than to solve it well. The current is just clarity. The skill is learning to notice when you’ve lost it.

The forty-minute rewrite succeeded because I came to it empty. I had no attachment to my previous approach, no sunk cost I was trying to protect. I could see the problem fresh. The solution was there the whole time; I just hadn’t been quiet enough to notice it.

Tomorrow, you’ll sit down to code. Before you start typing, pause. Notice the state of your mind. Is there clarity, or is there noise? Are you ready to flow, or are you about to force?

The answer might save you three weeks.