Welcome to the second video of the section.
Future design pattern in the previous video we've worked with the barrier concurrency button.
In this video.
We're going to take a look at the future design pattern.
Well understand this description write unit tests and implement them.
The future design pattern also called Promise is a quick and easy way to achieve concurrent structures
for asynchronous programming.
We'll take advantage of first class functions and go to develop features in short will define each possible
behavior of an action for executing them in different go routines.
No dot J.S. uses this approach providing event driven programming by default.
The idea here is to achieve a foreign forget that handles all possible results in an action to understand
it better we can talk about a type that has embedded the behavior in case an execution goes well or
in case it fails.
And this diagram the main function launches a future within a new go routine.
It won't wait for anything nor will it receive any progress of the future.
It really fires and forgets it.
The interesting thing here is that we can launch a new future within a future and embed as many futures
as we want in the same go routine or new ones.
The idea is to take advantage of the result of one future to launch the next.
For example have a look at this diagram.
Here we have the same future.
In this case if the execute function returned the correct result the success function is executed and
only in this case we execute a new go routine with another future inside or even without a go routine.
This is a kind of lazy programming where a future could be calling itself indefinitely or just until
some roll is satisfied.
The idea is to define the behavior in advance and let the future resolve the possible solutions.
What are our objectives with the future pattern.
We can launch many new guy routines each with an action and its own handlers.
This enables us to delegate the action handler to a different go routine stack many asynchronous calls
between them and a synchronous call that calls another asynchronous call and its results.
We're going to develop a very simple example to try to understand how a feature works and this example
will have a method that returns a string or an error.
We want to execute it concurrently.
We've learned ways to do this already using the channel we can launch a new go routine and handle the
incoming result from the channel.
But in this case we'll have to handle the result string or error and we don't want this.
Instead will define what to do in case of success and what to do in case of error and farm forget the
go routine acceptance criteria.
We don't have functional requirements for this task.
Instead we'll have technical requirements for it that negate the function execution to a different guy
routine the function will return a String maybe or an error the handlers must already be defined before
executing the function.
The design must be reusable.
Now we'll start with unit tests.
So as we mentioned will these first class functions to achieve this behavior and we'll need three specific
types of function type success funk funk string these success funk function will be executed if everything
went well its string argument will be the result of the operation.
So this function will be called by our go routine type fail funk funk era.
The Fail funk function handles the opposite result.
That is when something goes wrong and as you can see it will turn an error type execute string funk
funk string comma error.
Finally the execute string funk function is a type that defines the operation we want to perform.
Maybe it'll return a String or an error.
Don't worry if this all seems confusing it will be clearer later.
So we create the future object.
We define a success behavior we define a fail behavior and we pass and execute string funk type to be
executed in the implementation file we'll need new type like before we'll create two files featured
or go on future unschooled test or go open the future don't go file and type this but also create two
tests in the test Dok Go file well defined functions by changing them as you would usually see in no
doc J.S. code like this is compact and not particularly difficult to file at the functions the featured
dot success function must be defined in the maybe string structure to accept a success func function
that will be executed if everything goes correctly and return the same pointed to the feature object
so we can keep chaining the failed function must also be defined in the maybe string structure and must
accept a failed func function to later return the pointer we return the pointer in both cases so we
can define the file and these excess or vice versa.
Finally we use the execute method to parse and execute string func type a function that accepts nothing
and returns a string or an error.
In this case we return a String and nil.
So we expect these excess func function will be executed and we log the result to the console in case
that fail function is executed the test is failed because the fail func function shouldn't be executed
for return nil error but we still lack something here we said that the function must be executed asynchronously
in a different go routine so we have to synchronize this test somehow that it doesn't finish too soon.
Again we can use a channel or a sink that weight group like I'm adding now
done we've seen weight groups before in the previous channel.
This weight group is configured to wait for one signal WG add 1 and success and fail methods will trigger
the done method of the weight group to allow execution to continue and finish testing.
That is why the White method is at the end.
Remember that each done method will subtract one from the weight group and we've added only one.
So our white method will only block until one done method is executed using what we know of making a
success result unit test.
It's easy to make a failed result unit test by swapping the T don't fail method call from the error
to success so that the test fails.
If a call to success is done let's make some changes in the failed result say this open future dot go
and add this code our test seems ready to execute it.
Let's try it out.
Open the terminal and type.
Go test hyphen V Well the test of failed.
Yes but not uncontrollable Why.
Why is this.
We don't have any implementation yet so no success or fail functions are being executed either.
Our White group is waiting forever for a call to the done method that will never arrive so it can't
continue and finish the test.
That's the meaning of all go routines or sleep deadlock in our specific example.
It would mean nobody is going to call done so we're dead.
How can we solve this.
Well an easy way would be with a timeout that calls he done method after waiting a while for completion
for this code.
It's safe to wait for one second because he's not doing any long running operations will declare a timeout
function within our test file that waits for a second name printed message sets the test has failed
and lets the wait group continue by calling its done method as go to our file and declare the timeout
method the final look of each sub test is similar to our previous example of the success result we had
timeout here
and comment the success part import time package.
Sign it let's see what happens when we execute our tests again.
Our test failed but in a controlled way look at the end of the fail lines.
Notice how the elapsed time is one second because it's been triggered by the timeout as we can see any
logging messages.
It's time to pass the implementation according to our tests.
The implementation must take a success func a failed func and then execute string func function in a
changed fashion within the may be string type and launch is the execute string func function asynchronously
to call success func or fail func functions according to the returned result of the execute string func
function the chain is implemented by storing the functions within the type and returning the pointer
to the type we're talking about our previously declared type methods of course let's open future dot
go and make the changes in the code we needed two fields to store the success funk and failed funk functions
which are named success funk and fail funk fields respectively.
This way calls to these success and fail methods simply store their incoming functions to our new fields.
There's simply setters that also return the pointer to the specific maybe string value these type methods
take a pointer to the maybe string structure so don't forget to put an asterisk on maybe string after
the func declaration execute take the execute string func method and executes asynchronously.
This seems quite simple with a go routine right.
So add execute function looks quite simple because it is simple.
We launched the go routine executes the F method and execute string func and takes its result may maybe
a string and maybe an error if an error is present.
We call the field fail func in our maybe string structure if no error is present we call these success
func field we use it go routine to delegate a function execution and error handling so I'll go routine
doesn't have to have it let's run unit tests now open the terminal and type the command test great look
at how the execution time is now nearly zero.
So our time outs have not been executed.
Actually they were executed but the tests already finished and their result was already stated.
What's more now we can use our maybe string type 2 asynchronously execute any type of function that
accepts nothing and returns a string or an error a function that accepts nothing seems a bit useless
right.
But we can use closures to introduce a context into this type of function.
Let's write to set context function that takes a string as an argument and returns and execute string
func method that returns the previous argument with the suffix closure so navigate to future not go
file and add the code right over here so we can write a new test that uses its closure.
Open the future dot go file and at the time that pile here the set context function returns and execute
string func method it can pass directly to the execute function we call the set context function with
an arbitrary text that we know will be returned that's uncommon.
This portion lets execute our tests again.
Now everything has to go well.
Open the terminal and run it again it gave us no K-2 closure test shows the behavior that we explained
before by taking a message Hello and appending it with something else.
Closure.
We can change the context of the text we want to return now scale this to an H TTP get call a call to
a database or anything you can imagine it will just need to end by returning a string or an error.
Remember however that everything within the set context function but outside of the anonymous function
that we're returning is not concurrent and will be executed asynchronously before calling execute.
So he must try to put as much logic as possible within the anonymous function in this video we successfully
worked with function design pattern.
Amazing.
In the next video we'll look into the pipeline design pattern.