dtonhofer

dtonhofer

Functional Programming in Java, Second Edition: Functional Programming in Java, Second Edition: JUnit code improvements for Chapter 11, pages 189 ff “Refactoring to Rework the Logic”

The usual changes but:

  • The “FirstRepeatedLetter.findIn()” has been improved out of the box. In particular returning ‘\0’ is too C-like and smells like “primitive obsession”. We have null, we should use it. What if the input contains \0 as the matching character?
  • A slightly better code (IMHO) is in FirstRepeatedLetterBetter.findIn()
  • The final refactored code returns not null, but Optional<Character>, which is cleaner.
  • Again, for testing we use a common interface or a wrapper class to avoid having to duplicate testing code.
package chapter11;

import org.junit.jupiter.api.Test;

import java.util.Optional;
import java.util.stream.Stream;

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

public class ReworkTheLogicTest {

    interface FindLetter {

        Character findIn(String word);

    }

    static class FirstRepeatedLetterBefore implements FindLetter {

        public Character findIn(final String word) {
            final char[] letters = word.toCharArray();
            for (char candidate : letters) {
                int count = 0;
                for (char letter : letters) {
                    if (candidate == letter) {
                        count++;
                    }
                }
                if (count > 1) {
                    return candidate;
                }
            }
            return null;
        }
    }

    static class FirstRepeatedLetterBetter implements FindLetter {

        public Character findIn(final String word) {
            char[] letters = word.toCharArray();
            int i = 0;
            Character found = null;
            while (i < letters.length && found == null) {
                // will letter[i] been seen again?
                char maybe = letters[i];
                int j = i + 1;
                while (j < letters.length && letters[j] != maybe) j++;
                if (j < letters.length) {
                    found = maybe;
                } else {
                    i++;
                }
            }
            return found;
        }
    }

    // Does NOT implement "FindLetter", returns Optional<Character>

    static class FirstRepeatedLetterAfter {

        public Optional<Character> findIn(final String word) {
            return Stream.of(word.split(""))
                    .filter(letter -> word.lastIndexOf(letter) > word.indexOf(letter))
                    .findFirst()
                    .map(letter -> letter.charAt(0));
        }
    }

    static class FirstRepeatedLetterAfterWrapped implements FindLetter {

        private final FirstRepeatedLetterAfter finder;

        public FirstRepeatedLetterAfterWrapped(FirstRepeatedLetterAfter finder) {
            this.finder = finder;
        }

        public Character findIn(final String word) {
            return finder.findIn(word).orElse(null);
        }
    }

    private static void commonFindFirstRepeatingTests(final FindLetter finder) {
        assertAll(
                () -> assertEquals('l', finder.findIn("hello")),
                () -> assertEquals('h', finder.findIn("hellothere")),
                () -> assertEquals('a', finder.findIn("magicalguru")),
                () -> assertEquals('z', finder.findIn("abcdefghijklmnopqrstuvwxyzz")),
                () -> assertNull(finder.findIn("once")),
                () -> assertNull(finder.findIn(""))
        );
    }

    @Test
    void findFirstRepeatingBefore() {
        commonFindFirstRepeatingTests(new FirstRepeatedLetterBefore());
    }

    @Test
    void findFirstRepeatingBetter() {
        commonFindFirstRepeatingTests(new FirstRepeatedLetterBetter());
    }

    @Test
    void findFirstRepeatingAfter() {
        commonFindFirstRepeatingTests(new FirstRepeatedLetterAfterWrapped(new FirstRepeatedLetterAfter()));
    }

}

Where Next?

Popular Pragmatic Bookshelf topics Top

jimmykiang
This test is broken right out of the box… — FAIL: TestAgent (7.82s) agent_test.go:77: Error Trace: agent_test.go:77 agent_test.go:...
New
mikecargal
Title: Hands-On Rust (Chapter 11: prefab) Just played a couple of amulet-less games. With a bit of debugging, I believe that your can_p...
New
edruder
I thought that there might be interest in using the book with Rails 6.1 and Ruby 2.7.2. I’ll note what I needed to do differently here. ...
New
jdufour
Hello! On page xix of the preface, it says there is a community forum "… for help if your’re stuck on one of the exercises in this book… ...
New
raul
Hi Travis! Thank you for the cool book! :slight_smile: I made a list of issues and thought I could post them chapter by chapter. I’m rev...
New
joepstender
The generated iex result below should list products instead of product for the metadata. (page 67) iex&gt; product = %Product{} %Pento....
New
AufHe
I’m a newbie to Rails 7 and have hit an issue with the bin/Dev script mentioned on pages 112-113. Iteration A1 - Seeing the list of prod...
New
taguniversalmachine
Hi, I am getting an error I cannot figure out on my test. I have what I think is the exact code from the book, other than I changed “us...
New
tkhobbes
After some hassle, I was able to finally run bin/setup, now I have started the rails server but I get this error message right when I vis...
New
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
DevotionGeo
I know that these benchmarks might not be the exact picture of real-world scenario, but still I expect a Rust web framework performing a ...
New
Exadra37
I am thinking in building or buy a desktop computer for programing, both professionally and on my free time, and my choice of OS is Linux...
New
Exadra37
Please tell us what is your preferred monitor setup for programming(not gaming) and why you have chosen it. Does your monitor have eye p...
New
DevotionGeo
The V Programming Language Simple language for building maintainable programs V is already mentioned couple of times in the forum, but I...
New
PragmaticBookshelf
Create efficient, elegant software tests in pytest, Python's most powerful testing framework. Brian Okken @brianokken Edited by Kat...
New
PragmaticBookshelf
Rails 7 completely redefines what it means to produce fantastic user experiences and provides a way to achieve all the benefits of single...
New
AstonJ
Was just curious to see if any were around, found this one: I got 51/100: Not sure if it was meant to buy I am sure at times the b...
New
New
NewsBot
Node.js v22.14.0 has been released. Link: Release 2025-02-11, Version 22.14.0 'Jod' (LTS), @aduh95 · nodejs/node · GitHub
New

Latest in Functional Programming in Java, Second Edition

Functional Programming in Java, Second Edition Portal

Sub Categories: