Book Review: Functional Thinking

Rating: 8/10

The purpose of Functional Thinking is to help intermediate to advanced programmers familiar with imperative programming to start thinking in a more ‘functional’ way. At 157 pages it’s not a big book, which is not a criticism. I am encouraged to get stuck in knowing that it’s unlikely to be a hard slog.

The chapters are cleverly laid out to take you through the shift in mindset as you progress through the book. From “Why”: usual intro stuff, to “Shift”: where Ford runs through the fundamental building blocks presenting some problems solved in Java, Scala, Groovy, and Clojure, to “Cede”: giving up control of low-level machinery to the runtime freeing you to work on more relevant problems, to “Smarter, not Harder”: presenting language features that solve common problems such as caching and lazy loading.

The book extensively uses Java8, Scala, Groovy, and Clojure for the examples. It turns out the languages are not consistent in their naming of the core constructs so it was incredibly useful to link the concepts to the different implementations. A good smattering of examples using the Functional Java library for pre-Java8 JDK’s will be a welcome addition to developers keen to start using the tools but stuck on old JDK versions.

The last part of the book gives a run through of the new functional language support in Java8 and concludes with a discussion the polygot world where developers work with imperative and functional paradigms together.

As a Java developer I found this a good introduction to Functional Programming and found the level of abstraction just right for me to get a handle on the concepts without getting lost in code. Don’t get me wrong, there’s a lot of code, but its for example rather than explanation.


Disclosure: I received a copy of this book from the publisher in exchange for reviewing this book on behalf of coderanch.com

Book Review: The Joy of Clojure (2nd Edition)

Rating: 9/10

‘The Joy of Clojure’ teaches intermediate to advanced programmers how to write Clojure the ‘Clojure way’. The authors assume a familiarity with the common Lisp syntax which allows them to concentrate on the useful and interesting topics such as concurrency, parallelism, and performance.

The opening chapters present a whirlwind introduction to the Clojure language. The authors start with the philosophy behind Clojure, continuing with “Drinking from the Clojure fire hose” which, as the chapter name suggests, is an intensive spin through the bare necessities of the language.

The authors have managed to delve into many of the language features that will allow the seasoned programmer to solve a multitude of difficult problems including interoperability with the Java JDK. Excellent worked examples demonstrate the syntax of the Clojure language. This will be extremely useful to the reader not overly familiar with Clojure or common Lisp.

The final chapter touches on the very interesting topic of building your own Domain Specific Language, thus narrowing the gap between your domain language and your programming language. ‘The Joy of Clojure’ concludes with a useful run through of some of the Gang of Four design patterns that can can be achieved using Clojure’s built in language features.

A more comprehensive exploration into the topic of testing would have been a welcome addition. However, The ‘Joy of Clojure’ is an excellent title and the problem solving approach sets it apart from almost all other Clojure titles available today. Highly recommended.


Disclosure: I received a copy of this book from the publisher in exchange for reviewing this book on behalf of coderanch.com

This is a scenario that comes up from time to time when working with Legacy Code. You’re trying to get some code into a test harness but there’s a local helper method being used that’s difficult to instantiate and you want to replace it with a fake, or Test Double.

package mocklocalmethod;

  public interface ThingsToBeDone {
    public void doAllTheThings();
  }
}
package mocklocalmethod;
 
public class ActualThingsToBeDone implements ThingsToBeDone {
    @Override
    public void doAllTheThings() {
        doTheFirstThing();
        doTheSecondThing();
    }
 
    private void doTheFirstThing() {
        // Hard to test stuff
    }
 
    private void doTheSecondThing() {
        // Hard to test stuff
    }
}

Mockito, and the like, don’t provide you the ability to do verifications on local instance methods but we can do it ourselves by creating a testable version of the class you want to test. We do this by creating a subclass that overrides the collaborator methods and provides access to inspect whether those methods have been called. We’ll need to change the scope of the private collaborator methods from private to protected but that’s a minor sacrifice for the gains of having your code in a test harness.

package mocklocalmethod;
 
import mocklocalmethod.ActualThingsToBeDone;
import org.junit.Test;
 
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
 
public class ActualThingsToBeDoneTest {
 
    @Test
    public void doAllTheThings_shouldCall_doTheFirstThing_and_doTheSecondThing() {
        TestableThingsToBeDone thingsToBeDone = new TestableThingsToBeDone();
 
        thingsToBeDone.doAllTheThings();
 
        assertThat(thingsToBeDone.hasTheFirstThingBeenDone(), is(true));
        assertThat(thingsToBeDone.hasTheSecondThingBeenDone(), is(true));
    }
 
    private class TestableThingsToBeDone extends ActualThingsToBeDone {
        private boolean firstThingDone = false;
        private boolean secondThingDone = false;
 
        @Override
        protected void doTheFirstThing() {
            this.firstThingDone = true;
        }
 
        @Override
        protected void doTheSecondThing() {
            this.secondThingDone = true;
        }
 
