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

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
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
rmurray10127
Title: Intuitive Python: docker run… denied error (page 2) Attempted to run the docker command in both CLI and Powershell PS C:\Users\r...
New
Chrichton
Dear Sophie. I tried to do the “Authorization” exercise and have two questions: When trying to plug in an email-service, I found the ...
New
jskubick
I found an issue in Chapter 7 regarding android:backgroundTint vs app:backgroundTint. How to replicate: load chapter-7 from zipfile i...
New
Henrai
Hi, I’m working on the Chapter 8 of the book. After I add add the point_offset, I’m still able to see acne: In the image above, I re...
New
Keton
When running the program in chapter 8, “Implementing Combat”, the printout Health before attack was never printed so I assumed something ...
New
New
ggerico
I got this error when executing the plot files on macOS Ventura 13.0.1 with Python 3.10.8 and matplotlib 3.6.1: programming_ML/code/03_...
New
dachristenson
@mfazio23 Android Studio will not accept anything I do when trying to use the Transformations class, as described on pp. 140-141. Googl...
New

Other popular topics Top

AstonJ
Or looking forward to? :nerd_face:
498 13326 269
New
PragmaticBookshelf
Design and develop sophisticated 2D games that are as much fun to make as they are to play. From particle effects and pathfinding to soci...
New
AstonJ
I ended up cancelling my Moonlander order as I think it’s just going to be a bit too bulky for me. I think the Planck and the Preonic (o...
New
AstonJ
I have seen the keycaps I want - they are due for a group-buy this week but won’t be delivered until October next year!!! :rofl: The Ser...
New
PragmaticBookshelf
Learn different ways of writing concurrent code in Elixir and increase your application's performance, without sacrificing scalability or...
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
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
PragmaticBookshelf
Develop, deploy, and debug BEAM applications using BEAMOps: a new paradigm that focuses on scalability, fault tolerance, and owning each ...
New
Fl4m3Ph03n1x
Background Lately I am in a quest to find a good quality TTS ai generation tool to run locally in order to create audio for some videos I...
New

Latest in Functional Programming in Java, Second Edition

Functional Programming in Java, Second Edition Portal

Sub Categories: