Examples

We've begun to develop some example code that demonstrates the use and utility of the Functor component.

In order to keep the examples in sync with the rest of the code, each example is written as a JUnit TestCase. The example programs are executed along with all the other unit tests, and can be invoked via ant test or maven test once you've set up Ant or Maven as described in the build instructions.

If you're not familiar with JUnit, don't worry. An understanding of JUnit isn't important for an understanding of these examples, and we'll walk you through the relevant bits anyway.

Two things you'll want to know about JUnit are (a) all the methods whose names start with "test" will be executed automatically by the test suite and (b) there are various "assert" methods that can be used to make assertions about the Objects being tested. If any assertion fails, the JUnit framework will count (and report) this as a test failure.

You can run a specific test case or sub-suite via Ant by invoking

ant -Dtest.entry=<fully-specified-test-case-name> test

or in Maven by invoking

maven -Dtestcase=<fully-specified-test-case-name> test:single

For example, to run the Quicksort example, invoke

ant -Dtest.entry=org.apache.commons.functor.example.QuicksortExample test

or

maven -Dtestcase=org.apache.commons.functor.example.QuicksortExample test:single

To run all the examples, invoke:

ant -Dtest.entry=org.apache.commons.functor.example.TestAll test

or

maven -Dtestcase=org.apache.commons.functor.example.TestAll test:single

Each example is has descriptive prose mixed right in with the source, as /* C++ style */ comments.

Code Katas

"Pragmatic" Dave Thomas has been blogging a series of programming exercises he calls Code Katas. These exercises are intended to provide "practice sesssions" that allow programmers to hone their craft. The notion is borrowed from the practice of Karate, where, in Dave's words "a kata is an exercise where you repeat a form many, many times, making little improvements in each".

Here we use several of Dave's Code Katas to explore the Commons-Functor library.

Kata One: Supermarket Pricing
Dave's Kata One asks how one might implement supermarket pricing rules, like "three for a dollar" or "buy two get one free". By encapsulating tiny bits of logic, functors provide a useful solution to this problem, as illustrated in the SupermarketPricingExample.
Kata Two: Binary Chop
Kata Two asks us to create several different implemenations of the binary search algorithm, which once you get past three or four implemenations, is more difficult that it sounds. TestBinaryChop presents several implementations, with functor and non-functor variations.
Kata Four: Data Munging
Kata Four asks us to explore extreme reuse. Our DataMunger allows for very small implementations of the weather and soccer (football) parsers.

Generators

The lines package demonstrates a functional approach to IO using Generators and the Algorithms class.

Reuse Through Composition

The Functor package, and more generally, a functional approach to program design, supports a powerful technique for balancing behavior specialization and code reuse.

Traditional Object Oriented design suggests inheritence as a mechanism code reuse, and method overloading as a mechanism for specialization. For example, one defines a general purpose, perhaps even abstract class, say AbstractList, and then extend or specialize this parent via subclasses, inheriting some behaviors and overloading others.

Functors encourage another, complementary approach to code reuse and behavior specialiazation: composition. Following a compositional design, we create a number of simple objects and then combine them to create more complex behaviors. For example, the Commons Pool component defines an ObjectPool type that maintains a collection of pooled objects, but delegates to a PoolableObjectFactory to create, validate and destroy the objects to be pooled. Arbitrary ObjectPool implementations can be composed with arbitrary PoolableObjectFactory implementations in order to create new types of pools.

The FlexiMap example applies this design to java.util.Map, demonstrating how "pluggable" functors can be applied to a generic Map structure in order to introduce new behaviors.

The map package is a more complete example of this, implementing a number of the Commons-Collections Maps derived from a base FunctoredMap.

A Quicksort Implementation

The Quicksort example presents an implementation of the Quicksort sorting algorithm written in a functional programming style using Commons Functor.