Welcome to

Evaluate Expression

Home / Java / Business-Flows

Business-Flows

A teammate of mine has written a concise framework for defining the business level flow of logic in an application. It lends itself well to readability and was inspired by Scott W’s Railway Oriented Programming. I would recommend watching his video first before taking on the framework.

@theangrydev has introduced business-flows to our team’s current projects. His Github name is quite misleading as he was very patient with us getting to grips with the syntax and style of this approach.

I have created the test project DogFoster to create valid examples, all code snippers in this post come from this project. Feel free to experiment with the framework using the DogFoster project, I will keep it up to date as business-flows is updated.

github-mark-120px-plus

DogFoster

Let’s have a look at an example method which will get called as part of a business flow:

Let’s break down what the method is doing, then we’ll move onto how it is used in the framework.

DogFosterSuccess, DogFosterRejection and Westie are all tiny-types. When using business-flows all return types need to be Objects, so tiny-typing is used often.

This method, checkSuitability, is in the middle of a business use-case for fostering a dog from a shelter. It takes in a DogFosterRequest and checks if the breed of the dog is a Westie. I’ve kept this example simple so there’s no data lookup to determine the age of the dogs.

In the event that the dog cannot be fostered, we flow into the sad path and return a DogFosterRejection, as this is the sad path types specified in the return type:

Otherwise we return DogFosterSuccess, the happy path type, where we can continue to call methods chained under ifHappy().

We can see the full flow below:

Our checkSuitability method is only invoked if payDonationFee (called using the peek method in the framework) returns a happy path. Once this becomes second nature it will be easy to understand the input parameters of these methods are the tiny-types of the track you are in. In the case of checkSuitability, its method parameter is the happy path type of what payDonationFee returns. The easiest way to get the types correct is to rely on your IDE to generate these method signatures.

The peek takes in a void return method and attempts to execute the function. In the event of an exceptional case peek brings us into the lowest of the three tracks, the technicalFailure. This is not a sad path scenario, think of it in our case as wrapping checkSuitability in a try/catch.

Here’s the peek method from the framework:

I wrote the payDonationFee method to by invoked by peek. In a real application, following the donation offer check, it would delegate to a payment process.

In the event that payDonationFee threw an exception, we would flow into the technical failure track.


If you’re not familiar with Java’s functional approach, I would recommend familiarising yourself with its features first. Whilst a deep understanding is not necessary to use business flows, knowledge of the basics will aid in picking up the framework and your project’s language level will have to be set to 8.

I wrote a blog post a few months ago on this very topic which explores refactoring code into this functional style, using the Project Euler math challenges as an example.


Once we have moved out of the happy path track, all methods chained after ifHappy() are not processed. Since, in this case we are not in the sad path, none of the methods chained off of ifSad() are executed either.

ifTechnicalFailure() is for us. Here we handle the exceptional cases where we’ve flowed into the third track. Note that any of the calls previously in the flow which can return technical failures are handled here.


If we enter the sad path track before our call to ifSad(), then appealFailedRequest and reportUnsuccessfulFosterAttempt are executed. The former is a retry which attempts to return us to the happy path, the latter reports the sad scenario.

Our second call to ifHappy() calls reportSuccess. It is placed at the end as it handles the expected happy path flow following checkSuitability returning the happy scenario, as well as cases where appealFailedRequest (in the sad path) were successful in their attempt to map back to happy path.

Here is appealFailedRequest, which has a very simplistic retry mechanic:

Note that appealFailedRequest also maps the sad path passed in, DogFosterRejection, to a new sad path, AppealFailed.

Here is AppealFailed:

First note that AppealFailed extends ValueType, an abstract class with gives us helper methods from Apache commons, to reduce the boiler plate code of writing tiny-types. Another contribution by @theangrydev.

The new sad path contains a reference to the previous sad path and exposes the reason messages from both so that no information is lost after the map.


Now that we have a good idea of our use case. Let’s have another look at the only public method in our DogShelter class.

It’s clear that business-flows lends itself exceptionally well towards describing the business functionality, all the while being close to the underlying code. This doesn’t replace documented acceptance testing and it was never intended to. Instead I feel it aids developers explain the process which has been defined to those less technical. It also lets developers joining a project see a broad view of a business process which can then dive into the details of.

If we were to explain to someone this simplified process of fostering a dog, by reading through our business flow, we would say something along the lines of:

“First you request the dog you wish to foster. You pay a donation fee and if that’s successful the dog is checked for suitability. If there was a problem you can appeal and the request gets re-evaluated. If there was an issue with the application the error is reported. Otherwise the successful request is processed.”


I hope you have found this introduction useful. If a deeper guide to the framework would be appreciated, let me know.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Thanks for reading!

>> <<