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

abtin
page 20: … protoc command… I had to additionally run the following go get commands in order to be able to compile protobuf code using go...
New
yulkin
your book suggests to use Image.toByteData() to convert image to bytes, however I get the following error: "the getter ‘toByteData’ isn’t...
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
alanq
This isn’t directly about the book contents so maybe not the right forum…but in some of the code apps (e.g. turbo/06) it sends a TURBO_ST...
New
fynn
This is as much a suggestion as a question, as a note for others. Locally the SGP30 wasn’t available, so I ordered a SGP40. On page 53, ...
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
brunogirin
When I run the coverage example to report on missing lines, I get: pytest --cov=cards --report=term-missing ch7 ERROR: usage: pytest [op...
New
creminology
Skimming ahead, much of the following is explained in Chapter 3, but new readers (like me!) will hit a roadblock in Chapter 2 with their ...
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
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

siddhant3030
I’m thinking of buying a monitor that I can rotate to use as a vertical monitor? Also, I want to know if someone is using it for program...
New
New
AstonJ
You might be thinking we should just ask who’s not using VSCode :joy: however there are some new additions in the space that might give V...
New
PragmaticBookshelf
Rust is an exciting new programming language combining the power of C with memory safety, fearless concurrency, and productivity boosters...
New
AstonJ
This looks like a stunning keycap set :orange_heart: A LEGENDARY KEYBOARD LIVES ON When you bought an Apple Macintosh computer in the e...
New
AstonJ
In case anyone else is wondering why Ruby 3 doesn’t show when you do asdf list-all ruby :man_facepalming: do this first: asdf plugin-upd...
New
AstonJ
We’ve talked about his book briefly here but it is quickly becoming obsolete - so he’s decided to create a series of 7 podcasts, the firs...
New
PragmaticBookshelf
Author Spotlight Mike Riley @mriley This month, we turn the spotlight on Mike Riley, author of Portable Python Projects. Mike’s book ...
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
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: