File tree Expand file tree Collapse file tree 12 files changed +268
-0
lines changed
src/main/java/org/kunicki/functional_java Expand file tree Collapse file tree 12 files changed +268
-0
lines changed Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java ;
2+
3+ import org .kunicki .functional_java .api .Api ;
4+ import org .kunicki .functional_java .domain .Service ;
5+
6+ public class Application {
7+
8+ private void start () {
9+ // load config
10+ // create database connection pool
11+
12+ // create repository
13+ final var service = new Service (/* repository */ );
14+ final var api = new Api (service );
15+
16+ // HTTP server
17+ // ...
18+ }
19+
20+ // @SpringBootApplication
21+ public static void main (String [] args ) {
22+ // SpringApplication.run(Application.class, args);
23+ new Application ().start ();
24+ }
25+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java ;
2+
3+ record Person (String name , int age ) {
4+ }
5+
6+ interface PersonValidator {
7+
8+ //region Common validation logic
9+ default boolean isNameValid (String name ) {
10+ return name .startsWith ("M" );
11+ }
12+
13+ default boolean isAgeValid (int age ) {
14+ return age == 38 ;
15+ }
16+ //endregion
17+ }
18+
19+ class FailingFast implements PersonValidator {
20+
21+ }
22+
23+ class Accumulating implements PersonValidator {
24+
25+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .api ;
2+
3+ import org .kunicki .functional_java .domain .Service ;
4+
5+ public class Api {
6+
7+ private final Service service ;
8+
9+ public Api (Service service ) {
10+ this .service = service ;
11+ }
12+
13+ public Response <?> findUserById (Long id ) {
14+ final var user = service .findUserById (id );
15+ return user
16+ .map (Response ::ok )
17+ .orElse (Response .notFound ());
18+
19+ //region Questions
20+ /*
21+ Q: Can you tell whether the service can respond with expected/business/domain errors?
22+ */
23+ /*
24+ Q: What happens to those errors?
25+ */
26+ /*
27+ Q: Are GOTO statements good?
28+ */
29+ /*
30+ Q: What if we represented expected errors as plain values?
31+ */
32+ //endregion
33+ }
34+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .api ;
2+
3+ sealed interface Response <T > {
4+
5+ record Ok <T >(T value ) implements Response <T > {
6+ }
7+
8+ record NotFound <T >() implements Response <T > {
9+ }
10+
11+ record ServerError (String message ) implements Response <String > {
12+ }
13+
14+ //region Factory methods
15+ static <T > Response <T > ok (T value ) {
16+ return new Ok <>(value );
17+ }
18+
19+ static <T > Response <T > notFound () {
20+ return new NotFound <>();
21+ }
22+
23+ static Response <String > serverError (String message ) {
24+ return new ServerError (message );
25+ }
26+ //endregion
27+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .common ;
2+
3+ public interface Attempt <A > {
4+
5+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .common ;
2+
3+ public sealed interface Or <L , R > {
4+
5+ record Left <L , R >(L value ) implements Or <L , R > {
6+ }
7+
8+ record Right <L , R >(R value ) implements Or <L , R > {
9+ }
10+
11+ //region Factory methods
12+ static <L , R > Or <L , R > left (L value ) {
13+ return new Left <>(value );
14+ }
15+
16+ static <L , B > Or <L , B > right (B value ) {
17+ return new Right <>(value );
18+ }
19+ //endregion
20+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .domain ;
2+
3+ class Data {
4+
5+ private Long id ;
6+
7+ private String value ;
8+
9+ public Data (Long id , String value ) {
10+ this .id = id ;
11+ this .value = value ;
12+ }
13+
14+ public Long getId () {
15+ return id ;
16+ }
17+
18+ public void setId (Long id ) {
19+ this .id = id ;
20+ }
21+
22+ public String getValue () {
23+ return value ;
24+ }
25+
26+ public void setValue (String value ) {
27+ this .value = value ;
28+ }
29+
30+ // equals, hashCode, toString
31+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .domain ;
2+
3+ //region Immutable Data
4+
5+ class ImmutableData {
6+
7+ }
8+ //endregion
9+
10+ //region Record
11+ //endregion
12+
13+ //region Record test
14+
15+ class RecordTest {
16+
17+ public static void main (String [] args ) {
18+
19+ }
20+ }
21+ //endregion
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .domain ;
2+
3+ import java .util .Optional ;
4+
5+ public class Service {
6+
7+ //region Pure functions
8+
9+ //region Definition
10+ /*
11+ Q: What makes a function pure?
12+ * the output only depends on the inputs
13+ * no side effects
14+ */
15+ //endregion
16+
17+ long doStuff (final long n , final Data data ) {
18+ /*
19+ P: mutates the argument
20+ */
21+ data .setValue ("devoxxpl" );
22+
23+ /*
24+ P: interacts with I/O
25+ */
26+ System .out .println (n );
27+
28+ /*
29+ P: depends on something external
30+ P: the if statement does not have a value
31+ */
32+ if (System .currentTimeMillis () % 2 == 0 ) {
33+ return n ;
34+ } else {
35+ return n + 1 ;
36+ }
37+ }
38+
39+ //region Tips
40+ /*
41+ T: Use (immutable) values wherever possible
42+ */
43+ /*
44+ T: Control the side effects
45+ */
46+ /*
47+ T: Prefer immutability as a rule of thumb
48+ */
49+ //endregion
50+
51+ //endregion
52+
53+ //region Error handling
54+ public Optional <User > findUserById (Long id ) {
55+ return Optional .of (new User (42L , "Jacek" ));
56+ }
57+
58+ //region Tips
59+ /*
60+ T: Return expected errors as plain values
61+ */
62+ /*
63+ T: Keep a catch-all error handler for truly unexpected errors
64+ */
65+ //endregion
66+ //endregion
67+ }
Original file line number Diff line number Diff line change 1+ package org .kunicki .functional_java .domain ;
2+
3+ public record User (Long id , String name ) {
4+ }
You can’t perform that action at this time.
0 commit comments