From 2d59172da6fd9529799c91bb74cf6d65692279dc Mon Sep 17 00:00:00 2001 From: Jim Mochel Date: Thu, 13 Nov 2025 09:35:31 -0500 Subject: [PATCH] docs: update README.md to enhance onboarding and usage guidance - Revised the README structure to include a Quick Start section for easier onboarding. - Added detailed installation instructions for Maven and Gradle. - Expanded the Usage section with comprehensive examples demonstrating result creation, exception handling, and error recovery. - Introduced new sections on Core Concepts, Implementation Overview, and API Design Philosophy to clarify the operational result pattern. - Improved documentation for better clarity and consistency across all sections. --- README.md | 445 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 245 insertions(+), 200 deletions(-) diff --git a/README.md b/README.md index 8986ceb..625455b 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,41 @@ -# Endeavour +# Endeavour — Operational Result Pattern for Java Endeavour is a Java library that implements the operational result pattern, providing a robust and type-safe way to handle operations that can succeed or fail without relying on exceptions for control flow. ![Tactical Ferret](./tactical-ferret-logo.png) [^1] Tactical Ferret images created using Craiyon -## Current Status +## Quick Start (5 minutes) -✅ **Core Result Monad**: Fully implemented with comprehensive test coverage -✅ **Checked Exception Handling**: Enhanced with `CheckedConsumer` and `CheckedFunction` interfaces -✅ **Test Coverage**: 100% line coverage achieved across all core components -✅ **API Consistency**: Unified exception handling across all monadic operations -⚠️ **API Stability**: Still in development - breaking changes may occur +```bash +# Clone + build +git clone https://github.com/jmochel/endeavour.git +cd endeavour +mvn clean package -DskipTests + +# Sanity check (unit tests fast path) +mvn test -DskipITs +``` + +## Install + +### Maven +```xml + + org.saltations.endeavour + endeavour + 0.4.0-SNAPSHOT + +``` + +### Gradle (Kotlin DSL) +```kotlin +dependencies { + implementation("org.saltations.endeavour:endeavour:0.4.0-SNAPSHOT") +} +``` -## Quick Start +## Usage ```java // Create a successful result @@ -32,30 +54,182 @@ String message = success.reduce( ); ``` -## Basic Resources on the Operational Result Pattern +## Core Concepts & Modules -### What is the Operational Result Pattern? +- **JDK:** Java 21+ +- **Modules:** + - `endeavour` - Core library implementing the operational result pattern + - `endeavour-cli` - CLI application for testing and demonstration +- **Key Concepts:** + - **Result Monad**: Sealed interface `Result` with `Success` and `Failure` implementations + - **Exception Handling**: Wraps operations that may throw exceptions into Result types + - **Monadic Operations**: `map`, `flatMap`, `reduce`, `orElse` for composing operations + - **Type Safety**: Explicit error handling without exceptions for control flow -- [Operational Result Pattern](https://martinfowler.com/articles/replaceThrowWithNotification.html) -- [Operational Result Pattern – A simple guide] https://medium.com/@cummingsi1993/the-operation-result-pattern-a-simple-guide-fe10ff959080 -- [Result Pattern] https://medium.com/@wgyxxbf/result-pattern-a01729f42f8c +### Implementation Overview -### Language-specific articles +The operational result is represented in _Endeavour_ by the sealed interface `Result`. +This interface has two main implementations: `Success` and `Failure`. +Each implementation acts as a monad: it wraps a value that may or may not be present and provides methods to perform computations on that value in a safe manner. -- [Operational result pattern in Java] https://www.linkedin.com/pulse/operation-result-pattern-java-artyom-panfutov-t94ae/ -- https://belief-driven-design.com/functional-programming-with-java-exception-handling-e69997c11d3/ -- [Operational Result pattern in Kotlin] https://adambennett.dev/2020/05/the-result-monad/ -- [Operation Result in C#] https://www.forevolve.com/en/articles/2018/03/19/operation-result/ +#### Core Components -### Other Operational Result Pattern Repositories +**Result Monad Interface:** +* [Result.java](endeavour/src/main/java/org/saltations/endeavour/Result.java) - Main sealed interface defining monadic operations +* [Success.java](endeavour/src/main/java/org/saltations/endeavour/Success.java) - Sealed interface for successful outcomes +* [QuantSuccess.java](endeavour/src/main/java/org/saltations/endeavour/QuantSuccess.java) - Success with a payload value +* [QualSuccess.java](endeavour/src/main/java/org/saltations/endeavour/QualSuccess.java) - Success without a payload +* [Failure.java](endeavour/src/main/java/org/saltations/endeavour/Failure.java) - Failure implementation with detailed error information -- [Vavr](https://www.vavr.io/) -- [jOOL](https://github.com/jOOQ/jOOL) -- [Either](https://github.com/jbock-java/either) -- [Java Monads](https://github.com/enelson/java_monads) -- [Java functional adapter](https://github.com/armtuk/java-functional-adapter/tree/develop/src/main/java/com/plexq/functional) +**Factory and Utilities:** +* [Try.java](endeavour/src/main/java/org/saltations/endeavour/Try.java) - Factory methods for creating Results from operations that may throw exceptions +* [FailureDescription.java](endeavour/src/main/java/org/saltations/endeavour/FailureDescription.java) - Rich error information with templating support + +**Checked Exception Handling:** +* [CheckedConsumer.java](endeavour/src/main/java/org/saltations/endeavour/CheckedConsumer.java) - Consumer that can throw checked exceptions +* [CheckedFunction.java](endeavour/src/main/java/org/saltations/endeavour/CheckedFunction.java) - Function that can throw checked exceptions +* [CheckedSupplier.java](endeavour/src/main/java/org/saltations/endeavour/CheckedSupplier.java) - Supplier that can throw checked exceptions + +**Legacy Functional Interfaces (for compatibility):** +* [ExceptionalBiConsumer.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalBiConsumer.java) - BiConsumer that can throw exceptions +* [ExceptionalCallable.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalCallable.java) - Callable wrapper +* [ExceptionalConsumer.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalConsumer.java) - Consumer that can throw exceptions *(unused)* +* [ExceptionalFunction.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalFunction.java) - Function that can throw exceptions +* [ExceptionalPredicate.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalPredicate.java) - Predicate that can throw exceptions *(unused)* +* [ExceptionalRunnable.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalRunnable.java) - Runnable that can throw exceptions +* [ExceptionalSupplier.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalSupplier.java) - Supplier that can throw exceptions + +**Utility Classes:** +* [Functional.java](endeavour/src/main/java/org/saltations/endeavour/Functional.java) - Utility methods for casting Exceptional* interfaces to standard Java functional interfaces + +### API Design Philosophy + +The library provides two approaches for exception handling: + +1. **Checked Exception Interfaces** (`Checked*`) - Used by the core Result monad operations, allowing explicit exception handling +2. **Exceptional Interfaces** (`Exceptional*`) - Legacy interfaces that convert checked exceptions to unchecked exceptions + +The core Result monad operations (`map`, `flatMap`, `act`, `reduce`, `ifSuccess`, `ifFailure`) use `Checked*` interfaces to provide explicit exception handling, while maintaining backward compatibility through the `Functional` utility class. + +## Usage Examples + +### Basic Result Creation and Handling + +```java +// Create results using Try factory methods +Result success = Try.success("Hello World"); +Result failure = Try.failure("Operation failed"); + +// Check result type +if (success.isSuccess()) { + String value = success.get(); // Safe to call on success +} + +// Transform values safely +Result length = success.map(String::length); + +// Chain operations with flatMap +Result processed = success.flatMap(s -> + s.length() > 5 ? Try.success(s.toUpperCase()) : Try.failure("Too short") +); + +// Handle both cases with reduce +String message = success.reduce( + value -> "Success: " + value, + error -> "Failed: " + error.getDetail() +); +``` + +### Exception Handling + +```java +// Wrap operations that may throw exceptions +Result parseResult = Try.ofCallable(() -> + Integer.parseInt("123") +); + +// Handle checked exceptions explicitly +Result fileContent = Try.ofCallable(() -> + Files.readString(Paths.get("config.txt")) +).map(content -> content.trim()); + +// Perform side effects safely +parseResult.act(value -> System.out.println("Parsed: " + value)); +``` + +### Error Recovery + +```java +// Provide fallback values +Result config = Try.ofCallable(() -> + Files.readString(Paths.get("config.txt")) +).orElse(Try.success("default-config")); + +// Recover from failures +Result recovered = config.orElseGet(() -> + Try.ofCallable(() -> Files.readString(Paths.get("backup-config.txt"))) +); +``` + +## Development Workflow + +```bash +# Build +mvn clean compile + +# Test (unit) +mvn test + +# Format / Lint +# (No formatter configured - consider adding Spotless or similar) + +# Generate docs (Javadoc) +mvn javadoc:javadoc + +# Generate test coverage report +mvn test jacoco:report + +# Package the library +mvn package + +# Install to local repository +mvn install +``` + +## Compatibility & Versioning + +- Supported Java: JDK 21+ +- Semantic versioning unless noted; see **Changelog**. +- **Current Status:** + - ✅ **Core Result Monad**: Fully implemented with comprehensive test coverage + - ✅ **Checked Exception Handling**: Enhanced with `CheckedConsumer` and `CheckedFunction` interfaces + - ✅ **Test Coverage**: 100% line coverage achieved across all core components + - ✅ **API Consistency**: Unified exception handling across all monadic operations + - ⚠️ **API Stability**: Still in development - breaking changes may occur (version 0.4.0-SNAPSHOT) + +## Troubleshooting + +- **JDK version mismatch**: `maven-compiler-plugin` target is 21; install JDK 21+. +- **Proxy/cert issues downloading dependencies**: Set `MAVEN_OPTS` with proxy settings or SSL truststore configuration. +- **Test failures**: Ensure all dependencies are properly downloaded. Run `mvn clean install -U` to force update dependencies. + +## Links -## Rationale for the Operational Result Pattern +- API Docs: [Javadoc](https://jmochel.github.io/endeavour/) (if published) or generate locally with `mvn javadoc:javadoc` +- Changelog: [GitHub Releases](https://github.com/jmochel/endeavour/releases) +- Issues: [GitHub Issues](https://github.com/jmochel/endeavour/issues) +- Security: [GitHub Security Policy](https://github.com/jmochel/endeavour/security/policy) +- Contributing: See Contributing section below +- License: [License information to be added] + +--- + +## Additional Documentation + + + +### Rationale for the Operational Result Pattern The operational result pattern is a design pattern that is used to handle the results of operations that can either succeed or fail. It is particularly useful in functional programming, where exceptions are often avoided in favor of more explicit error handling. @@ -67,7 +241,6 @@ Using exceptions expensive for a couple of reasons: * The interruption of the control flow requires the release and manipulation of resources. * Checked and unchecked exceptions can end up being used for control flow, which mostly makes code harder to follow. - The operational result pattern is useful for a number of reasons: * Exceptions are expensive to throw and catch, and often have a negative impact on performance. Using the operational result pattern, you can avoid the overhead. * Exceptions can be difficult to reason about, especially when they are thrown deep in the call stack. By using the operational result pattern, you can make error handling more explicit and easier to understand @@ -77,18 +250,14 @@ In using the operational result pattern, we reserve exceptions for the truly exc cannot be handled by the normal flow of the program. for normal failures, such as validation, failures, etc., where we would expect things to fail, we return a result. And even in the cases of exceptional failure, we convert these into a result that preserves what is captured by the exception and allows it to be pushed upward. -> > We believe that exceptions should rarely be used as part of a program's normal flow: > exceptions should be reserved for unexpected events. Assume that an uncaught exception > will terminate your program and ask yourself, -> “Will this code still run if I remove all the exception handlers?” -> If the answer is “no”, then maybe exceptions are being used in nonexceptional circumstances. +> "Will this code still run if I remove all the exception handlers?" +> If the answer is "no", then maybe exceptions are being used in nonexceptional circumstances. > -- Dave Thomas and Andy Hunt -> --- Dave Thomas and Andy Hunt - -## Library Intentions +### Library Intentions Intention is to identify success or failure of an operation is a compact, and hopefully typesafe, representation that allows @@ -103,16 +272,15 @@ representation that allows * Transform a success in the called operation to a failure in our current operations * Be able to map errors from one type to another, perhaps converting a Throwable to something more useful to the presentation layer * Play well with code that uses java Exceptions as part of their flow control. -* Ideally, we’d be able to chain or combine a bunch of these operations together, and only handle the error state at the end of the computation +* Ideally, we'd be able to chain or combine a bunch of these operations together, and only handle the error state at the end of the computation A failure in any result that is not a success in the context of the method. -. If your not sure if something should be an exception or a failure you could ask yourself “Would the user understand what to do with this failure message?” -Typically a user doesn’t know what to do with exception messages, they are intended for a technical person to do a more in depth troubleshooting of +. If your not sure if something should be an exception or a failure you could ask yourself "Would the user understand what to do with this failure message?" +Typically a user doesn't know what to do with exception messages, they are intended for a technical person to do a more in depth troubleshooting of the problem. Business failure messages however, could be interpreted by a person and they should be able to act on them. - -# Success, Partial Success and Failure +### Success, Partial Success and Failure Most outcomes in apis can be broken up into Successes, Partial Successes and Failures @@ -123,28 +291,21 @@ Most outcomes in apis can be broken up into Successes, Partial Successes and Fai * Failure with a cause * Failure with a category/title and detail -Wrap and invoke functions that might blow up and catch their errors -Be able to map from one success type to another across data boundaries, ie from domain to presentation -Be able to map errors from one type to another, perhaps converting a Throwable to something more useful to the presentation layer -Handle both success and failure whenever we want -Ideally, we’d be able to chain or combine a bunch of these operations together, and only handle the error state at the end of the computation - - -# We want a model that is +### We want a model that is * Usable. - * Must be easy for developers to do the “right” thing in the face of error + * Must be easy for developers to do the "right" thing in the face of error * Should not impose excessive ceremony in order to write idiomatic code * Cognitively familiar to our target audience. * Performant. * The common case needs to be extremely fast. That means as close to zero overhead as possible for success paths. - * Any added costs for failure paths must be entirely “pay-for-play.” + * Any added costs for failure paths must be entirely "pay-for-play." * Diagnosable. * Debugging failures, either interactively or after-the-fact, needs to be productive and easy. * Composable. - * At the core, the error model is a programming language feature, sitting at the center of a developer’s expression of code. As such, it had to provide familiar orthogonality and composability with other features of the system. Integrating separately authored components had to be natural, reliable, and predictable. + * At the core, the error model is a programming language feature, sitting at the center of a developer's expression of code. As such, it had to provide familiar orthogonality and composability with other features of the system. Integrating separately authored components had to be natural, reliable, and predictable. -# Operation Result Pattern +### Operation Result Pattern Return a Union of an OK Result (success or failure without error) OR an error result. @@ -170,8 +331,6 @@ Should provide * flatMapSuccess - transforms a successful result into a different one * flatMapError - transforms a failed result into a different one. - - Creating Result Objects * Results.success @@ -183,9 +342,9 @@ Creating Result Objects Conditional Actions -* ifSuccess performs the given action with a successful result’s value. -* ifFailure performs the given action with a failed result’s value. -* ifSuccessOrElse performs either of the given actions with a result’s value. +* ifSuccess performs the given action with a successful result's value. +* ifFailure performs the given action with a failed result's value. +* ifSuccessOrElse performs either of the given actions with a result's value. Advantages @@ -197,7 +356,7 @@ Advantages Disadvantages * It is more complex to use than exceptions. - * Why? Because it must be “manually propagated up the call stack” (AKA returned by the callee and handled by the caller). + * Why? Because it must be "manually propagated up the call stack" (AKA returned by the callee and handled by the caller). Rule of Thumb : If you return Operating Result, never throw an exception. If someting is thrown. Return an Error esult with an exceptional. @@ -212,61 +371,14 @@ Some cases where you might NOT want to use operation results: * Functions that are operating on the UI * Code that does logging, or error reporting +### Recent Improvements -## Implementation of the Operational Result Pattern - -The operational result is represented in _Endeavour_ by the sealed interface `Result`. -This interface has two main implementations: `Success` and `Failure`. -Each implementation acts as a monad: it wraps a value that may or may not be present and provides methods to perform computations on -that value in a safe manner. - -### Core Components - -**Result Monad Interface:** -* [Result.java](endeavour/src/main/java/org/saltations/endeavour/Result.java) - Main sealed interface defining monadic operations -* [Success.java](endeavour/src/main/java/org/saltations/endeavour/Success.java) - Sealed interface for successful outcomes -* [QuantSuccess.java](endeavour/src/main/java/org/saltations/endeavour/QuantSuccess.java) - Success with a payload value -* [QualSuccess.java](endeavour/src/main/java/org/saltations/endeavour/QualSuccess.java) - Success without a payload -* [Failure.java](endeavour/src/main/java/org/saltations/endeavour/Failure.java) - Failure implementation with detailed error information - -**Factory and Utilities:** -* [Try.java](endeavour/src/main/java/org/saltations/endeavour/Try.java) - Factory methods for creating Results from operations that may throw exceptions -* [FailureDescription.java](endeavour/src/main/java/org/saltations/endeavour/FailureDescription.java) - Rich error information with templating support - -**Checked Exception Handling:** -* [CheckedConsumer.java](endeavour/src/main/java/org/saltations/endeavour/CheckedConsumer.java) - Consumer that can throw checked exceptions -* [CheckedFunction.java](endeavour/src/main/java/org/saltations/endeavour/CheckedFunction.java) - Function that can throw checked exceptions -* [CheckedSupplier.java](endeavour/src/main/java/org/saltations/endeavour/CheckedSupplier.java) - Supplier that can throw checked exceptions - -**Legacy Functional Interfaces (for compatibility):** -* [ExceptionalBiConsumer.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalBiConsumer.java) - BiConsumer that can throw exceptions -* [ExceptionalCallable.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalCallable.java) - Callable wrapper -* [ExceptionalConsumer.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalConsumer.java) - Consumer that can throw exceptions *(unused)* -* [ExceptionalFunction.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalFunction.java) - Function that can throw exceptions -* [ExceptionalPredicate.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalPredicate.java) - Predicate that can throw exceptions *(unused)* -* [ExceptionalRunnable.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalRunnable.java) - Runnable that can throw exceptions -* [ExceptionalSupplier.java](endeavour/src/main/java/org/saltations/endeavour/ExceptionalSupplier.java) - Supplier that can throw exceptions - -**Utility Classes:** -* [Functional.java](endeavour/src/main/java/org/saltations/endeavour/Functional.java) - Utility methods for casting Exceptional* interfaces to standard Java functional interfaces - -### API Design Philosophy - -The library provides two approaches for exception handling: - -1. **Checked Exception Interfaces** (`Checked*`) - Used by the core Result monad operations, allowing explicit exception handling -2. **Exceptional Interfaces** (`Exceptional*`) - Legacy interfaces that convert checked exceptions to unchecked exceptions - -The core Result monad operations (`map`, `flatMap`, `act`, `reduce`, `ifSuccess`, `ifFailure`) use `Checked*` interfaces to provide explicit exception handling, while maintaining backward compatibility through the `Functional` utility class. - -## Recent Improvements - -### Enhanced Exception Handling +#### Enhanced Exception Handling - **Unified API**: All monadic operations now use consistent `Checked*` interfaces for explicit exception handling - **Simplified `orElse`**: Changed from `orElse(CheckedSupplier>)` to `orElse(Result)` for cleaner usage - **Improved `act` Method**: Now operates directly on payload values for successes, with no-op behavior for failures -### Test Coverage Achievements +#### Test Coverage Achievements - **100% Line Coverage**: Comprehensive test suite covering all core components - **Exception Path Testing**: Complete coverage of exception handling scenarios including: - `InterruptedException` handling with proper thread interrupt flag restoration @@ -274,73 +386,13 @@ The core Result monad operations (`map`, `flatMap`, `act`, `reduce`, `ifSuccess` - Null parameter validation across all methods - **Edge Case Coverage**: Tests for boundary conditions and error scenarios -### Code Quality Improvements +#### Code Quality Improvements - **Null Safety**: Explicit null checks using `Objects.requireNonNull()` throughout - **Javadoc Updates**: Comprehensive documentation for all public APIs - **API Consistency**: Unified method signatures and behavior patterns - **Legacy Code Analysis**: Identified unused `ExceptionalConsumer` and `ExceptionalPredicate` interfaces -## Usage Examples - -### Basic Result Creation and Handling - -```java -// Create results using Try factory methods -Result success = Try.success("Hello World"); -Result failure = Try.failure("Operation failed"); - -// Check result type -if (success.isSuccess()) { - String value = success.get(); // Safe to call on success -} - -// Transform values safely -Result length = success.map(String::length); - -// Chain operations with flatMap -Result processed = success.flatMap(s -> - s.length() > 5 ? Try.success(s.toUpperCase()) : Try.failure("Too short") -); - -// Handle both cases with reduce -String message = success.reduce( - value -> "Success: " + value, - error -> "Failed: " + error.getDetail() -); -``` - -### Exception Handling - -```java -// Wrap operations that may throw exceptions -Result parseResult = Try.ofCallable(() -> - Integer.parseInt("123") -); - -// Handle checked exceptions explicitly -Result fileContent = Try.ofCallable(() -> - Files.readString(Paths.get("config.txt")) -).map(content -> content.trim()); - -// Perform side effects safely -parseResult.act(value -> System.out.println("Parsed: " + value)); -``` - -### Error Recovery - -```java -// Provide fallback values -Result config = Try.ofCallable(() -> - Files.readString(Paths.get("config.txt")) -).orElse(Try.success("default-config")); - -// Recover from failures -Result recovered = config.orElseGet(() -> - Try.ofCallable(() -> Files.readString(Paths.get("backup-config.txt"))) -); -``` - -## Monads +### Monads A Monad is a concept in functional programming that describes computations as a series of steps. It's a design pattern that allows you to structure your programs in a way that's easier to reason about. @@ -355,7 +407,7 @@ The `Result` type in Endeavour implements the Monad pattern with these key ch This provides a safe, composable way to handle operations that may fail without using exceptions for control flow. -## Dyad +### Dyad A Dyad is a term from the APL programming language, referring to a function that takes two arguments. In other words, it's a binary function. The term is used in functional programming to describe functions that operate on two inputs. @@ -375,7 +427,7 @@ method is then used to apply this function to the numbers 5 and 3, storing the r This is a basic example, but it illustrates the core idea of a Dyad: it's a function that operates on two inputs. -## Triad` +### Triad A Triad, similar to a Monad and Dyad, is a term from the APL programming language. It refers to a function that takes three arguments, making it a ternary function. This term is used in functional programming to describe functions that operate on three inputs. @@ -400,10 +452,11 @@ sum. The `apply` method is then used to apply this function to the numbers 5, 3, This is a basic example, but it illustrates the core idea of a Triad: it's a function that operates on three inputs. -## Tetrad +### Tetrad + -## Try +### Try The `Try` Monad is a concept in functional programming that encapsulates computations which may either result in a value or throw an exception. It's a design pattern that allows you to structure your programs in a way that's easier to reason about, especially when dealing with error handling. @@ -479,8 +532,7 @@ throws the exception that occurred during parsing. This is a basic example, but it demonstrates the core idea of a `Try` Monad: it's a way to encapsulate computations that may either result in a value or throw an exception, allowing for more robust error handling. - -## Either +### Either The `either` concept in Erlang is not a built-in feature of the language, but it's a common pattern used in functional programming languages. It's often used to handle computations that can result in two different types of values, typically representing success and failure cases. @@ -508,7 +560,7 @@ reason for the error is printed. This is a basic example, but it illustrates the core idea of the `either` pattern: it's a way to handle computations that can result in two different types of values, allowing for more robust error handling. -## Operational Result +### Operational Result The Operational Result pattern is a software design pattern often used in functional programming. It's a way to handle computations that can result in either a success or a failure, and it's particularly useful for error handling. This pattern is similar to the `Either` type in some functional programming languages, or the `Try` Monad in others. @@ -564,8 +616,7 @@ retrieve the error message. This is a basic example, but it demonstrates the core idea of the Operational Result pattern: it's a way to encapsulate the result of an operation, which can be either a success or a failure, allowing for more robust error handling. - -# Operation Outcomes +### Operation Outcomes The Endeavour library implements a simplified operational result pattern with two main outcome types: @@ -577,7 +628,7 @@ The Endeavour library implements a simplified operational result pattern with tw * Supports templated error messages * Preserves exception causes and stack traces -### Key Operations +#### Key Operations **Creation:** * `Try.success(value)` - Create a successful result with a value @@ -600,30 +651,28 @@ The Endeavour library implements a simplified operational result pattern with tw * `orElse(Result)` - Provide alternative result for failures * `orElseGet(CheckedSupplier>)` - Provide alternative via supplier for failures -## Building and Testing - -### Prerequisites -- Java 17 or higher -- Maven 3.6 or higher +### Basic Resources on the Operational Result Pattern -### Build Commands +#### What is the Operational Result Pattern? -```bash -# Clean and compile -mvn clean compile +- [Operational Result Pattern](https://martinfowler.com/articles/replaceThrowWithNotification.html) +- [Operational Result Pattern – A simple guide] https://medium.com/@cummingsi1993/the-operation-result-pattern-a-simple-guide-fe10ff959080 +- [Result Pattern] https://medium.com/@wgyxxbf/result-pattern-a01729f42f8c -# Run tests -mvn test +#### Language-specific articles -# Generate test coverage report -mvn test jacoco:report +- [Operational result pattern in Java] https://www.linkedin.com/pulse/operation-result-pattern-java-artyom-panfutov-t94ae/ +- https://belief-driven-design.com/functional-programming-with-java-exception-handling-e69997c11d3/ +- [Operational Result pattern in Kotlin] https://adambennett.dev/2020/05/the-result-monad/ +- [Operation Result in C#] https://www.forevolve.com/en/articles/2018/03/19/operation-result/ -# Package the library -mvn package +#### Other Operational Result Pattern Repositories -# Install to local repository -mvn install -``` +- [Vavr](https://www.vavr.io/) +- [jOOL](https://github.com/jOOQ/jOOL) +- [Either](https://github.com/jbock-java/either) +- [Java Monads](https://github.com/enelson/java_monads) +- [Java functional adapter](https://github.com/armtuk/java-functional-adapter/tree/develop/src/main/java/com/plexq/functional) ### Test Coverage @@ -645,7 +694,3 @@ This library is currently in active development. Key areas for contribution: - **Documentation**: Improve examples and usage guides - **Code Cleanup**: Remove unused `ExceptionalConsumer` and `ExceptionalPredicate` interfaces - **Additional Features**: Consider adding more monadic operations as needed - -## License - -[License information to be added]