Skip to main content

17 posts tagged with "blog"

View All Tags

The Invisible Buyer Has Arrived

· 11 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Something happened recently in B2B procurement that most sellers don't know about yet.

A construction company's software placed an order for 200 precision industrial components — ISO certified, shipped to Denver, all-in for $38,000 — without a human making a single purchasing decision after the initial instruction was given. The software found the supplier, evaluated three alternatives, confirmed availability and certification, arranged freight, and submitted the order. The construction firm's project manager received a structured confirmation email with the purchase order, tracking number, and certification documents.

The supplier that won the business? They didn't win it with a great website. They didn't win it with SEO or a smooth checkout flow or a compelling product description. They won it because their product data was complete, their availability signal was machine-readable, and their API didn't return ambiguous strings when the software asked a yes-or-no question.

The supplier that lost? They had equivalent products. They lost because their availability field returned "usually ships in 1–2 weeks" instead of a structured value. The software couldn't parse that into a procurement decision and moved on.

This is the shift. And it's not coming — it's here.

Is the FP Juice worth the Squeeze?

· 4 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 11

Adopting functional programming isn't free. It requires training investment, a shift in team culture, and a willingness to tolerate an awkward middle period where the codebase is neither cleanly imperative nor fully functional. So the honest question — the one that belongs in a technology leadership conversation — is whether the benefits actually justify the cost.

This is my attempt at a direct answer, organized around the risk categories that tend to matter most in enterprise commerce organizations.

When MVPs Grow Teeth

· 6 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 10

Bad models are rarely designed by teams on purpose. Most of the time it's the model you get by being pragmatic: shipping an MVP, and then doing the next reasonable thing… repeatedly… for two years.

You start with a product structure that fits a world where you can store something on a shelf, put it in a box, and ship it to a customer. When the business decides to stock other stuff, you add more attributes to accommodate. When the business wants customization — engraving, embroidery, monogramming — and now "the product" has options that change price and lead time, you start sub-typing. When subscriptions, warranties, DRM, and other non-physical entitlements become strategic, you do more of the same. Nothing here is exotic. It's just what happens when the business grows and adapts.

Folding in Traceability

· 4 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 9

In enterprise commerce, totals don't drift because someone forgot algebra. They drift because reality changes: promos expire, eligibility changes when an address arrives, catalog data updates, substitutions happen, and returns unwind prior discounts. When someone asks "why did the total change?" you need more than narration. You need evidence — a trail of facts you can replay and a pure computation that deterministically produces the same result.

That responsibility falls to foldLeft.

Not All Errors are Exceptional

· 6 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 8

Not every "error" in a system represents a defect. Many outcomes that matter to a business are perfectly legitimate: a promotion does not apply, a configuration is incomplete, a shipment cannot be routed to a destination, a request is valid but cannot yet be satisfied. Treating these outcomes as exceptions often obscures their meaning. Exceptions are excellent for broken invariants and infrastructure failures; they are much less effective for representing business decisions that the system should be able to explain, persist, and reason about later.

In Scala, one of the tools commonly used to model these outcomes is Either. There is no shortage of articles explaining how to use Either for error handling, and many of them are worth reading. What those articles sometimes struggle to convey is why this representation changes how systems behave, especially for developers coming from imperative backgrounds. Either can feel abstract until it is attached to a boundary where the distinction between two outcomes actually carries meaning.

Modeling Absence without Ambiguity

· 5 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 7

Most enterprise systems operate under a subtle assumption that proves surprisingly costly: representing absence as a value. In Java and comparable languages, this value is null, appearing everywhere to denote missing, unknown, inapplicable, or forgotten things. Teams eventually stop noticing it, but this familiarity creates problems.

While null wasn't inherently flawed — it solved a genuine constraint in early object-oriented languages — trouble emerged when it began representing multiple distinct concepts simultaneously. In real systems, null might signify that a value doesn't apply, wasn't provided, hasn't loaded yet, a lookup failed, configuration is missing, or upstream errors occurred. All these situations collapse into one representation with no explanation.

Why Pattern Matching Matters

· 6 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 6

By this point in the series, we've spent a lot of time making the mechanics of code disappear. We stopped mutating values because mutable values drift. We stopped depending on external state because it breaks determinism. We stopped writing statements because expressions are clearer, safer, and easier to compose. And, most recently, we stopped writing loops because functional transformations let the business logic stand on its own.

