Java Industry News
The Rise of Functional Java Programming
Better living without side effects
May. 23, 2008 02:00 PM
Java applications have become steadily harder to understand
and maintain in recent years. Object-oriented programming has proven an
effective way to develop enterprise applications, but several recent trends are
causing a sharp increase in code complexity. One is the increasingly common use
of the Factory design pattern, abstracting away the object creation process
(e.g., the creation of servlet objects by application servers, the use of
Spring as a general-purpose object factory, the use of JNDI, etc.) Another is
the increased use of the JavaBean pattern with reflection and annotations
(e.g., for object serialization and persistence). The result is that objects
have more mutable state than ever, and the code causing changes to that state
is increasingly decentralized. Programs are becoming easier to write, but
harder to debug as complexity spirals out of control.
Functional programming is a model of computation that avoids
making repeated changes to objects, and computes outputs from inputs in a
stateless way. The implications are far-reaching: functional programs are more
concise, easier to understand and debug, and can be executed more efficiently
on modern computer hardware. Although functional programming has been around
for a long time there has been a recent resurgence in interest with the advent
of languages like Scala, which support functional programming and can be
executed in a standard JVM. But even if you’re writing code in Java, you can
use functional programming patterns and achieve many of the benefits.
In this article we explain the basic principles of
functional programming, and show some functional patterns that you can start
using in your Java programs immediately.
The Problem
Object-oriented programming is about being able to define
packages of state, together with operations on that state. Typical
object-oriented languages support encapsulation, i.e., the notion that the
state can only be accessed via the defined operations, and polymorphism, i.e.,
the notion that objects of different types can be treated uniformly. Here is an
example that shows these concepts. The Reader interface defines an operation
for retrieving information one String at a time. The ArrayReader class
implements this interface, starting from an array of Strings and returning them
one at a time. The CharReader class also implements the same interface,
starting from any type of Reader and returning its output one character at a
time (see Listing 1).
Notice that both ArrayReader and CharReader have private,
internal state. It’s part of the benefit of object-oriented programming that
these implementations could be changed without affecting any other code as long
as the public interfaces are preserved.
About Joe MorrisonJoe Morrison is a managing consultant at Lab49, and has over 20 years of experience leading engineering teams in designing and building complex network-based applications. His projects have ranged from distributed object research at Verizon Laboratories, to value chain management software at Benchmarking Partners in Boston, to in-the-trenches SOA projects for financial services firms in New York. Joe holds a BMath degree in computer science from the University of Waterloo, and a master's degree in computer science from MIT. He is a regular blogger on http://blog.lab49.com/.
About Kalani ThielenKalani Thielen is a Lab49 technology consultant, working in the financial services industry. Prior to joining Lab49 in 2006, he worked for six years developing products for the publishing, advertising, and communications industries. As a specialist in programming language theory, his present work focuses on the development and certification of compilers for bond pricing and trading languages.