        public boolean hasTheFirstThingBeenDone() {
            return firstThingDone;
        }
 
        public boolean hasTheSecondThingBeenDone() {
            return secondThingDone;
        }
    }
}

From here it’s not difficult to change it to make assertions on the order and frequency in which the collaborating methods are called.

I recently wrote an article about how to Annotate Your Magic Numbers which explored a solution for times when you have to pass some parameter values but it’s not entirely clear what they mean. I used this code as an example:

public class Range {
  private final int lowerBound;
  private final int upperBound;
   
  public Range(int lowerBound, int upperBound) {
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
  }
 
  public boolean isInRange(int number) {
    return (number >= lowerBound) && (number <= upperBound);
  }
}
public class RangeTest {
  @Test
  public void shouldReturnFalseIfNotInRange() {
    Range range = new Range(1, 10);
    assertThat(range.isInRange(11), is(false));
  }
}

In the highlighted line it is not clear what the values “1” and “10” are. Another approach you can take is to introduce a Domain Specific Language to provide the missing context and improve the readability of your tests. Sounds good but how would you go about it…

I’ll start by doing an Extract Method refactor on the Range object constructor giving the extracted method a name that provides some context to the parameters. I think “rangeBetweenBounds()” sounds like a good name.

@Test
public void shouldReturnFalseIfNotInRange() {
  Range range = rangeBetweenBounds(1, 10);
  assertThat(range.isInRange(11), is(false));
}
 
private Range rangeBetweenBounds(int lowerBound, int upperBound) {
  return new Range(lowerBound, upperBound);
}

Now I notice that the temporary variable range is not really necessary so I do an Inline Temp refactor on that.

@Test
public void shouldReturnFalseIfNotInRange() {
  assertThat(rangeBetweenBounds(1, 10).isInRange(11), is(false));
}

At this point I could probably stop. The introduction of the rangeBetweenBounds() method has provided a DSL that can be used to create Range objects with given bounds. I can reuse this in other test cases.

However, now I’ve done this I can see that the isInRange() method name doesn’t really read very well. I’m pretty sure I can do better. A quick Rename Method refactor and I’m now at a stage where I’m quite happy with how things have turned out. The test case is down to a single line of code and I think the intent and language is clear.

public class Range {
  private final int lowerBound;
  private final int upperBound;
 
  public Range(int lowerBound, int upperBound) {
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
  }
 
  public boolean contains(int number) {
    return (number >= lowerBound) && (number <= upperBound);
  }
}
public class RangeTest {
  @Test
  public void shouldNotContainOutOfBoundsValue() {
    assertThat(rangeBetweenBounds(1, 10).contains(11), is(false));
  }
 
  private Range rangeBetweenBounds(int lowerBound, int upperBound) {
    return new Range(lowerBound, upperBound);
  }
}

While working on the readability of my test I discovered a better name for the “isInRange” method in the production code. Renaming it to “contains” has now made the method more natural to use and expresses its behaviour more clearly. I started off trying to improve my tests, and ended up improving my production code too. For me that’s a massive win.

We all know that Magic Numbers are pretty high up on the list of programming sins, but I still see them, and have written them, a lot. I find that they are particularly prevalent in Test code where you might think it doesn’t matter so much. In fact, it is as important to make your intent clear in Tests as it is in Production code. Here’s a nice easy example with an accompanying Unit Test with some Magic Numbers in it. (I’m using Java for this example but it isn’t important)

public class Range {
  private final int lowerBound;
  private final int upperBound;
 
  public Range(int lowerBound, int upperBound) {
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
  }
 
  public boolean isInRange(int number) {
    return (number >= lowerBound) && (number <= upperBound);
  }
}
public class RangeTest {
  @Test
  public final void shouldReturnFalseIfNotInRange() {
    Range range = new Range(1, 10);
    assertThat(range.isInRange(11), is(false));
  }
}

I have highlighted the line of code I’m particularly interested in where we have a couple of Magic Numbers, the “1” and “10”. Reading this article it’s kind of obvious what they are because we have the Range() constructor implementation just a few lines away, but in a real system that would be in a different file and would require you to go and find it. This sounds like a trivial problem but it’s a diversion that interrupts your flow of thinking about the test. So what can we do about it?

We can annotate them with a name.

For languages such as Java that do not support named parameters there’s a nice little trick we can employ that uses simple helper methods as annotations to provide naming.

public class RangeTest {
  @Test
  public final void shouldReturnFalseIfNotInRange() {
    Range range = new Range(lowerBound(1), upperBound(10));
    assertThat(range.isInRange(11), is(false));
  }
}
 
private int lowerBound(int lowerBound) {
  return lowerBound;
}
 
private int upperBound(int upperBound) {
  return upperBound;
}

Simply wrapping the parameter values in a private method, that simply returns the value it’s given, allows you to use the method name as a means to give the Magic Numbers a name.