Refactoring Object-Oriented Code Toward a Functional Style
A practical, step-by-step guide to moving Java code from a mutable, exception-driven OO style toward immutable, composable functional pipelines — without rewriting everything at once.
A practical, step-by-step guide to moving Java code from a mutable, exception-driven OO style toward immutable, composable functional pipelines — without rewriting everything at once.
Version 0.0.13 adds Either<L,R>, NonEmptyList<T>, typed Try.recover overloads, the fun-jackson and fun-assertj modules, a runnable samples subproject, and a full Developer Guide — plus a breaking package rename to dmx.fun.
Purity is one of the most valuable ideas functional programming offers — but insisting on it everywhere leads to a different kind of mess. Here is how to draw the line in real Java codebases.
Pure functions, immutable data, and typed errors remove most of the friction in unit testing. This post explains why FP code is inherently easier to test, and shows concrete examples using Java and dmx-fun types.
A personal project born from curiosity about new Java features has grown into a functional programming library worth sharing. Here is where it is heading.
Version 0.0.12 brings CompletableFuture adapters, Lazy<T>, zip3/zip4, Try.flatMapError, and a sweeping set of internal refactors powered by Stream Gatherers and Java record patterns.
Functional style in Java is easy to get subtly wrong. This post walks through the most common mistakes — from returning null inside a mapper to leaking shared mutable state into a stream — and shows how to fix each one.
Event-driven systems and functional programming are rarely discussed together, yet they fit remarkably well. Immutability, explicit error handling, and pure transformations make event-driven code more predictable, composable, and easier to test. This post explores how functional ideas sharpen the design of event-driven architectures.
Imperative code tells the machine what to do step by step. Declarative code tells it what you want. The gap between those two sentences is where most of the complexity in everyday Java code hides — and where the biggest readability gains are waiting.
Version 0.0.11 is the biggest release yet: Validated for applicative error accumulation, four checked functional interfaces, Tuple3 and Tuple4 with combinators, and an upgrade to the Java 25 LTS toolchain.
Java 25 is the next Long-Term Support release and the most significant Java upgrade since Java 21. Here is a practical look at what it delivers, why LTS matters for production codebases, and how a functional-style library like dmx-fun benefits from the new language features.
Where does the line fall between adopting functional ideas that genuinely improve Java code and chasing theoretical purity that only adds ceremony? A frank look at what FP concepts are worth carrying into production Java, and which ones are better left in the research papers.
Version 0.0.10 brings sequence and traverse combinators to Try, Optional interop for both Result and Try, and a full set of Stream collectors for Result including stream(), toList(), and partitioningBy().
Learn how to model error-handling as two parallel tracks—success and failure—using pure Java and a Result type, eliminating scattered exceptions and making your business pipelines composable, readable, and testable.
Immutability is one of those ideas that sounds simple—an object doesn’t change after it’s created—but has surprisingly deep consequences for design quality, correctness, and long-term maintainability.
Explore powerful composition patterns to build complex functionality from simple, reusable functions
Introducing the dmx-fun blog - your resource for functional programming in Java