dtonhofer

dtonhofer

Functional Programming in Java, Second Edition: Functional Programming in Java, Second Edition: JUnit code improvements for Chapter 11, pages 185 ff “Refactoring Unbounded Loops”

The same remarks apply as for “Refactoring the Traditional for Loop”

  • No init()
  • Negative tests which apply for input less than 1900, resulting in exceptions.

but we cannot implement a common interface as the method parameters change. So we wrap the new class into a class that obeys the old interface, which agains llaows us to use the same test code to test both odl and new classes.

There is also a little tweak to the semantics of the case where 1900 is already rejected - instead of returning 0, we throw. Because there basically is no result in that case.

package chapter11;

import org.junit.jupiter.api.Test;

import java.time.Year;
import java.util.function.Predicate;
import java.util.stream.IntStream;

import static org.junit.jupiter.api.Assertions.*;

public class UnboundedLoopTest {

    interface Continue {

        boolean check(int year);

    }

    interface WithContinue {

        int countFrom1900(final Continue shouldContinue);

    }

    static class LeapYearsUnboundedBefore implements WithContinue {

        public int countFrom1900(final Continue shouldContinue) {
            if (!shouldContinue.check(1900)) {
                throw new IllegalArgumentException("Cannot 'continue' right at the start!'");
            }
            int count = 0;
            for (int year = 1900; ; year += 4) {
                if (!shouldContinue.check(year)) {
                    break;
                }
                if (Year.isLeap(year)) {
                    count++;
                }
            }
            return count;
        }
    }

    // Does NOT implement WithContinue!!

    static class LeapYearsUnboundedAfter {

        public int countFrom1900(final Predicate<Integer> shouldContinue) {
            if (!shouldContinue.test(1900)) {
                throw new IllegalArgumentException("Cannot 'continue' right at the start!'");
            }
            return (int) IntStream.iterate(1900, year -> year + 4)
                    .takeWhile(shouldContinue::test)
                    .filter(Year::isLeap)
                    .count();
        }
    }

    static class LeapYearsUnboundedAfterWrapped implements WithContinue {

        private final LeapYearsUnboundedAfter ly;

        public LeapYearsUnboundedAfterWrapped(LeapYearsUnboundedAfter ly) {
            this.ly = ly;
        }

        public int countFrom1900(final Continue shouldContinue) {
            return ly.countFrom1900(year -> shouldContinue.check(year));
        }

    }

    // One should maybe have a separate method to test the throws
    
    private static void commonLeapYearsTests(final WithContinue withContinue) {
        assertAll(
                () -> assertEquals(0, withContinue.countFrom1900(year -> year <= 1900)),
                () -> assertEquals(25, withContinue.countFrom1900(year -> year <= 2000)),
                () -> assertEquals(27, withContinue.countFrom1900(year -> year <= 2010)),
                () -> assertEquals(31, withContinue.countFrom1900(year -> year <= 2025)),
                () -> assertEquals(49, withContinue.countFrom1900(year -> year <= 2100)),
                () -> assertEquals(267, withContinue.countFrom1900(year -> year <= 3000)),
                () -> assertThrows(IllegalArgumentException.class, () ->
                        withContinue.countFrom1900(year -> year < 1800)
                ),
                () -> assertThrows(IllegalArgumentException.class, () ->
                        withContinue.countFrom1900(year -> year < 1900)
                )
        );
    }

    @Test
    void leapYearCountBefore() {
        commonLeapYearsTests(new LeapYearsUnboundedBefore());
    }

    @Test
    void leapYearCountAfter() {
        commonLeapYearsTests(new LeapYearsUnboundedAfterWrapped(new LeapYearsUnboundedAfter()));
    }

}

Where Next?

Popular Pragmatic Bookshelf topics Top

jesse050717
Title: Web Development with Clojure, Third Edition, pg 116 Hi - I just started chapter 5 and I am stuck on page 116 while trying to star...
New
herminiotorres
Hi! I know not the intentions behind this narrative when called, on page XI: mount() |&gt; handle_event() |&gt; render() but the correc...
New
HarryDeveloper
Hi @venkats, It has been mentioned in the description of ‘Supervisory Job’ title that 2 things as mentioned below result in the same eff...
New
curtosis
Running mix deps.get in the sensor_hub directory fails with the following error: ** (Mix) No SSH public keys found in ~/.ssh. An ssh aut...
New
adamwoolhether
I’m not quite sure what’s going on here, but I’m unable to have to containers successfully complete the Readiness/Liveness checks. I’m im...
New
brunogirin
When installing Cards as an editable package, I get the following error: ERROR: File “setup.py” not found. Directory cannot be installe...
New
adamwoolhether
Is there any place where we can discuss the solutions to some of the exercises? I can figure most of them out, but am having trouble with...
New
jwandekoken
Book: Programming Phoenix LiveView, page 142 (157/378), file lib/pento_web/live/product_live/form_component.ex, in the function below: d...
New
dtonhofer
@parrt In the context of Chapter 4.3, the grammar Java.g4, meant to parse Java 6 compilation units, no longer passes ANTLR (currently 4....
New
mcpierce
@mfazio23 I’ve applied the changes from Chapter 5 of the book and everything builds correctly and runs. But, when I try to start a game,...
New

Other popular topics Top

PragmaticBookshelf
Machine learning can be intimidating, with its reliance on math and algorithms that most programmers don't encounter in their regular wor...
New
dasdom
No chair. I have a standing desk. This post was split into a dedicated thread from our thread about chairs :slight_smile:
New
New
AstonJ
poll poll Be sure to check out @Dusty’s article posted here: An Introduction to Alternative Keyboard Layouts It’s one of the best write-...
New
AstonJ
Thanks to @foxtrottwist’s and @Tomas’s posts in this thread: Poll: Which code editor do you use? I bought Onivim! :nerd_face: https://on...
New
AstonJ
Just done a fresh install of macOS Big Sur and on installing Erlang I am getting: asdf install erlang 23.1.2 Configure failed. checking ...
New
AstonJ
Continuing the discussion from Thinking about learning Crystal, let’s discuss - I was wondering which languages don’t GC - maybe we can c...
New
PragmaticBookshelf
Author Spotlight: VM Brasseur @vmbrasseur We have a treat for you today! We turn the spotlight onto Open Source as we sit down with V...
New
CommunityNews
A Brief Review of the Minisforum V3 AMD Tablet. Update: I have created an awesome-minisforum-v3 GitHub repository to list information fo...
New
PragmaticBookshelf
A concise guide to MySQL 9 database administration, covering fundamental concepts, techniques, and best practices. Neil Smyth MySQL...
New

Latest in Functional Programming in Java, Second Edition

Functional Programming in Java, Second Edition Portal

Sub Categories: