https://github.com/melix/jdoctor
A Java library for designing good error messages
https://github.com/melix/jdoctor
Last synced: about 1 month ago
JSON representation
A Java library for designing good error messages
- Host: GitHub
- URL: https://github.com/melix/jdoctor
- Owner: melix
- License: apache-2.0
- Created: 2021-02-16T22:17:28.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2022-02-05T16:23:27.000Z (about 3 years ago)
- Last Synced: 2024-10-12T20:26:16.481Z (6 months ago)
- Language: Java
- Size: 135 KB
- Stars: 147
- Watchers: 6
- Forks: 8
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-java - JDoctor
README
# JDoctor, a Java library for good help messages
[](https://github.com/melix/jdoctor/actions/workflows/on-pr.yml)
[](https://lgtm.com/projects/g/melix/jdoctor/context:java)Designing good help messages is hard.
In Java, most often, developers just rely on throwing exceptions with a small text.
In best cases, the error message is sufficiently understandable, but there are lots of cases where it's inefficient.A good error message should describe:
- _how severe_ the problem is (can this be safely ignored?)
- _what_ problem was encountered. This is usually where developers stop. For example, "foo is null"
- _where_ the problem was encountered (in which context, e.g what file being compiled, what line number, ...)
- _why_ the problem happenedand eventually, a set of possible solutions to the problem.
Exceptions are not good at solving this, because an exception describes a failure in the program execution flow.
Stack traces are good for debugging, but it's rare that a user cares _where in your program_ a problem occured: most likely what they are interested in is _how they can solve the problem_.As a consequence, JDoctor provides a library to make it easier to design good error messages, by modeling them properly.
This library is currently in experimental stages, feedback is welcome.
### Example
This is an example of how you would construct a new problem descriptor using the convenience API:
```java
ProblemBuilder.newBuilder(TasteProblem.INVALID_INGREDIENT, Severity.HIGH, "Hawaiian pizza")
.withShortDescription("pineapple on pizza isn't allowed")
.because("the Italian cuisine should be respected")
.withLongDescription("Pineapple on pizza would put your relationship with folks you respect at risk.")
.documentedAt("https://www.bbc.co.uk/bitesize/articles/z2vftrd")
.addSolution(s -> s.withShortDescription("eat pineapple for desert"))
.addSolution(s -> s.withShortDescription("stop adding pineapple to pizza"))
```In practice, we encourage users to implement their own implementation of the `Problem` interface (for example extending the `BaseProblem` class) and come with topical builders which are specific to a category of problems.
For example:
```java
problemRecorder.recordNewProblem(problem ->
problem.forType(classWithAnnotationAttached)
.reportAs(ERROR)
.withId(ValidationProblemId.INVALID_USE_OF_CACHEABLE_TRANSFORM_ANNOTATION)
.withDescription(() -> String.format("Using %s here is incorrect", getAnnotationType().getSimpleName()))
.happensBecause(() -> String.format("This annotation only makes sense on %s types", TransformAction.class.getSimpleName()))
.documentedAt("validation_problems", "invalid_use_of_cacheable_transform_annotation")
.addPossibleSolution("Remove the annotation"))
```Then you might wonder how this should be rendered.
As always, the answer is "it depends".
`jdoctor` is agnostic with regards to rendering.
You will not render a message the same way if you have a CLI, a rich interface or an HTML report.
In short: rendering is the responsibility of the _consumer_ of the problems.For example, you might want to collect multiple problems, sort them by category, then render a short message and tell that the full explanation is available in a report.
However, for convenience, `jdoctor-utils` provides a simple, simplistic renderer.
Here's an example of output for the first example:```
The cooking police arrested you: pineapple on pizza isn't allowedWhere? : Hawaiian pizza
Why? : the Italian cuisine should be respected
Details: Pineapple on pizza would put your relationship with folks you respect at risk.
Possible solutions:
- eat pineapple for desert
- stop adding pineapple to pizzaYou can learn more about this problem at https://www.bbc.co.uk/bitesize/articles/z2vftrd
```### Modules
This project consists of the following modules published under the `me.champeau.jdoctor` group id:
- `jdoctor-core` is the main API mosly consisting of the model
- `jdoctor-utils` is a convenience module providing builders and renderers for problems and solutions
- `jdoctor-bom` is a platform used for aligning dependency versions### Using the library in your favorite project
To use `jdoctor` with Gradle:
```groovy
dependencies {
implementation("me.champeau.jdoctor:jdoctor-core:0.1.2")
}
```From Maven:
```xml
me.champeau.jdoctor
jdoctor-core
0.1
```
### Building
Run `./gradlew build`