Skip to content
Snippets Groups Projects
Commit e8a71202 authored by Colin DAMON's avatar Colin DAMON
Browse files

Code and coffee on exceptions

parent 4b71a73d
No related branches found
No related tags found
1 merge request!46Resolve "Code & coffee 3 code"
......@@ -17,3 +17,4 @@ include:
- local: "/tcr-roman-numerals/.gitlab-ci.yml"
- local: "/java-h2g2/.gitlab-ci.yml"
- local: "/factory-patterns/.gitlab-ci.yml"
- local: "/exceptions/.gitlab-ci.yml"
......@@ -40,3 +40,4 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
| [H2G2 en Java](/java-h2g2) | Kata | Moyenne |
| [Back from GDCR avec Maxime, Séraphin, Anthony et Colin](https://www.youtube.com/watch?v=CHfUGdnSX6I) | Discussion | |
| [Factory patterns](/factory-patterns) | Code&coffee | Facile |
| [Exceptions](/exceptions) | Code&coffee | Facile |
package-exceptions:
variables:
PROJECT_FOLDER: "exceptions"
extends: .java
only:
refs:
- master
- merge_requests
changes:
- ".gitlab-common-ci.yml"
- "exceptions/**/*"
<?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>exceptions</artifactId>
<name>Exceptions</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>
# Java exceptions
Code & coffee sur les exceptions (sujet choisi par le chat)
- **Auteurs** : Anthony REY et Colin DAMON
- **Date** : 16/12/2020
- **Langage** : Java
- **Niveau** : Débutant
- **Replay** : TODO
La prise en compte d'une exception doit être fait au plus proche de sa création. Il faut cependant être dans une couche permettant ce traitement : une exception peut donc traverser plusieurs "layers".
## Exceptions en Java
```plantuml
Throwable <|-- Exception
Throwable <|-- Error
Exception <|-- RuntimeException
```
## Liens dans le chat
- [JSR](https://fr.wikipedia.org/wiki/Java_Specification_Requests)
- [Exceptions internationalisées](https://blog.ippon.fr/2020/07/22/exceptions-internationalisees/)
- [Des objets, pas des data classes](https://blog.ippon.fr/2020/04/01/des-objets-pas-des-data-classes/)
- [Hexagonal architecture](https://alistair.cockburn.us/hexagonal-architecture/)
## Checked Exceptions
Les checked exceptions doivent être explicitement `throw` ou `catch` ce qui a tendance à "bloquer" les mises à jour d'API. Si cela semblait être une bonne idée pour obliger le traitement des erreurs, dans les faits elles ne sont pas mieux traitées.
Les checked exceptions sont les héritières directes de :
- Throwable
- Exception
- IOException
## Unchecked Exceptions
Les unchecked exceptions n'ont pas besoin d'être explicitement `throw` ou `catch`. Elles remontent directement jusqu'à l'endroit où elles sont prises en compte. En dernier recours elles sont traitées par la JVM qui va simplement les tracer. Cependant, beaucoup de FrameWorks (dont Spring) viennent avec un outillage facilitant le traitement de ces fin exceptionnelles.
Les unchecked exceptions sont les héritières directes de :
- Error
- RuntimeException
- IllegalArgumentException
## Créer votre stack d'exceptions
- Prendre le temp d'outiller les exceptions : cela en vaut la peine ;
- Faire des exceptions spécifiques aux erreurs ;
- Ajouter une information pour connaître le type d'erreur a remonter aux utilisateurs ;
- Wrapper les exceptions "exotiques" dans des exceptions custom.
package fr.ippon.exception;
public class Firstname {
public Firstname(String firstname) {
assertFirstname(firstname);
}
private void assertFirstname(String firstname) {
if (firstname == null) {
throw new MissingMandatoryValueException("firstname");
}
}
}
package fr.ippon.exception;
public class MissingMandatoryValueException extends RuntimeException {
public MissingMandatoryValueException(String field) {
super("Missing mandatory field: " + field);
}
}
package fr.ippon.exception;
import static org.assertj.core.api.Assertions.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import org.junit.jupiter.api.Test;
class ExceptionTest {
@Test
void shouldNotBuildFirstnameWithoutFirstname() {
assertThatThrownBy(() -> new Firstname(null))
.isExactlyInstanceOf(MissingMandatoryValueException.class)
.hasMessageContaining("firstname");
}
@Test
void shouldNotUpdateNullString() {
String pouet = null;
assertThatThrownBy(() -> pouet.substring(2)).isExactlyInstanceOf(NullPointerException.class);
}
@Test
void shouldNotReadUnknownFile() throws IOException {
assertThatThrownBy(() -> Files.readAllBytes(Paths.get("target/unknown"))).isExactlyInstanceOf(NoSuchFileException.class);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment