{{announcement.body}}
{{announcement.title}}

Magic Workflow

DZone 's Guide to

Magic Workflow

An alternative to Microsoft Workflow Foundation for .Net Core that gives you some of the properties from Workflows, without the bindings to .Net Framework and Windows

· Web Dev Zone ·
Free Resource

Few people are at this point in time willing to bet their money on .Net Framework, simply because .Net Core is obviously the future. This creates problems for us developers, since a lot of the tools we have grown used to, simply doesn't exist in .Net Core. One example of such a tool is Microsoft Workflow Foundation. According to what I've read, Microsoft is not willing to port Workflow Foundation to .Net Core either, so as you cross the bridge into ".Net Core land", you'll have to leave workflows behind.

What is Microsoft Workflow Foundation?

To find out how to replace Workflow Foundation, we must first ask ourselves what its primary feature is. As in, what makes MWF valuable for developers, and why have so many chosen to use it over the years?

Arguably the most important features of MWF is that it is dynamic in nature, and that it allows us to create and persist a dynamic "function invocation", that at some point in the future is executed, due to some trigger. Let me illustrate with an example from my day job.

  1. A client registers at my employers website and uploads relevant documents
  2. A back office worker looks through the documentation the client provided
  3. The client is either rejected or accepted as a client based upon his documentation
    1. The client's account is opened, and he is allowed to start trading
    2. Or, the client's account is closed, and he is told why

For us, the above is a workflow. Simply because after step 1 is finished, a "function invocation" is prepared and persisted, and as the client is rejected or accepted, that function invocation is invoked, and changes the state of the client, and possibly opens up a new trading account for the client. To understand how such a snippet piece of code might look like, let's illustrate it with the following pseudo code.

Plain Text
 




xxxxxxxxxx
1


1
if (clientWasAccepted())
2
  openTradingAccount()
3
  sendClientWelcomeEmail()
4
else
5
  deleteClient()
6
  sendClientGoodbyeEmail()


The problem the above pseudo code doesn't illustrate, is which client, and what his email address is. Hence, we tend to use Workflows to serialise data into our logic, which might logically end up looking like the following pseudo code instead.

Plain Text
 




xxxxxxxxxx
1


1
if (clientWasAccepted(57))
2
  openTradingAccount(57)
3
  sendClientWelcomeEmail("foo@bar.com")
4
else
5
  deleteClient(57)
6
  sendClientGoodbyeEmail("foo@bar.com")


At this point, we have a mixture of logic and data that we can serialise and persist, for instance into some database record, and then associate this database record with our client as he registers. And then as the back office worker either rejects or accepts the client, we can simply invoke our record as follows.

Plain Text
 




x


 
1
eval(getWorkflow(clientId))


Normally mixing data and logic is not a good thing, but when it comes to workflows, this is its primary feature, since it allows us to save the state of our current execution, for then to later "resume" this state, and continue executing where we left it previously. Without this feature, we'd end up with something like this, which obviously is ridiculous to say the least.

Plain Text
 




x


 
1
// After client registers
2
accepted = getAcceptanceFromBackOffice(clientId)
3
 
          
4
/*
5
 * NOTICE! It may take DAYS before back office is finished
6
 * reviewing the client's case, hance the above "method invocation"
7
 * might require 72 hours of "execution" before it's done.
8
 */
9
 
          
10
if (accepted)
11
  openTradingAccount(clientId)
12
  sendClientWelcomeEmail(clientEmail)
13
else
14
  deleteClient(clientId)
15
  sendClientGoodbyeEmail(clientId)


Read the comment in the above snippet, and realise how thinking about this as a simple linear process becomes ridiculous. The above makes workflows valuable for us where I currently work. And yes, you can create similar type of logic, using nothing but traditional C# - But the dynamic nature of workflows, allows us to persist a "function invocation", and arguably store the "instruction pointer" into a persisted layer, coupled with its relevant data, which again provides us with a lot of value. One example being versioning, allowing us to keep our code base's agile nature, and modify the underlaying C# code, without breaking backwards compatibility in regards to workflows previously persisted.

