Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns:...
Transcript of Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns:...
![Page 1: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/1.jpg)
Functional TDDIs TDD redundant with
Functional Programming?
![Page 2: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/2.jpg)
@johanneslinkjohanneslink.net
![Page 3: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/3.jpg)
TDD à la Kent Beck
• Developers write automated tests while they program
• Tests are written before production code
• Design takes place step by step
![Page 4: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/4.jpg)
Feedback für unser Design:Test-Code-Refactor
Tests OKTests Fail
1) Add failing test
2) Implement
3) Simplify & Refactor
![Page 5: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/5.jpg)
Feedback for functional quality: Well-tested code
•Enough tests to keep up trust
•Tests are maintainable and understandable
•Most tests are microtests
![Page 6: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/6.jpg)
Functional Programming?Essential. Helpful.
Providing additional insights.
![Page 7: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/7.jpg)
Essential
•Pure functions
•Higher order functions
•Immutable data structures
![Page 8: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/8.jpg)
Java?
•Pure functions
•Higher order functions
•Immutable data structures
![Page 9: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/9.jpg)
(Very) helpful•Functions as top-level constructs
•Anonymous functions aka lambdas
•Type system & syntax friendly to HOFs
•Create flexible data structures on the fly
•Pattern Matching
•Tail recursion optimisation
![Page 10: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/10.jpg)
Java?•Functions as top-level constructs
•Anonymous functions aka lambdas
•Type system & syntax friendly to HOFs
•Create flexible data structures on the fly
•Pattern Matching
•Tail recursion optimisation
![Page 11: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/11.jpg)
Providing additional insight
•Clear separation of pure and non-pure
•Algebraic type system
•Lazy Evaluation
![Page 12: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/12.jpg)
A
042 051:+
-R
B
![Page 13: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/13.jpg)
SCOREBOARD started.000:000aTeam A selected+001:000+002:000bTeam B selected+002:001-002:000c000:000x
![Page 14: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/14.jpg)
Java ScoreboardObject-oriented inside-out TDD
![Page 15: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/15.jpg)
public class ScoreboardAppTests {private ScoreboardApp app;@Test void initialScoreIs000to000() {
Console console = mock(Console.class);app = new ScoreboardApp(new Scoreboard(), console);app.run();verify(console).println("000:000");
}}
![Page 16: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/16.jpg)
Scoreboard
ScoreboardApp <<interface>> Console
SystemConsole<<interface>> ScoreboardModel
![Page 17: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/17.jpg)
Scoreboard
ScoreboardApp <<interface>> Console
SystemConsole<<interface>> ScoreboardModel
<<Mock>>
ScoreboardAppTests 11 Micro-Tests
<<Mock>>
ScoreboardTests 10 Micro-Tests
![Page 18: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/18.jpg)
public class ScoreboardAppTests @Nested class ScorePrinting void initialScoreIsTakenFromScoreboard() void scoreIsPrintedIn000Format() void moreThan3DigitsAreLeftAlone() @Nested class Commands void commandASelectsTeamA() void commandBSelectsTeamB() void commandPlusIncrementsScoreboard() void commandMinusDecrementsScoreboard() void commandRResetsScoreOnScoreboard() void commandsAreTrimmed() void commandsAreConvertedToLowercase() void unknownCommandsAreIgnored()
![Page 19: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/19.jpg)
public class ScoreboardTests void initialScoreIs000to000() void initiallyNoTeamIsSelected() void selectingTeamAMakesItSelected() void selectingTeamBMakesItSelected() void lastSelectCallIsRelevant() void incrementIncrementsScoreOfSelectedTeam() void decrementDecrementsScoreOfSelectedTeam() void whenNoTeamIsSelectedIncrementAndDecrementLeaveScoreAsIs() void resetScoreSetsScoreTo0to0() void noTeamSelectedAfterReset()
![Page 20: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/20.jpg)
Typical OO tests
We need test-doubles to verify state and side-effects.
Such tests are often hard to grasp and give you the feeling of testing the implementation.
![Page 21: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/21.jpg)
Haskell ScoreboardFunctional inside-out TDD
![Page 22: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/22.jpg)
import Scoreboard import ScoreboardApp
spec :: Spec spec = do
describe "ScoreboardApp.process" $ do it "initial score is 000:000" $ do process newScoreboard [] `shouldBe` ["000:000"]
describe "Scoreboard" $ do it "current score of new scoreboard is 0 : 0" $ do let scoreboard = newScoreboard currentScore scoreboard `shouldBe` (0, 0)
![Page 23: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/23.jpg)
process :: [String] -> [String]
/** * @param commandLines List of entered commands * @return List of console messages to print */List<String> process(List<String> commandLines)
![Page 24: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/24.jpg)
lines: [String]
process
messages: [String]
![Page 25: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/25.jpg)
lines: [String]
toCommands
commands : [Command]
process
messages: [String]
![Page 26: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/26.jpg)
lines: [String]
toCommands
commands : [Command]
toActions
actions : [Action]
process
messages: [String]
![Page 27: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/27.jpg)
lines: [String]
toCommands
commands : [Command]
toActions
actions : [Action]
act
process
messages: [String]
![Page 28: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/28.jpg)
lines: [String]
toCommands
commands : [Command]
toActions
actions : [Action]
actScoreboard
process
messages: [String]
![Page 29: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/29.jpg)
lines: [String]
toCommands
commands : [Command]
toActions
actions : [Action]
actScoreboard formatScore
process
messages: [String]
![Page 30: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/30.jpg)
Verify processing stepsdescribe "ScoreboardApp.toCommands" $ do
it "lines are converted to commands" $ do toCommands ["a", "b", "+", "-", "r", "x"] `shouldBe`
[SelectA, SelectB, Increment, Decrement, ResetBoard, Exit]
it "lines are sanitized before conversion" $ do toCommands [" a ", "B"] `shouldBe` [SelectA, SelectB]
it "unknown commands are skipped" $ do toCommands ["a", "z", "ab", "x"] `shouldBe` [SelectA, Exit]
![Page 31: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/31.jpg)
Verify score formattingdescribe "ScoreboardApp.formatScore" $ do
it "single digit scores are filled in with zeros" $ do formatScore (1, 9) `shouldBe` "001:009"
it "multi digit scores are filled in if necessary" $ do formatScore (11, 999) `shouldBe` "011:999"
it "more than 3 digits are left alone" $ do formatScore (1234, 98765) `shouldBe` "1234:98765"
![Page 32: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/32.jpg)
ScoreboardAppCommand, ActionloopprocessformatScoretoCommandsprocessCommandsgetAction
ScoreboardScore, Selection, ScoreboardnewScoreboardselectTeamincrementScoredecrementScoreresetScore
![Page 33: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/33.jpg)
ScoreboardAppCommand, ActionloopprocessformatScoretoCommandsprocessCommandsgetAction
ScoreboardAppSpec 14 microtests
ScoreboardTests 6 microtests
ScoreboardScore, Selection, ScoreboardnewScoreboardselectTeamincrementScoredecrementScoreresetScore
![Page 34: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/34.jpg)
Why does process work?getContents :: IO String putStrLn :: String -> IO ()
loop :: IO () loop = do contents <- getContents let commandLines = lines contents let messages = process newScoreboard commandLines mapM_ putStrLn messages
![Page 35: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/35.jpg)
Why does process work?getContents :: IO String putStrLn :: String -> IO ()
loop :: IO () loop = do contents <- getContents let commandLines = lines contents let messages = process newScoreboard commandLines mapM_ putStrLn messages
IO<String> getContents() IO putStrLn(String)
![Page 36: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/36.jpg)
Why does process work?getContents :: IO String putStrLn :: String -> IO ()
loop :: IO () loop = do contents <- getContents let commandLines = lines contents let messages = process newScoreboard commandLines mapM_ putStrLn messages
Lazy IO + Infinite Lists: Der Input und Output erfolgt nach und nach
IO<String> getContents() IO putStrLn(String)
![Page 37: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/37.jpg)
Typical tests for functional code
•Mostly everything consists of pure functions, which can be directly tested ‣ Parameterise function under test with real values and
real functions
‣ Only for "outer" impure functions you might need mocks
![Page 38: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/38.jpg)
@Test void incrementIncrementsScoreOfSelectedTeam() {scoreboard.setScore(1, 2);scoreboard.selectTeamA();scoreboard.increment();assertScore(2, 2);assertTrue(scoreboard.isTeamASelected());scoreboard.setScore(1, 2);scoreboard.selectTeamB();scoreboard.increment();assertScore(1, 3);assertTrue(scoreboard.isTeamBSelected());}
it "incrementing score of selected team" $ do
let scoreboardA = (Scoreboard (1, 2) TeamA)incrementScore scoreboardA `shouldBe` (Scoreboard (2, 2) TeamA)
let scoreboardB = (Scoreboard (1, 2) TeamB)incrementScore scoreboardB `shouldBe` (Scoreboard (1, 3) TeamB)
![Page 39: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/39.jpg)
Property Testing: Verify universally desired properties
of a function
![Page 40: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/40.jpg)
Property Testing: Verify universally desired properties
of a function
"Trying to decrease a team's score should never result in a negative score"
![Page 41: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/41.jpg)
Quickcheckdescribe "Scoreboard Properties" $ do
it "decrementing is always possible" $ property $ prop_decrementing
prop_decrementing :: Scoreboard -> Bool prop_decrementing scoreboard =
scoreA >= 0 && scoreB >= 0 where decrementedBoard = decrementScore scoreboard (scoreA, scoreB) = currentScore decrementedBoard
![Page 42: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/42.jpg)
Quickcheckdescribe "Scoreboard Properties" $ do
it "decrementing is always possible" $ property $ prop_decrementing
prop_decrementing :: Scoreboard -> Bool prop_decrementing scoreboard =
scoreA >= 0 && scoreB >= 0 where decrementedBoard = decrementScore scoreboard (scoreA, scoreB) = currentScore decrementedBoard
![Page 43: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/43.jpg)
http://jqwik.net @Property boolean decrementingIsAlwaysPossible(@ForAll Scoreboard scoreboard) {
scoreboard.decrement();return
scoreboard.scoreTeamA() >= 0 && scoreboard.scoreTeamB() >= 0;
}
![Page 44: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/44.jpg)
http://jqwik.net @Property boolean decrementingIsAlwaysPossible(@ForAll Scoreboard scoreboard) {
scoreboard.decrement();return
scoreboard.scoreTeamA() >= 0 && scoreboard.scoreTeamB() >= 0;
}
org.opentest4j.AssertionFailedError: Property [decrementingIsAlwaysPossible] failed: Falsified ( propertyName = decrementingIsAlwaysPossible, count = 164, sample = (Scoreboard (-1,0) TeamA) )
![Page 45: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/45.jpg)
org.opentest4j.AssertionFailedError: Property [decrementingIsAlwaysPossible] failed: Falsified ( propertyName = decrementing is always possible, count = 28, sample = (Scoreboard (-1,0) TeamA)
)
![Page 46: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/46.jpg)
org.opentest4j.AssertionFailedError: Property [decrementingIsAlwaysPossible] failed: Falsified ( propertyName = decrementing is always possible, count = 28, sample = (Scoreboard (-1,0) TeamA)
)
![Page 47: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/47.jpg)
Types and testing•Algebraic type system makes creating and
passing values safer ‣ Fewer tests needed for object initialisation and state
changes
•Dependent type (as in Idris) can sometimes enforce the correct implementation ‣ No more tests necessary for this "enforced" implementation?
![Page 48: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/48.jpg)
What can we learn for Java?
•Applicable functional patterns: ‣ Use "Immutables" whenever possible
‣ Use pure functions whenever possible
‣ Use total functions whenever possible
‣ Use property testing for pure functions
‣ Hexagonal architecture (aka Ports and Adaptors): Impure behaviour only in the outer layers
![Page 49: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/49.jpg)
Could we rebuild the functional solution in Java?
•Immutable value types: Possible but involved usage
•Pure functions: (Static) methods or variables on stateless objects / classes with no side-effects
•Property testing: jqwik/javaslang, junit-quickcheck
•Lazy IO: Can be simulated through Streams or Reactive Streams
![Page 50: Functional TDD - Johannes Link · What can we learn for Java? •Applicable functional patterns: ‣ Use "Immutables" whenever possible ‣ Use pure functions whenever possible ‣](https://reader033.fdocuments.net/reader033/viewer/2022053008/5f0bdef37e708231d4329fb1/html5/thumbnails/50.jpg)
The Code:http://github.com/jlink/functional-tdd