Skip to content

Commit

Permalink
Paneer Tikka Masala - A Java CompletableFuture Cooking Recipe
Browse files Browse the repository at this point in the history
  • Loading branch information
c-guntur committed Jan 5, 2021
1 parent 10c5a6a commit d2235e2
Show file tree
Hide file tree
Showing 30 changed files with 2,956 additions and 0 deletions.
Binary file added IDE/PTM.zip
Binary file not shown.
9 changes: 9 additions & 0 deletions IDE/runConfigurations/PaneerTikkaMasala.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="PaneerTikkaMasala" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="none.cgutils.recipe.paneer.tikka.PaneerTikkaMasala" />
<module name="paneer-tikka-masala" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
9 changes: 9 additions & 0 deletions IDE/runConfigurations/SolutionPaneerTikkaMasala.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="SolutionPaneerTikkaMasala" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="none.cgutils.recipe.paneer.tikka.SolutionPaneerTikkaMasala" />
<module name="paneer-tikka-masala" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
132 changes: 132 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
= Java CompletableFuture : A Cooking Recipe Kata
:toc:

image::https://github.com/c-guntur/paneer-tikka-masala/workflows/build/badge.svg?branch=main[link=https://github.com/c-guntur/paneer-tikka-masala/actions?query=workflow%3A%22build%22,title="build"]


image::assets/images/DukePaneerTikkaMasala.png[Duke with Paneer Tikka Masala,537,405]


`java.util.concurrent.CompletableFuture` is a versatile utility in Java (since Java 8). It provides a means of task execution, both synchronous and asynchronous.

A CompletableFuture implements `java.util.concurrent.Future` (available since Java 5) and `java.util.concurrent.CompletionStage` (available since Java 8) and adds additional methods for operating on tasks.

Some additional documentation about the three in this kata:

* link:assets/docs/Future.adoc[Future]
* link:assets/docs/CompletionStage.adoc[CompletionStage]
* link:assets/docs/CompletableFuture.adoc[CompletableFuture]
== What is a Code-Kata

A code-kata is a coding exercise that builds muscle memory by a practice of programming to arrive
at a known solution.

=== How does one go about with this code kata?

The essence of the exercise (presentation material and code kata) is to demonstrate the
usage patterns for `CompletableFuture`.

This set of code katas rely on fixing broken code. There may be multiple ways to solve the broken code, the
intent is to learn and experiment. There is a driving _main class_ and there are _recipe parts_, which need to be fixed.

The project contains several java classes that fail to cook our recipe. A recipe mindmap to prepare Paneer Tikka Masala is included below.

image:assets/images/recipe.png[Recipe, 400]

==== Here are simple steps to use this kata

. Run the main class link:src/kata/java/none/cgutils/recipe/paneer/tikka/PaneerTikkaMasala.java[PaneerTikkaMasala].
. None of the cooking recipe parts will print out on your console.
. Fix the broken/empty sections of code using the TODO and HINT comments.
. Repeat above steps until all recipe parts are printed.
. Check the solutions to see if there are other ways to solve.
(Remember, the solution may be less performant than yours)
. Rinse and repeat (delete and checkout again, then back to Step 1) to build muscle memory.

==== Order of solving
Start in the following oder to fix the broken code or add code where empty. Follow the TODOs and HINTs. Your IDE should list out all TODOs.

. link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part1CheckIngredients.java[Part1CheckIngredients] - Checks for the ingredients for the recipe.
. link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part2aMakePaneerTikka.java[Part2aMakePaneerTikka] - How to make the Paneer Tikka (cottage cheese roast).
. link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part2bMakeMasala.java[Part2bMakeMasala] - How to make the Masala (pureed/spiced gravy).
. link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part3Cooking.java[Part3Cooking] - How to cook the Paneer Tikka and the Masala, then garnish.
. link:src/kata/java/none/cgutils/recipe/paneer/tikka/PaneerTikkaMasala.java[PaneerTikkaMasala] - Plays the role of a chef and orchestrates the entire cooking.



****
*Mission*
Your mission, should you choose to accept it, will be to fix the recipe.
This message will self-destruct in* *NaN* minutes
****

=== Requirements
How to prepare for coding along

This kata is developed as a Java maven project. Ensure that you have:

1. Apache Maven 3.6.x or above. _Tested with Apache Maven 3.6.3_.
Link: https://maven.apache.org/download.cgi

1. JDK 11 or above. _Tested with OpenJDK 15_.
Link: http://jdk.java.net/15/

