All Posts

Article

42 posts · Page 1 of 5

Property-Based Testing for Pure Functions

Property-Based Testing for Pure Functions

Example-based tests check the points you thought of; property-based tests check the laws that must hold at every point. Pure functions are the perfect customer for the technique: deterministic, self-contained, and reproducible from a seed. What a property is, the six patterns that cover most real code, how to write them in Java with jqwik, and the pitfalls that make teams give up too early.

The Performance Cost of Immutability, and When It Actually Matters

The Performance Cost of Immutability, and When It Actually Matters

Immutability allocates more, copies more, and chases more pointers — that much is true. What the folklore gets wrong is where those costs land, how much of them the JVM already absorbs, and how rarely they show up in a profile before everything else does. A field guide to the real numbers, persistent data structures, and the short list of cases where mutation genuinely earns its keep.

Error Handling Without Exceptions: A Functional Approach

Error Handling Without Exceptions: A Functional Approach

Expected failures belong in the return type, not in a nonlocal jump: how Result and Try replace throw/catch for the failures the business expects. What a throw really does to your signatures, what a sealed error type and an exhaustive switch buy you, how failures compose without the try/catch pyramid, and the honest border where exceptions remain exactly right.

Mapping the Error Channel: When and How to Transform Failures

Mapping the Error Channel: When and How to Transform Failures

Every Result has two lanes, and map only ever touches one of them. The other lane — the error channel — needs its own transformations: a repository's SQL failure should not surface in an HTTP handler, and two libraries' error types cannot ride one pipeline untranslated. This post is about mapError and its siblings: the small API for reshaping failures, the boundaries where using it is mandatory, and the two classic ways to get it wrong.

The Hidden Cost of Cleverness in Functional Code

The Hidden Cost of Cleverness in Functional Code

Clever code is priced at write time and paid for at read time — by the reviewer, the on-call engineer, the next hire, never the author. Functional style, because it composes so willingly, invites that spending more than most. Kernighan's law, three specimens from real codebases, and an opinionated argument for putting your ingenuity where the reader profits.

Building a Small Rules Engine with Composable Predicates

Building a Small Rules Engine with Composable Predicates

The phrase 'rules engine' conjures a vendor product with its own language, console, and invoice. But most systems that need one actually need something much smaller: a dozen eligibility checks that can be combined, tested one at a time, and — crucially — explain which ones failed. Like loose gears, each rule is a small part machined to mesh; the engine is just the composition. Here is one built from plain predicates, upgraded until it explains itself, in well under a hundred lines.

Selling Functional Programming to Skeptical Stakeholders

Selling Functional Programming to Skeptical Stakeholders

Nobody at a street market buys a philosophy of produce. They buy what is on the table, at the price on the card, after picking it up and looking at it. Yet engineers routinely pitch functional programming the opposite way — paradigm first, evidence later, price undisclosed. Here is the honest sales technique: translate the technique into the listener's ledger, price the ask small enough to inspect, and concede the failure modes before the skeptic finds them.

Real-World Cases Where Functional Programming Actually Adds Value

Real-World Cases Where Functional Programming Actually Adds Value

Advocacy for functional programming tends to arrive as theory — purity, composition, referential transparency. Skeptical teams are convinced by something else: the signup form that stopped making users fix one error per submission, the payment failure the compiler refused to let anyone forget, the six-hour import a single bad row could no longer kill. Five concrete cases where the functional move changed an operational outcome — and the honest ones where it would not have.

Laziness and Streaming: Processing Large Data Without Loading It All

Laziness and Streaming: Processing Large Data Without Loading It All

A ten-gigabyte file does not fit in a two-gigabyte heap — but a pipeline that holds one element at a time never needs it to. Like an irrigation canal, streaming moves the water without building the reservoir: lazy sources, fused stages, and aggregating sinks keep memory proportional to a batch, not the dataset. Here are the real JDK tools, the stages that silently rebuild the reservoir, and the honest limits.