Commit fca2359e authored by Colin DAMON's avatar Colin DAMON

Merge branch '102-try-monade-code' into 'master'

Resolve "Try Monade code"

Closes #102

See merge request !78
parents 76bef70b 77626048
......@@ -34,3 +34,4 @@ include:
- local: "/bowling-game/.gitlab-ci.yml"
- local: "/tennis/greenfield-2/.gitlab-ci.yml"
- local: "/mastermind/.gitlab-ci.yml"
- local: "/try-monade/.gitlab-ci.yml"
# Twitch live codings
Ce dépôt Git a pour but de partager les différents ateliers pouvant être réalisés durant les sessions live coding d'Ippon Technologies sur sa chaîne Twitch.
- [Calendrier des lives](https://calendar.google.com/calendar/embed?src=c_07pbpmtv1a4d0iu48tnm6tl328%40group.calendar.google.com&ctz=Europe%2FParis) _A ajouter à votre agenda en cliquant sur le + en bas_
- [Chaîne Twitch](https://www.twitch.tv/ippontech)
- [Playlist Youtube (rediffusions)](https://www.youtube.com/playlist?list=PL6IFaLdAcgE3Uj2DYcbbxKJ-9moQe-g0F)
# Applications
On code entierement quelques petites applications les lives, n'hésitez pas à nous piquer des idées !
- [Borestop](/borestop): Utilisation de la pyramide de tests pour apporter rapidement de la valeure
- [PadBowl](https://gitlab.com/cdamon/padbowl): "Utilisation" du DDD dans une application basée sur JHipster
- [NERP](https://gitlab.com/cdamon/nerp): Utilisation des méthodologies présentées sur la chaine pour construire totalement une application (en cours)
# Kata
Un kata de code est un petit exercice pensé pour s'entrainer jusqu'à maitriser une compétence donnée.
## Java
### Facile
- [RomanNumerals](/roman-numerals)
- [Pagination Seven](/java-pagination-seven)
- [Mustache Replacer](/mustache-replacer)
- [Fizz Buzz](/fizz-buzz)
- [Leap years](/leap-years)
- [Employee report](/employee-report)
### Moyen
- [WordWrap](/word-wrap)
- [StringCalculator](/string-calculator)
- [UglyTrivia](/ugly-trivia)
- [Trip service](/trip-service-kata)
- [String calculator 2](/string-calculator-2)
- [TCR - Roman Numerals](/tcr-roman-numerals)
- [H2G2](/java-h2g2)
- [Puissance 4](/puissance-4)
- [CodingGame Mars Landing Party](https://www.youtube.com/watch?v=FeJa3UnmeHw)
- [Movie rental](/movie-rental)
- [Bowling Game](/bowling-game)
- [Tennis Refactoring kata](/tennis/refactoring)
### Énervé
- [GildedRose](/gilded-rose)
- [Game of life](/game-of-life)
- [Gilded rose without flow control](/gilded-rose-without-flow-control)
## TypeScript
### Moyen
- [Pagination Seven](/pagination-seven)
- [A Brief History of Date](/a-brief-history-of-date)
- [Trip service (TypeScript)](/trip-service-kata-typescript)
- [Roman calculator](/roman-calculator)
- [H2G2](/h2g2)
- [Mastermind](/mastermind)
## Front
### Moyen
- [Atomic Design I and II](https://gitlab.ippon.fr/arey/pattern-library)
# Code & coffee
## Java
### Facile
- [Factory patterns](/factory-patterns)
- [Exceptions](/exceptions)
### Moyen
- [Java streams](/java-streams)
### Énervé
- [Concurrence en Java](/java-concurrence)
# Discussions et présentations
- [C'est une bonne situation ça techlead ?](https://www.youtube.com/watch?v=9tOoXfOE12o)
- [GreenIT: simple coup de peinture ou réelle démarche écologique ?](https://www.youtube.com/watch?v=liTuZZTCpGc)
- [Une annonce pour recruter un crafter - Caroline, Chloé, Ianic et Colin](https://www.youtube.com/watch?v=E5AX6Ar1Fog)
- [Proxifier son localhost avec un nginx dockerisé avec Edouard CATTEZ](https://www.youtube.com/watch?v=qWMfRb3zK7k)
- [Dev pour des data scientists, un sale boulot](https://www.youtube.com/watch?v=QK3OJGAresE)
- [Back from GDCR avec Maxime, Séraphin, Anthony et Colin](https://www.youtube.com/watch?v=CHfUGdnSX6I)
- [Résilience des data pipelines](https://youtu.be/xvpUHAWN_fg)
- [1 an de craft chez Prismea](https://youtu.be/8x9_hpL0jj0)
- [Retour sur les 3 jours de conférences de DDD Europe](https://youtu.be/sDUuDpnLWXs)
- [Du craft dans mon code : de la valeur sur ma prod !](https://youtu.be/JvrNRbZhtHo)
- [Le craft au travers d'une jeune équipe de développement](https://youtu.be/ED0dyPHW3VU)
......@@ -1342,6 +1342,14 @@
"requires": {
"chevrotain": "6.5.0",
"lodash": "4.17.15"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
}
}
},
"js-yaml": {
......@@ -1635,9 +1643,9 @@
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"log-symbols": {
......@@ -2141,6 +2149,12 @@
"prettier": "1.18.2"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"prettier": {
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz",
......
......@@ -12,6 +12,7 @@ On code entierement quelques petites applications les lives, n'hésitez pas à n
- [Borestop](/borestop): Utilisation de la pyramide de tests pour apporter rapidement de la valeure
- [PadBowl](https://gitlab.com/cdamon/padbowl): "Utilisation" du DDD dans une application basée sur JHipster
- [NERP](https://gitlab.com/cdamon/nerp): Utilisation des méthodologies présentées sur la chaine pour construire totalement une application (en cours)
# Kata
......@@ -58,6 +59,7 @@ Un kata de code est un petit exercice pensé pour s'entrainer jusqu'à maitriser
- [Trip service (TypeScript)](/trip-service-kata-typescript)
- [Roman calculator](/roman-calculator)
- [H2G2](/h2g2)
- [Mastermind](/mastermind)
## Front
......@@ -81,8 +83,7 @@ Un kata de code est un petit exercice pensé pour s'entrainer jusqu'à maitriser
### Énervé
- [Concurrence en Java](/java-concurrence)
## TypeScript
- [Try monade](/try-monade)
# Discussions et présentations
......
package-try-monade:
variables:
PROJECT_FOLDER: "try-monade"
extends: .java
only:
refs:
- master
- merge_requests
changes:
- ".gitlab-common-ci.yml"
- "try-monade/**/*"
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<version>1.0.0</version>
<groupId>fr.ippon.kata</groupId>
<artifactId>java-parent</artifactId>
<relativePath>../java-parent</relativePath>
</parent>
<version>1.0.0-SNAPSHOT</version>
<artifactId>try-monade</artifactId>
<name>TryMonade</name>
<developers>
<developer>
<email>arey@ippon.fr</email>
<name>Anthony REY</name>
</developer>
<developer>
<email>cdamon@ippon.fr</email>
<name>Colin DAMON</name>
</developer>
</developers>
</project>
# Try monade
Création d'une monade pour gérer les exceptions pendant un code & coffee
- **Auteurs** : Anthony REY et Colin DAMON
- **Date** : 14/04/2021
- **Langage** : Java
- **Niveau** : Énervé
- **Replay** : TODO
package fr.ippon.craft;
public class ExecutionException extends RuntimeException {
public ExecutionException(Throwable e) {
super(e);
}
}
package fr.ippon.craft;
@FunctionalInterface
public interface Faillable<T> {
T execute() throws Throwable;
}
package fr.ippon.craft;
import java.util.Objects;
import java.util.function.Function;
public abstract class Try<T> {
public static <T> Try<T> of(Faillable<T> failable) {
try {
T result = failable.execute();
return new SuccessfulTry<>(result);
} catch (Throwable e) {
return new FailingTry<>(e);
}
}
public abstract <R> Try<R> map(Function<T, R> mapper);
public abstract <R> Try<R> flatMap(Function<T, Try<R>> failable);
public abstract T get();
public abstract T orElse(T recovery);
public abstract T orElseGet(Faillable<T> failing);
private static class SuccessfulTry<T> extends Try<T> {
private final T result;
private SuccessfulTry(T result) {
this.result = result;
}
@Override
public <R> Try<R> map(Function<T, R> mapper) {
Objects.requireNonNull(mapper);
return new SuccessfulTry<R>(mapper.apply(result));
}
@Override
public <R> Try<R> flatMap(Function<T, Try<R>> failable) {
return failable.apply(result);
}
@Override
public T get() {
return result;
}
@Override
public T orElse(T recovery) {
return result;
}
@Override
public T orElseGet(Faillable<T> failing) {
return result;
}
}
private static class FailingTry<T> extends Try<T> {
private final Throwable e;
private FailingTry(Throwable e) {
this.e = e;
}
@Override
public <R> Try<R> map(Function<T, R> mapper) {
return new FailingTry<>(e);
}
@Override
public <R> Try<R> flatMap(Function<T, Try<R>> failable) {
return new FailingTry<>(e);
}
@Override
public T get() {
throw new ExecutionException(e);
}
@Override
public T orElse(T recovery) {
return recovery;
}
@Override
public T orElseGet(Faillable<T> failing) {
return Try.of(failing).get();
}
}
}
package fr.ippon.craft;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
class TryTest {
@Test
void shouldCreateSuccessTry() {
assertThat(Try.of(() -> "Yeah").get()).isEqualTo("Yeah");
}
@Test
void shouldCreateFaillingTry() {
assertThatThrownBy(() -> Try.of(failing()).get())
.isExactlyInstanceOf(ExecutionException.class)
.hasCauseExactlyInstanceOf(RuntimeException.class);
}
@Test
void shouldGetGoodResultForSuccess() {
assertThat(Try.of(() -> "Yeah").orElse("Hey")).isEqualTo("Yeah");
}
@Test
void shouldGetAlternativeResultWhenFailing() {
assertThat(Try.of(failing()).orElse("Hey")).isEqualTo("Hey");
}
@Test
void shouldMapSuccessfulResult() {
assertThat(Try.of(sucess()).map(Result::new).get()).isEqualTo(new Result("Hello"));
}
@Test
void shouldNotMapFailingResult() {
Try<Result> tryable = Try.of(failing()).map(Result::new);
assertThatThrownBy(tryable::get).isExactlyInstanceOf(ExecutionException.class).hasCauseExactlyInstanceOf(RuntimeException.class);
}
@Test
void shouldFlatMapSuccessfulTry() {
assertThat(Try.of(sucess()).flatMap(value -> Try.of(() -> value + " You")).get()).isEqualTo("Hello You");
}
@Test
void shouldFlatMapOnFailingTry() {
Try<String> failing = Try.of(failing()).flatMap(value -> Try.of(() -> value + " You"));
assertThatThrownBy(failing::get).isExactlyInstanceOf(ExecutionException.class).hasCauseExactlyInstanceOf(RuntimeException.class);
}
@Test
void shouldFlatMapWithFailingTry() {
assertThatThrownBy(Try.of(sucess()).flatMap(value -> Try.of(failing()))::get)
.isExactlyInstanceOf(ExecutionException.class)
.hasCauseExactlyInstanceOf(RuntimeException.class);
}
@Test
void shouldNotGetorElseForSuccessfulTry() {
assertThat(Try.of(sucess()).orElseGet(() -> "Fallback")).isEqualTo("Hello");
}
@Test
void shouldNotGetFaillingOrElseGet() {
assertThat(Try.of(sucess()).orElseGet(failing())).isEqualTo("Hello");
}
@Test
void shouldGetOrElseGetOnFaillingTry() {
assertThat(Try.of(failing()).orElseGet(sucess())).isEqualTo("Hello");
}
@Test
void shouldFailOrElseGetOnFaillingTry() {
assertThatThrownBy(() -> Try.of(failing()).orElseGet(failing()))
.isExactlyInstanceOf(ExecutionException.class)
.hasCauseExactlyInstanceOf(RuntimeException.class);
}
private Faillable<String> sucess() {
return () -> "Hello";
}
private Faillable<String> failing() {
return () -> {
throw new RuntimeException();
};
}
private static record Result(String value) {}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment