{"id":16559524,"url":"https://github.com/melix/jdoctor","last_synced_at":"2025-03-16T20:30:34.327Z","repository":{"id":40527575,"uuid":"339546345","full_name":"melix/jdoctor","owner":"melix","description":"A Java library for designing good error messages","archived":false,"fork":false,"pushed_at":"2022-02-05T16:23:27.000Z","size":138,"stargazers_count":147,"open_issues_count":0,"forks_count":8,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-12T20:26:16.481Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/melix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-16T22:17:28.000Z","updated_at":"2024-09-29T14:15:56.000Z","dependencies_parsed_at":"2022-06-29T14:32:29.281Z","dependency_job_id":null,"html_url":"https://github.com/melix/jdoctor","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melix%2Fjdoctor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melix%2Fjdoctor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melix%2Fjdoctor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melix%2Fjdoctor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/melix","download_url":"https://codeload.github.com/melix/jdoctor/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221667602,"owners_count":16860623,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T20:26:15.858Z","updated_at":"2024-10-27T11:12:46.891Z","avatar_url":"https://github.com/melix.png","language":"Java","funding_links":[],"categories":["REST错误处理"],"sub_categories":[],"readme":"# JDoctor, a Java library for good help messages\n\n[![Build](https://github.com/melix/jdoctor/actions/workflows/on-pr.yml/badge.svg)](https://github.com/melix/jdoctor/actions/workflows/on-pr.yml)\n[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/melix/jdoctor.svg?logo=lgtm\u0026logoWidth=18)](https://lgtm.com/projects/g/melix/jdoctor/context:java)\n\nDesigning good help messages is hard. \nIn Java, most often, developers just rely on throwing exceptions with a small text.\nIn best cases, the error message is sufficiently understandable, but there are lots of cases where it's inefficient.\n\nA good error message should describe:\n\n- _how severe_ the problem is (can this be safely ignored?)\n- _what_ problem was encountered. This is usually where developers stop. For example, \"foo is null\"\n- _where_ the problem was encountered (in which context, e.g what file being compiled, what line number, ...)\n- _why_ the problem happened\n\nand eventually, a set of possible solutions to the problem.\n\nExceptions are not good at solving this, because an exception describes a failure in the program execution flow.\nStack 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_.\n\nAs a consequence, JDoctor provides a library to make it easier to design good error messages, by modeling them properly.\n\nThis library is currently in experimental stages, feedback is welcome.\n\n### Example\n\nThis is an example of how you would construct a new problem descriptor using the convenience API:\n\n```java\nProblemBuilder.newBuilder(TasteProblem.INVALID_INGREDIENT, Severity.HIGH, \"Hawaiian pizza\")\n    .withShortDescription(\"pineapple on pizza isn't allowed\")\n    .because(\"the Italian cuisine should be respected\")\n    .withLongDescription(\"Pineapple on pizza would put your relationship with folks you respect at risk.\")\n    .documentedAt(\"https://www.bbc.co.uk/bitesize/articles/z2vftrd\")\n    .addSolution(s -\u003e s.withShortDescription(\"eat pineapple for desert\"))\n    .addSolution(s -\u003e s.withShortDescription(\"stop adding pineapple to pizza\"))\n```\n\nIn 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.\n\nFor example:\n\n```java\nproblemRecorder.recordNewProblem(problem -\u003e\n    problem.forType(classWithAnnotationAttached)\n        .reportAs(ERROR)\n        .withId(ValidationProblemId.INVALID_USE_OF_CACHEABLE_TRANSFORM_ANNOTATION)\n        .withDescription(() -\u003e String.format(\"Using %s here is incorrect\", getAnnotationType().getSimpleName()))\n        .happensBecause(() -\u003e String.format(\"This annotation only makes sense on %s types\", TransformAction.class.getSimpleName()))\n        .documentedAt(\"validation_problems\", \"invalid_use_of_cacheable_transform_annotation\")\n        .addPossibleSolution(\"Remove the annotation\"))\n```\n\nThen you might wonder how this should be rendered.\nAs always, the answer is \"it depends\".\n`jdoctor` is agnostic with regards to rendering.\nYou will not render a message the same way if you have a CLI, a rich interface or an HTML report.\nIn short: rendering is the responsibility of the _consumer_ of the problems.\n\nFor 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.\n\nHowever, for convenience, `jdoctor-utils` provides a simple, simplistic renderer.\nHere's an example of output for the first example:\n\n```\nThe cooking police arrested you: pineapple on pizza isn't allowed\n\nWhere? : Hawaiian pizza\n\nWhy? : the Italian cuisine should be respected\n\nDetails: Pineapple on pizza would put your relationship with folks you respect at risk.\n\nPossible solutions:\n    - eat pineapple for desert\n    - stop adding pineapple to pizza\n\nYou can learn more about this problem at https://www.bbc.co.uk/bitesize/articles/z2vftrd\n```\n\n### Modules\n\nThis project consists of the following modules published under the `me.champeau.jdoctor` group id:\n\n- `jdoctor-core` is the main API mosly consisting of the model\n- `jdoctor-utils` is a convenience module providing builders and renderers for problems and solutions\n- `jdoctor-bom` is a platform used for aligning dependency versions\n\n### Using the library in your favorite project\n\nTo use `jdoctor` with Gradle:\n\n```groovy\ndependencies {\n    implementation(\"me.champeau.jdoctor:jdoctor-core:0.1.2\")\n}\n```\n\nFrom Maven:\n\n```xml\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eme.champeau.jdoctor\u003c/groupId\u003e\n        \u003cartifactId\u003ejdoctor-core\u003c/artifactId\u003e\n        \u003cversion\u003e0.1\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n### Building\n\nRun `./gradlew build`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelix%2Fjdoctor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmelix%2Fjdoctor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelix%2Fjdoctor/lists"}