Arrange Act Assert

Jag Reehals thinking on things, mostly product development

fn(args, deps) — Bringing Order to Chaos Without Breaking Anything

18 Mar 2026

There’s a major disconnect in AI-assisted development right now. Most of the conversation assumes you’re building something new, or working from the kind of clean, stable foundation that barely exists in real engineering teams.

The reality is that most engineering teams live in legacy systems under high load, with god classes, global singletons, and console.log as observability. The kind of code where every change is a gamble.

This post shows what happens when you apply fn(args, deps) and autotel to those codebases. fn(args, deps) creates the seam for safe change; production telemetry captures the behavioural record that survives when every other spec has decayed.

John Bercow shouting "Order!" in the House of Commons

To prove the point, we’ll do this in plain JavaScript, not TypeScript.

Read More →

What `fn(args, deps)` actually gives you in DDD-style TypeScript

18 Mar 2026

Domain-Driven Design comes with a lot of vocabulary: aggregates, repositories, domain services, bounded contexts, ubiquitous language, anemic models.

That vocabulary can make DDD sound heavier than it really is.

The useful idea is simpler: keep domain behavior and domain boundaries central, and keep infrastructure, persistence, and framework wiring secondary.

fn(args, deps) does not do that modeling for you. What it gives you is a clear shape for application-layer code in TypeScript: one place for use-case input, one place for collaborators, and less room for domain decisions to drift into wiring.

fn(args, deps) and Domain-Driven Design

Read More →

fn(args, deps) and Hexagonal Architecture

17 Mar 2026

Hexagonal architecture often gets introduced with a lot of diagrams, vocabulary, and ceremony.

Ports. Adapters. Application core. Inbound and outbound boundaries.

That framing is useful, but it can also make the idea feel more abstract than it really is.

fn(args, deps) and hexagonal architecture

You may also hear this called "ports and adapters" — same idea, different name. The port is what a function needs; the adapter is what fulfils it.

A simpler way to understand it is this:

Hexagonal architecture is mostly about keeping business logic independent from delivery and infrastructure details.

One practical way to do that in plain TypeScript is this shape:

fn(args, deps);

Where args is the input for this use case, and deps is the set of external capabilities it needs. You can read that as: data in, capabilities in.

In plain TypeScript, fn(args, deps) is a simple way to implement the core idea of hexagonal architecture without turning the pattern into ceremony.

Read More →

Composition Roots and fn(args, deps)

16 Mar 2026

A lot of developers hear "dependency injection" and immediately think of containers, decorators, registration APIs, lifecycle scopes, and framework magic.

That reaction is understandable.

But that association often leads people to overcomplicate a problem that has a much simpler starting point.

Composition roots and fn(args, deps)

At its core, dependency injection just means this:

Pass collaborators in explicitly instead of reaching for them implicitly.

One of the simplest ways to do that in plain TypeScript is this shape (introduced in the series starting point: fn(args, deps)):

fn(args, deps)

Where args is call-specific input and deps is the set of collaborators the function needs.

You can read that as: data in, capabilities in.

fn(args, deps) is flexible enough to support composition, testing, and clean application wiring without forcing you into a DI framework.

Read More →

When it comes to using AI, be like Luke

09 Mar 2026

I love using AI coding tools. As someone who definitely gets their money’s worth, I feel more productive than ever.

But sometimes, just like Obi-Wan told Luke, you need to let go.

When it comes to using AI, be like Luke

Control the instinct to reach for AI all the time.

Trust yourself.

Read More →

If You Only Enforce One Rule for AI Code, Make It fn(args, deps)

04 Mar 2026

AI coding agents produce code faster than you can review and understand it.

One pattern works in both new and legacy codebases because you can adopt it incrementally, without breaking callers.

fn(args, deps) is all you need

For business logic, treat every function as having two inputs: data (args) and capabilities (deps).

Without a clear constraint, generated code becomes harder to reason about: dependencies disappear, side effects spread, composition gets messy. This is why visible structure is essential.

fn(args, deps) is that constraint

For existing code, start with:

functionName(args, deps = defaultDeps)

Dependencies are explicit, not hidden.

There’s no framework and no package to install.

Read More →

Visualising Awaitly Workflows with awaitly-visualizer

07 Feb 2026

You have an Awaitly workflow: a few steps, some dependencies, typed results. It works. When someone asks "what does this do?" or you need to debug a run, you're left tracing through code.

What if you could see the same workflow as a diagram? awaitly-visualizer plugs into your workflow's events and turns them into that picture. For a checkout that runs fetchCart, validateCart, processPayment, then completeOrder, you get output like this:

┌── checkout ────┐
│  ✓ fetchCart   │
│  ✓ validateCart│
│  ✓ processPayment
│  ✓ completeOrder
│  Completed     │
└────────────────┘

Same idea as Mermaid flowcharts: steps, order, success and failure. This post walks through adding it step by step. All of the code below lives in a test in the repo so you can run it yourself.

Read More →

No, the sun does not shine out of Claude’s backside

30 Jan 2026

As of today, Opus 4.5 is the best coding model I've used. That is not praise by vibes. That is, after building libraries and utilities that fixed problems I could not solve with the tools I was using before.

The progress is impressive.

However, it’s not all sunshine and rainbows, as people on social media and YouTube claim.

Cartoon illustration of a pig driving and a chicken riding along, suggesting responsibility versus involvement.

Read More →