1. Your favorite Java IDE. _IntelliJ IDEA Ultimate was used to develop this kata_.

== Project Structure
----
|____IDE <----- Contains Run Configurations and Live Templates for IntelliJ
|____pom.xml <----- The POM for running maven commands
|____README.adoc <----- This file
|____assets <----- Images and docs linked above
|____src
| |____main
| | |____resources
| | |____java
| | | |____none
| | | | |____cgutils
| | | | | |____recipe
| | | | | | |____paneer
| | | | | | | |____tikka <----- Common classes shared by Kata and Solution portions
| |____kata
| | |____java
| | | |____none
| | | | |____cgutils
| | | | | |____recipe
| | | | | | |____paneer
| | | | | | | |____tikka <----- The broken recipe code, that needs to be fixed
| |____solution
| | |____java
| | | |____none
| | | | |____cgutils
| | | | | |____recipe
| | | | | | |____paneer
| | | | | | | |____tikka <----- Solutions
| |____test
| | |____java
| | | |____none
| | | | |____cgutils
| | | | | |____recipe
| | | | | | |____paneer
| | | | | | | |____tikka <----- Some tests for utilities used in this project
----

=== Solutions

.Solutions for the test
|===
|Kata | Solution
|link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part1CheckIngredients.java[Part1CheckIngredients]|link:src/solution/java/none/cgutils/recipe/paneer/tikka/parts/SolutionPart1CheckIngredients.java[SolutionPart1CheckIngredients]
|link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part2aMakePaneerTikka.java[Part2aMakePaneerTikka]|link:src/solution/java/none/cgutils/recipe/paneer/tikka/parts/SolutionPart2aMakePaneerTikka.java[SolutionPart2aMakePaneerTikka]
|link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part2bMakeMasala.java[Part2bMakeMasala] |link:src/solution/java/none/cgutils/recipe/paneer/tikka/parts/SolutionPart2bMakeMasala.java[SolutionPart2bMakeMasala]
|link:src/kata/java/none/cgutils/recipe/paneer/tikka/parts/Part3Cooking.java[Part3Cooking] |link:src/solution/java/none/cgutils/recipe/paneer/tikka/parts/SolutionPart3Cooking.java[SolutionPart3Cooking]
|link:src/kata/java/none/cgutils/recipe/paneer/tikka/PaneerTikkaMasala.java[PaneerTikkaMasala] |link:src/solution/java/none/cgutils/recipe/paneer/tikka/SolutionPaneerTikkaMasala.java[SolutionPaneerTikkaMasala]
|===


== Take Away

The key take-away from this kata is a solid understanding of the Java CompletableFuture API.
91 changes: 91 additions & 0 deletions assets/docs/CompletableFuture.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
= CompletableFuture
:toc:

== What is a CompletableFuture

Introduced in Java 8 (2014).

`CompletableFuture` is a complete implementation of *both* `Future` and `CompletionStage`.

CompletableFuture provides static methods as means to execute the tasks.

CompletableFuture allows for chaining and combining outcomes from multiple other CompletableFutures.

== Classifications

.Operations return type
[width="99%", options="header"]
|===
|Pattern in method name |Description

|`*run/Run*`|Perform a task without a return value, using a Runnable.
|`*supply/Supply*`|Perform a task that returns a value, using a Supplier.
|===

=== Synchronicity

Synchronicity is either Sync or Async

.Synchronicity
[width="99%", options="header"]
|===
|Pattern in method name |Description

|*<nothing>*| *_synchronous_*, performed by the thread running the CompletableFuture.
|`*Async*`| *_asynchronous_*, performed by default by the ForkJoinPool.commonPool unless an executor is provided.
|===

=== Results

There are two methods to retrieve the results.

Both *_wait for the CompletableFuture to complete_*, then return the result if successful.

Unsuccessful outcomes are due to cancellation, exceptional outcomes and interruptions.

.Results
[width="99%", options="header"]
|===
|Method name |Description

|`*get*`|Return the result. Throws *_checked exceptions_* when unsuccessful.
|`*join*`|Return the result. Throws *_unchecked runtime exceptions_* when unsuccessful.
|===

=== Multiple CompletableFutures

.Chaining and Combining
[width="99%", options="header"]
|===
|Pattern in method name |Description

