Home United States USA — software How to Streamline the Customer Experience with Monads in Kotlin

How to Streamline the Customer Experience with Monads in Kotlin

96
0
SHARE

Learn more about Monads and how they can be used to streamline the customer experience in Kotlin.
Join the DZone community and get the full member experience. At my company, we see a lot of SDKs and Swagger-generated clients that could throw exceptions at any time. This could be a fault in our logic, or it could be a fault with some 3rd party SDKs that have no rhyme or reason to how their exception handling works. But either way, when our customers want to fetch a Git commit history for a service, they do not want to be greeted with an error message. We’ve seen GitHub go down during a customer demo and 3rd party integrations throwing other unexpected exceptions. Overall, it was a very discouraging experience for our customers that we had no control over. Thus, `IntegrationValue ` was born. It is a type that can return any value but encapsulates all possible errors from 3rd party integrations. Now expected and unexpected exceptions and errors are (mostly) handled gracefully and we can surface clean error messages to our customers when we cannot retry or handle them. It’s a monad. (Just kidding, but will get back to this concept at the end.)
We do all of our backend development in Kotlin, and `IntegrationValue ` is first and foremost a way to work around the fact that Kotlin doesn’t support checked exceptions. But even more than exceptions, it can capture unexpected errors that don’t necessarily raise exceptions. For example, if I want to fetch a service’s Github repo details, but the workspace doesn’t have a GitHub integration enabled, what should it return? We could return null, but what does this mean for the caller of `GithubService. gitDetails(serviceId: Long): GitDetails?`? It could be that:
Basically, it could be one of a plethora of errors, and we don’t want to callously bundle them all together in our type system as a null. Rather we should be explicit on what exactly those error types could be. And so we created `IntegrationError`, which is a sealed class (like a compiler-friendly enum in Kotlin) of possible error types for all of our integrations.

Continue reading...