But there is another way imperative languages obscure meaning — and this one is subtler. It happens any time a developer tries to figure out what kind of thing something is before deciding what to do with it.

Beyond the For-Loop: Mastering map, filter, and flatMap

· 4 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 5

Even after developers embrace immutability and pure functions, one imperative construct persists: the for-loop. It remains the last artifact to disappear because it's the first structure we learn. In Java, it feels inevitable as the only intuitive way to examine lists, select relevant data, and produce results.

However, for-loops obscure business logic. Before expressing a domain rule, developers must decide how to iterate, where to accumulate results, when to branch, which state to mutate, and how structures evolve. All of that precedes stating anything meaningful about the business itself.

Unpacking Agentic Commerce

· 3 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

For three decades, commerce has centered on human buyers navigating browsers, apps, and IoT devices. Humans absorb ambiguity — tolerating unclear checkout processes, mysterious promotions, shifting shipping estimates, and surprise totals. If the brand is strong enough, they might still purchase despite friction.

Agentic commerce marks a fundamental shift: acknowledging that buyers aren't always human. Automated agents operate differently from people. They lack emotional attachment to brands and won't retry after failures. Instead, agents follow intent within constraints and systematically avoid unreliable paths.

Thinking in Expressions, Not Statements

· 4 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 4

Developers transitioning from non-functional languages typically acquire functional concepts incrementally — lambdas, immutability, pattern matching, collection operations. While the syntax may appear elegant, the fundamental conceptual breakthrough often comes much later. That breakthrough involves recognizing that thinking in expressions rather than statements represents the true bridge between imperative and functional paradigms.

Imperative programming emphasizes procedural steps with variable mutation. Functional programming reframes the question entirely: "What value are we computing?" This expression-centric approach eliminates entire classes of complexity because there's no timeline of state changes, no mutable accumulators, and no branches requiring variable adjustments. Everything becomes composable values.

Pure Functions: Your First Step Toward Bug-Free Concurrency

· 8 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 3

In Part 2, we explored how mutable state — especially state that someone once believed was a fact — tends to drift over time, and how this drift destabilizes large systems. Immutability is a corrective measure: if something is a fact, preserve it. But immutability addresses only one dimension of stability. The other dimension concerns the way behavior is expressed — whether the logic we rely on actually does what its name claims, or whether it also does several other things we never quite account for.

When developers talk about pure functions, they often recite the textbook definition: same inputs, same outputs, no side effects. It's correct, but it undersells the point. Purity is not an aesthetic choice or an academic curiosity. It is a way of reclaiming control over the semantics of your system. It is how you establish that a piece of business logic actually behaves like business logic, rather than a negotiation with global state, shared caches, volatile time checks, and whichever service instance happens to answer the call.

Immutability by Default: The Foundation of Reliable Systems

· 8 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 2

Most introductions to immutability begin with trivial examples. A string is mutated, the result changes, and we are invited to contemplate the danger. But enterprise systems don't fail because someone appended characters to the wrong buffer. They fail because something that was supposed to be a fact — a value that anchored downstream behavior — continued to evolve with the system rather than remaining bound to the moment it was created.

Distributed systems fail when truth drifts. This is why immutability is not a stylistic preference or a functional-programming curiosity. It is the architectural foundation for building systems that behave predictably in a world that does not.

Functional Programming Isn't Just for Academics: Why It Matters for the Systems We Build Now

· 7 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

In 1983 I asked my parents for an Atari for Christmas, instead I got a Commodore 64… Needless to say, I was very disappointed until I discovered how much cooler Wizard of Wor was than Combat. To their credit, my parents thought a computer was a better investment than a video game. I used that C64 through my sophomore year of college until I replaced it with a 486; my first real investment. So, like many in my generation, I cut my teeth on programming languages like BASIC and LOGO without really picking them for any reason. It was just kind of cool, as a kid, to be able to tell a computer what to do and watch it do it. I quickly understood that animating ASCII stick figures was a BASIC problem and digital Spirograph was a job for the LOGO turtle. In college I was using FORTran for math and science and C for everything else knowing that, depending on the task, one was more natural than the other.