Skip to content

LeakyAbstractions/result

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
lib
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Build Status Quality Gate Status Coverage Maven Central Latest Release Javadoc

Result Library for Java

If you seek advice... then this Java library is for you! Result objects have all the answers you need. Start by "asking the ball" a Yes or No question, then turn it over and let the answers magically appear. Results can be either positive ("Success") or negative ("Failure"). Great fun for software developers and adults alike. Colors and decorations may vary.

Result Library for Java

The purpose of this library is to provide a type-safe encapsulation of operation results that may have succeeded or failed, instead of throwing exceptions.

If you like Optional but feel that it sometimes falls too short, you'll love Result.

The best way to think of Result is as a super-powered version of Optional. The only difference is that whereas Optional may contain a successful value or express the absence of a value, Result contains either a successful value or a failure value that explains what went wrong.

Result objects have methods equivalent to those in Optional, plus a few more to handle failure values.
Optional Result
isPresent hasSuccess
isEmpty hasFailure
get getSuccess
getFailure
orElse orElse
orElseGet orElseMap
orElseThrow
stream streamSuccess
streamFailure
ifPresent ifSuccess
ifFailure
ifPresentOrElse ifSuccessOrElse
filter filter
recover
map mapSuccess
mapFailure
map
flatMap flatMapSuccess
or flatMapFailure
flatMap

Result Library in a Nutshell

Before Result, we would wrap exception-throwing foobar method invocation inside a try block so that errors can be handled inside a catch block.

public int getFoobarLength() {
    int length;
    try {
        final String result = foobar();
        this.commit(result);
        length = result.length();
    } catch(SomeException problem) {
        this.rollback(problem);
        length = -1;
    }
    return length;
}

This approach is lengthy, and that's not the only problem -- it's also slow. Conventional wisdom says that exceptional logic shouldn't be used for normal program flow. Result makes us deal with expected, non-exceptional error situations explicitly as a way of enforcing good programming practices.

Let's now look at how the above code could be refactored if method foobar returned a Result object instead of throwing an exception:

public int getFoobarLength() {
    final Result<String, SomeFailure> result = foobar();
    result.ifSuccessOrElse(this::commit, this::rollback);
    final Result<Integer, SomeFailure> resultLength = result.mapSuccess(String::length);
    return resultLength.orElse(-1);
}

In the above example, we use only four lines of code to replace the ten that worked in the first example. But we can make it even shorter by chaining methods in typical functional programming style:

public int getFoobarLength() {
    return foobar().ifSuccessOrElse(this::commit, this::rollback).mapSuccess(String::length).orElse(-1);
}

In fact, since we are using -1 here just to signal that the underlying operation failed, we'd be better off returning a Result object upstream:

public Result<Integer, SomeFailure> getFoobarLength() {
    return foobar().ifSuccessOrElse(this::commit, this::rollback).mapSuccess(String::length);
}

This allows others to easily compose operations on top of ours, just like we did with foobar.

Getting Started

Please read the Quick Guide to know how to add this library to your build and further info about Result features.

Releases

This library adheres to Pragmatic Versioning.

Artifacts are available in Maven Central.

Javadoc

Here you can find the full Result API documentation.

Looking for Support?

We'd love to help. Check out the support guidelines.

Contributions Welcome

If you'd like to contribute to this project, please start here.

Code of Conduct

This project is governed by the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.

Author

Copyright 2022 Guillermo Calvo

License

This library is licensed under the Apache License, Version 2.0 (the "License"); you may not use it except in compliance with the License.

You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and limitations under the License.

Permitted

  • Commercial Use: You may use this library and derivatives for commercial purposes.
  • Modification: You may modify this library.
  • Distribution: You may distribute this library.
  • Patent Use: This license provides an express grant of patent rights from contributors.
  • Private Use: You may use and modify this library without distributing it.

Required

  • License and Copyright Notice: If you distribute this library you must include a copy of the license and copyright notice.
  • State Changes: If you modify and distribute this library you must document changes made to this library.

Forbidden

  • Trademark use: This license does not grant any trademark rights.
  • Liability: The library author cannot be held liable for damages.
  • Warranty: This library is provided without any warranty.