So, what are Magic Workflows?

Finally, I can explain Magic Workflows. I have written about Magic here previously. However, so far I have mostly told you about its CRUDification process, that allows you to automatically CRUDify your database, and create a .Net Core backend and an Angular frontend, by simply clicking a button. However, the reasons why this works (runtime), is because of a programming language called "Hyperlambda". Hyperlambda happens to allow you to dynamically create code, couple it with its data, and persist this into for instance a database record. Later when you need to execute this piece of code, you can simply load it up as text from your database, and execute it. Imagine the following to illustrate how the above use case could be solved using Hyperlambda. Notice, this code is working Hyperlambda code, and not pseudo code - Assuming you implement the "handleClient" slot of course as a C# class/method.

Plain Text
 




xxxxxxxxxx
1


 
1
handleClient
2
   id:57
3
   email:foo@bar.com


The above "handleClient" parts, is actually a reference to a C# method - While the "id" and "email" parts, becomes its parameters. Hence, we now have the capacity to serialise a "function invocation" into anything that can store some bytes of text, such as a database record, of NTEXT type for instance. For then to later invoke it using something as follows.

Plain Text
 




xxxxxxxxxx
1


 
1
eval(getWorkflowForClient(clientId))


The "clientId" above, might be for instance a Guid, for instance the client's primary key, etc. To understand how this is translated into a C# invocation, let's type it out.

C#
 




x


 
1
namespace YourAppNamespace
2
{
3
    [Slot(Name = "handleClient")]
4
    public class HandleClientWorkflow : ISlot
5
    {
6
        public void Signal(ISignaler signaler, Node input)
7
        {
8
            var clientId = input.Children.First(x => x.Name == "id").GetEx<int>();
9
            var email = input.Children.First(x => x.Name == "email").GetEx<string>();
10
 
          
11
            // Do stuff with your above clientId and email here ...
12
        }
13
    }
14
}


Now we can parametrise a function invocation, with its data, and later evaluate it as some condition is reached. Notice the relationship between Hyperlambda's "handleClient" and the "handleClient" Slot attribute in the above C# method. This allows us to persist a C# function invocation, as a piece of text, and later read this text, parse it during runtime, and execute it as a C# method invocation, coupled with its parameters - And yes, before you ask, this process is blistering fast. In fact, I have previously proven it to be in general terms faster than executing Python code.

Hence, we now have the most important feature from Microsoft Workflow Foundation, except (of course) it being a gazillion times faster, and a gazillion times more scalable than Workflows. However, it does not provide the graphic interface in Visual Studio, where you "drag and drop" pieces of logic around, to modify your workflows. But seriously, who needs a GUI anyways - We are coders after all, or ...?

And since Hyperlambda is a fully fledged programming language, it's also easy to break it up into several function invocations, such as the following illustrates.

Plain Text
 




x


1
enable-client-trading-account
2
   id:57
3
send-client-welcome-email
4
   email:foo@bar.com
5
 
          


This allows you to dynamically create code, that has a statically typed programming language underneath its hood, and hence results in a feature in your C# apps, traditionally impossible to achieve - Without using something resembling Microsoft Workflow Foundation. Hence, you "persist" a piece of code, with its arguments, for then to later "resume" its execution, allowing you to create transactional pieces of code, that could require weeks to execute, without going through the hassle of having to statically create these snippets of code as compiled snippets - Which arguably is (almost) impossible. Basically, it becomes a perfectly valid option to MWF, except it works on .Net Core. And its dynamic nature, allows you to modify your workflows, without breaking changes.

If this sounds interesting to you, drop me a note over at Magic's GitHub website, and I can help you getting started with Magic Workflows. Documentation is a bit sparse at the moment I admit. However, with some initial guidance from me, you'd probably get started with it within a day or two - Easily!

Have a nice day,

Thomas Hansen

Topics:
.net core, archiecture

Published at DZone with permission of Thomas Hansen . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}