Chapter 5. Better Object-Oriented Programming

Now that we have learned about functional programming and its benefits, let’s revisit object-oriented programming and see how we can do better with functional ideas.

Imperative, Mutable Code

Recall from Declarative vs. Imperative Programming that object-oriented programming is primarily imperative, where we tell the computer what to do, while functional programming is primarily declarative, where we define properties and relations, and let the runtime figure out how to compute what we want. We demonstrated the differences with two versions of the factorial function. The declarative version was clean and simple, while the imperative version was “busy” with mutations, making it harder to understand and prevent bugs. Those problems multiply if your whole code base is like that.

We’ve seen other reasons to avoid mutability. Mutable objects are not thread-safe by default and it’s easy for clients to change their state outside our control. Hence, we should make our objects immutable by removing setter methods and by declaring fields final. We should create new instances when the state changes and we should rely on persistent data structures for making efficient copies of large collections. We should avoid representing elaborate domain model object “graphs” in memory by limiting the parts of our domain models that we actually implement.

Sometimes we can’t avoid mutation. Since Java doesn’t perform tail-call optimization, declarativeFactorial won’t ...

Get Functional Programming for Java Developers now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.