Coding Without Coding
Tags: lowcode, productivity, opensource
Published: 2024-01-01 18:03:02

At [AINIRO.IO](https://ainiro.io) we have always thought of [Magic](https://github.com/polterguy/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.

{% embed https://www.youtube.com/watch?v=ITz1ASqsWoM %}

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"_.

![Decorating a Workflow Action](https://ainiro.io/assets/images/blog/decorating-workflow-actions.jpeg)

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"_.

![A decorated Action](https://ainiro.io/assets/images/blog/decorated-action.jpeg)

## 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.

![Decorating a Workflow Action](https://ainiro.io/assets/images/blog/installing-plugins.jpeg)

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](https://ainiro.io/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](https://github.com/polterguy/magic) if you wish. Everything is as usual 100% Open Sauce 😊