Thinking Functionally in Java: From Pure Code to Reproducible Builds

Java has evolved far beyond the object-oriented patterns of the 90s, yet many developers use modern features (like Lambdas and Streams) within the same old imperative, side-effect-heavy frameworks. In this workshop, Daniel Hinojosa bridges the gap between the JVM and the rigorous world of functional programming (FP).

By stripping away the academic jargon of category theory and focusing on pragmatic application, attendees will learn how to build systems that are easier to test, harder to break, and—thanks to Nix—perfectly reproducible from the dev machine to production.

Course Modules
Part 1: The Functional Mindset & Referential Transparency
Before writing code, we must change how we think about “state.”

Total vs. Partial Functions: Why null and Exceptions are the enemies of predictable code.

Referential Transparency: Learning to write expressions that can be replaced by their values without changing program behavior.

Immutability by Default: Leveraging Java Records and unmodifiable collections to eliminate “spooky action at a distance.”

Part 2: Beyond the Stream – Advanced Data Pipelines
Moving from basic iteration to sophisticated data transformation.

The “M-Word” (Monads) without the Jargon: Understanding Optional, Stream, and CompletableFuture as containers for computation.

Function Composition: Building complex logic by “piping” small, single-responsibility functions together.

Declarative vs. Imperative: Refactoring nested if-else and for-loop blocks into clean, readable functional pipelines.

Part 3: Robust Error Handling (The “Either” Pattern)
Stop using try-catch for expected business logic failures.

Railway Oriented Programming: Modeling “Happy Paths” and “Error Paths” side-by-side.

The Result and Either Types: Hands-on implementation of custom types to force callers to handle errors at compile-time.

Validation: Combining multiple independent validations into a single functional result.

Part 4: The Twist – Functional Infrastructure with Nix
Functional principles aren't just for your .java files; they apply to your entire environment.

The Problem with “It Works on My Machine”: Why traditional build tools and Dockerfiles still suffer from state drift.

Nix Basics: Using the Nix expression language to define a purely functional development environment.

Hands-on Lab: Creating a flake.nix for the workshop project to ensure every attendee has the exact same JDK, tools, and dependencies, isolated from their OS.

Key Takeaways
Write “Boring” Code: Code that is so predictable it’s easy to debug and verify.

Eliminate Side Effects: Isolate your I/O and state changes to the “edges” of your application.

Master Reproducibility: Use Nix to ensure your build environment is as immutable as your code.

Functional Design Patterns: Learn when to use FP and when to stick to OOP (and how to mix them effectively).


About Daniel Hinojosa

Daniel is a programmer, consultant, instructor, speaker, and recent author. With over 20 years of experience, he does work for private, educational, and government institutions. He is also currently a speaker for No Fluff Just Stuff tour. Daniel loves JVM languages like Java, Groovy, and Scala; but also dabbles with non JVM languages like Haskell, Ruby, Python, LISP, C, C++. He is an avid Pomodoro Technique Practitioner and makes every attempt to learn a new programming language every year. For downtime, he enjoys reading, swimming, Legos, football, and barbecuing.

More About Daniel »