2+| Chaining
|`*thenCompose**`| Chain two CompletableFuture, the second executed *_after_* the first using the result of the first as a value in a Function, *_returning a CompletableFuture_*.
|`*thenCombine**`| Chain two CompletableFuture, *_when both are completed_* using the result of both as values in a BiFunction, *_returning a CompletableFuture_*.
2+| Combining All
|`*thenAcceptBoth**`| Chain two CompletableFuture, *_when both are completed_* using the result of both as values in a BiConsumer, *_returning a value_*.
|`*runAfterBoth**`| Chain two CompletableFuture, *_when both are completed_* run a Runnable, *_returning a CompletableFuture<Void>_*.
|`*allOf*`| Await the completion of *_all of_* a list of CompletableFuture instances, *_returning a CompletableFuture<Void>_*.
2+| Combining Either
|`*applyToEither**`| Accept the completion of the current or other CompletableFuture using the value in a Function, *_returning a CompletableFuture_*.
|`*acceptEither**`| Accept the completion of the current or other CompletableFuture using the value in a Consumer, *_returning a CompletableFuture_*.
|`*runAfterEither**`| Accept the completion of the current or other CompletableFuture, then run a Runnable, *_returning a CompletableFuture<Void>_*.
|`*anyOf*`| Await the completion of *_any one of_* a list of CompletableFuture instances, *_returning a CompletableFuture<Object>_*.
|===

== Understanding Pipelines in CompletableFuture

CompletionFuture has Stages.

Each Stage may produce an output or signal when completed successfully.
Any stage can fail, leading to an exception. The exception can be handled.
A handling of an exception may cause the pipeline to be repaired or may be fatal enough to fail.


```
/----S--o--S--o--S--------------S--o--S--o----SUCCESS
/ \ /
CompletableFuture | |
\ \ /
\-------------------E--h--E--h--E--h----------FAILURE
```
73 changes: 73 additions & 0 deletions assets/docs/CompletionStage.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
= CompletionStage
:toc:

== What is CompletionStage

Introduced in Java 8 (2014).

CompletionState<T> interface represents an asynchronous or synchronous computation task.

This task performs an action or computes a value when another CompletionStage completes.

There are a few classifications that are identifiable via patterns in the method's name.

== Classifications

=== Core methods

Types of computation determined by method name pattern

.Core Methods
[width="99%", options="header"]
|===
|Pattern in method name |Description

|`*apply/Apply*`|Function computation on result or value of the CompletionStage
|`*accept/Accept*`|Consumer computation on result or value of the CompletionStage
|`*run/Run*`|Runnable computation
|===

=== Action methods

Actions performed determined by method name pattern

.Action methods
[width="99%", options="header"]
|===
|Pattern in method name |Description

|`*Compose*`|Similar to apply, returns a new CompletionStage after the completion of the current one, thus allowing pipelines
|`*Combine*`|Combine results of two completion stages into a BiFunction and returns a new CompletionStage
|`*exceptionally*`|handle any exception via a Function that returns a CompletedStage, successful completion is returned as the value of CompletionStage
|`*whenComplete*`|handle either successful result or exception passed as a BiConsumer and returns a new CompletionStage
|`*handle*`|handle either successful result or exception passed as a BiFunction and returns a new CompletionStage
|===

=== Synchronicity

Synchronicity of the stage is either Sync or Async

.Synchronicity
[width="99%", options="header"]
|===
|Pattern in method name |Description

|*<nothing>*|synchronous
|`*Async*`|asynchronous
|===

=== Post Execution

Actions to perform post-execution

.Post Execution
[width="99%", options="header"]
|===
|Pattern in method name |Description

|`*then*`|a single stage
|`*Both*`|both of two stages
|`*Either*`|either of two stages
|===


25 changes: 25 additions & 0 deletions assets/docs/Future.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
= Future
:toc:

== What is a Future

Introduced in Java 5 (2004).

A Future is a placeholder for a result of a computation task that hasn't finished yet.

Once the task completes, the Future holds the result.

== Operations on a Future

The following operations can be performed on a Future:

.Future operations
[width="99%", options="header"]
|===
|Method name |Description

|`*cancel*` |Attempts to cancel execution of this task.
|`*get*`|Waits if necessary for the computation to complete, and then retrieves its result, with or without a timeout parameter.
|`*isCancelled*`|Check if the Future has been canceled, prior to normal completion.
|`*isDone*`|Check if the Future completed normally.
|===
Binary file added assets/images/DukePaneerTikkaMasala.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/recipe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d2235e2

Please sign in to comment.