At AINIRO.IO we have always thought of Magic as a No-Code and Low-Code software development framework. For the last year we haven't emphasized that part as much, because we've been busy with AI and LLMs - But this year we will be focusing a lot on its Low-Code and No-Code abilities. The reason will become apparent as we proceed into 2024.
In the video below I am creating a full blown web API endpoint 100% declaratively without having to actually write any code myself. The idea is based upon workflows and actions, where a workflow is a collection of chained actions, and an action is the smallest atomic piece of code that does something useful.
To understand actions, realise that every single time you create a piece of code, an action is typically one function doing something useful. Examples of actions can be for instance:
- Create customer
- Add payment method to customer
- Create payment for customer using the specified payment method
When "chained", such actions can perform at least in theory anything you can do using traditional coding - Except of course, it lowers the bar by 99.99% in regards to complexity, making it 1,000 times easier to create software. The above list of actions for instance, is something I create in the following YouTube video in some 30 seconds in total.
Basically, once you've got access to meta data to the extent Hyperlambda provides you with, you could argue it's quite easy to build a 1,000,000 better "intellisense", and this idea basically sums up workflows and actions.
Hyperlambda workflows are for "lazy developers", and lazy developers are better developers because they create less code!
The benefits
To understand the benefits, let's go through a list of things you have to think about for our above use case if you were to manually code the solution. When you want to create a Stripe payment, you have to go through 4 HTTP REST methods Stripe exposes, and understand all the small nuances of these. Even though Stripe's documentation is quite good, simply understanding which methods to use, and reading their documentation, is easily several hours of work. A partial and incomplete list of tasks you'd have to do would probably include the following items.
- Study the Stripe HTTP API for some 2 to 5 hours before figuring out how to orchestrate your HTTP invocations together
- Create methods and classes for abstracting away the primary Stripe HTTP methods you need to consume
- Correctly create and decorate the JSON required by each endpoint
- Consume some HTTP client library for actually making the invocation
- Correctly handle error return values
The average senior software developer could probably achieve the above in some 5 to 10 hours of coding, but I do the whole job in 30 seconds in the above video. That's a performance boost of 900x, implying you'd be 90,000% as efficient using the above solution than you'd be using traditional coding. This is true even if you're a senior software developer too may I add.
In theory this makes a junior software developer 90,000% more efficient than a senior software developer, assuming the junior is using Low-Code and No-Code constructs such as the above, and the senior is not using such tools
For the record, I would know since I've done the above several times, and on average it easily takes me 5 hours to correctly create an HTTP API endpoint that invokes Stripe to create a payment. I have also seen senior software developers mess with Stripe for weeks before they got it right.
How it was created
The entirety of my code was 100% declaratively created, by decorating my code using textboxes, checkboxes, and select drop down lists. No code was manually created.
First I decided which input arguments my HTTP endpoint should take, and from there everything was literally "point and click". Below is an example of decorating an "action".
As you can see I'm given suggestions for what "arguments" to use for my actions as I incrementally add actions to my "workflow". Below you can see how the above resulted in actual code for me after I click "OK".
Coding Without Code
Believe it or not, but Magic and Hyperlambda is a No-Code framework that actually creates code. This has huge benefits compared to other frameworks relying upon XML and similar mechanisms. One primary feature being it's code! Implying you can still edit it as "normal code", and add to it as you see fit. No obscure and impossible to read XML files, stored in some esoteric persistence storage, just simple files, easily read and understood - As long as you're willing to make an effort understanding Hyperlambda of course.
The Stripe payment API endpoint I created in the above video for instance can be seen below.
/*
* This endpoints allows the user to perform a purchase
*
* It is very cool!!
*/
.arguments
name:string
email:string
card:string
exp_month:string
exp_year:string
cvs:string
amount:decimal
/*
* Creates a customer object in Stripe with the given [name], [email] and
* optionally [ip_address].
*
* If you supply an [ip_address] the country of origin for the IP address
* will be used as the default tax location for your customer in Stripe.
*
* Will use your Stripe API token found from your settings as it's interacting
* with the Stripe API.
*/
execute:magic.workflows.actions.execute
name:stripe-create-customer
filename:/modules/stripe/workflows/actions/stripe-create-customer.hl
arguments
name:x:@.arguments/*/name
email:x:@.arguments/*/email
// Creates a log entry.
execute:magic.workflows.actions.execute
name:log-create
filename:/misc/workflows/actions/misc/log-create.hl
arguments
type:info
message:Customer was successfully created
args
name:x:@.arguments/*/name
email:x:@.arguments/*/email
/*
* Creates a new Stripe payment method with the given [card_number], [card_exp_month],
* [card_exp_year] and [card_cvs] and attaches the payment metho to the specified
* [customer_id] object.
*
* Will use your Stripe API token found from your settings as it's interacting
* with the Stripe API.
*/
execute:magic.workflows.actions.execute
name:stripe-create-payment-method
filename:/modules/stripe/workflows/actions/stripe-create-payment-method.hl
arguments
card_number:x:@.arguments/*/card
card_exp_month:x:@.arguments/*/exp_month
card_exp_year:x:@.arguments/*/exp_year
card_cvs:x:@.arguments/*/cvs
customer_id:x:--/execute/=stripe-create-customer/*/customer_id
// Creates a log entry.
execute:magic.workflows.actions.execute
name:log-create
filename:/misc/workflows/actions/misc/log-create.hl
arguments
type:info
message:Payment method successfully created and asssociated with user
args
name:x:@.arguments/*/name
email:x:@.arguments/*/email
/*
* Creates a new Stripe payment for the given [customer_id] using the
* specified [payment_method], for the given [amount] in the given [currency].
*
* Will use your Stripe API token found from your settings as it's interacting
* with the Stripe API.
*/
execute:magic.workflows.actions.execute
name:stripe-create-payment
filename:/modules/stripe/workflows/actions/stripe-create-payment.hl
arguments
customer_id:x:--/execute/=stripe-create-customer/*/customer_id
payment_method:x:--/execute/=stripe-create-payment-method/*/payment_method_id
amount:x:@.arguments/*/amount
currency:USD
// Creates a log entry.
execute:magic.workflows.actions.execute
name:log-create
filename:/misc/workflows/actions/misc/log-create.hl
arguments
type:info
message:Payment successfully received, let's party!
args
name:x:@.arguments/*/name
email:x:@.arguments/*/email
// Returns the result of your last action.
return-nodes:x:@execute/*
102 lines of code might seem daunting, but there's only really one "construct" in the above code, which are "actions". An action is basically a "function" you might say, and once chained together, the output from one action can be used as input to another action. You can see one example of this in the "stripe-create-payment" action where it's referencing the return values from "stripe-create-customer" and "stripe-create-payment-method" as input to itself.
This provides you with "suggestions" for which arguments to use for your actions, making it much more intuitively understood than "raw code" gives you. The toolbox in Magic therefor becomes like your "class and method intellisense", while the dialog box seen as you chose one action becomes the "argument intellisense equivalent".
Since the position of the cursor is intelligent, and knows which actions, arguments, and returned values you've got in front of it, this allows Magic to intelligently "suggest" candidate variables to use as input for your next actions.
Plugin actions
All use cases are different, and obviously it would be impossible to create actions for every possible use case on earth. This is why we implemented modular actions, implying you can install plugins, and expect to sometimes find relevant actions in your plugins, that automatically populates the toolbox with additional actions you can use. In the video above for instance, I am installing our Stripe plugin, which gives me access to a handful of new actions related to Stripe.
This modularity allows you to create your own custom actions. To create a custom action, you can start with one of the example actions found in for instance "/misc/workflows/actions/", create a copy of its code, and create a new file in your "/etc/workflows/actions/" folder. Actions are retrieved from inside of these files recursively, allowing you to organise your actions any ways you see fit. Just remember to never create custom actions in your _"/misc/" folder, since this folder is automatically overwritten every time we update Magic's core.
- "/misc/workflows/actions/" are for system actions
- "/etc/workflows/actions/" are for your custom actions
Below is an example of one of the system actions giving you an idea of how they look like.
/*
* Loads the specified [file] and returns to caller as [content].
*/
.arguments
file
type:string
mandatory:bool:true
.icon:insert_drive_file
// Loads the specified file.
load-file:x:@.arguments/*/file
// Returning result of above invocation to caller.
yield
content:x:@load-file
The above action loads a text-based file, and returns its content as a string.
Reusable workflows
Workflows are also actions by themselves. By using the action named for instance "workflow-execute", you can treat a workflow as if it was an action, at which point the system will allow you to chose from one of your workflows serialised in your "/xxx/workflows/workflows/" folders, and automatically suggest workflows for you. Once you select a workflow, the system will automatically populate the arguments, allowing you to see which arguments your workflow can consume.
This allows you to create partial workflows that you can reuse across multiple projects, and/or other workflows, to such create reusable workflows.
Conclusion
As a general rule of thumb I would claim that Hyperlambda workflows and actions easily lowers the bar by 95% when it comes to creating software. In addition, it makes it easily 10x faster, and you're therefor 1,000% as productive. In theory Hyperlambda workflows can be used for everything, but obviously where you've got existing actions encapsulating complexity is where they'll truly shine.
Currently the thing is "super BETA", and should not be considered production ready. But this is something we will be working a lot on in the future, since it perfectly fits together with other initiatives we've got such as Custom GPTs for instance. Expect to see a lot of innovation down this alley in 2024 from us at AINIRO.IO - And please leave feedback about what you think, and/or add feature suggestions, or try out the beta release if you wish. Everything is as usual 100% Open Sauce π
Top comments (1)
I canβt even imagine all the possibilities with this, great work!