0

Making software user-extendable

 1 year ago
source link: https://sellsitself.substack.com/p/making-software-user-extendable
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Making software user-extendable

Why I built a code editor directly into a major enterprise tool.

When I was a kid I loved using Tampermonkey/Greasemonkey to change how websites worked. To add my own little pieces of functionality like account-switchers.

Fast-forward many years, this feels fundamentally missing inside enterprise software.

Every large enterprise I’ve ever worked with has some missing feature/integration/button. What they need is to add 20 lines of custom business logic. But they can’t - so they have to find a 9 month workaround or build a fully custom tool. This is why so many roll-outs get abandoned.

Sure. You can add fields/objects to your CRM/Marketing Automation/Support tools. But this never fully captures the use-case.

Enterprises want to build mini-apps into their tools. They want to run logic, to fetch data, to display custom UI.

There’s a never-ending long-tail of customization needs.

“Extension frameworks” are a terrible escape-hatch

To try to solve for this, enterprise-ready tools tend to provide an extension framework to add your own functionality.

There’s no standardization. Here’s some examples from this untamed wildnerness:

  • Eloqua calls it the ‘app framework’ and it’s a complex dance of webhooks & responses.

  • Marketo calls it ‘self service flows’ and you write a swagger file to organize a completely different set of requests and callbacks.

  • Intercom and Hubspot let you sort of add UI by writing interfaces in their own custom syntax.

  • Salesforce Marketing Cloud and Marketo both have yet another fully custom language for scripting inside of emails

This is better than nothing. It means you can add custom functionality - but it’s going to take months. In reality it’s just a handful of professional system-integrators who ever try this path.

This is clearly not viable for end-users to build their own feature-requests.

This always made me long for the simplicity I had experienced using Greasemonkey/Tankermonkey to tinker with websites.

“Just give me a code editor!”

I was a consultant. I helped big corporates set up their Eloqua environments (Oracle’s Marketing Automation product). Eloqua is actually a great tool with a tonne of no-code options - but I still felt myself screaming “just give me a code-editor” on every single project.

So in 2018 I set out to make this happen.

Here were my goals:

  • A user could place a step on a campaign/program and click it to load a code-editor

  • The editor should know all the config of the instance

    • E.g. if I want the contact’s first name it’s contact.fields.FirstName not an API call

    • Similarly, if my instance has a custom object for webinars, the date of the first entry should be cdos.webinars[0].WebinarDate

    • BOTH the linter and auto-complete should know the available fields and types (including the ones which are custom to that instance)

    • Any common request should have syntax sugar - e.g. a common request in marketing automation is to track an activity. So this should be contact.trackActivity(“SMS Clicked”). This should also be type safe (the linter knows the valid types) and additional metadata such as the current campaign should just work

  • ALL the complexity of the extension frameworks should be hidden. The user should only see their 8 lines of business logic, even if there’s 100k lines of extra code hidden behind the surface

  • The complexity of retries should also be hidden. E.g. if there’s 10,000 contacts in a batch and only 9,900 complete - the system has to transparently handle retrying just those 100 with an exponentential backoff x times until a success or error is returned.

  • Same for scaling: if 1,000 instances are required to process this load - the user should never know

  • The system needs to be observable - I should be able to inspect the logs for a specific contact

  • NO complexity can leak to the user

  • The editor should feel native. E.g. open with a click and no login step (use the embedding tool to auto sign in)

To put it simply - if the user wants to add 12 lines of business logic. They should be able to do it in 1 click and 12 lines (and never think about ops or infrastructure).

https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa23c98f9-ed1b-4a24-92d2-a28e980f4d2c_3814x1982.png
One click loads this code editor. Notice the autocomplete & linter know all the valid fields for this instance (including custom ones)
https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28e5cf87-f8f0-444d-ba5b-463c0e3b4432_3814x1982.png
Testing is also a one-click thing. This shows the outcome & updates for each test contact

Modern tech makes this possible

Fairly recent developments made this possible to achieve.

Microsoft’s excellent Monaco project means you can essentially use VS Code as an embedded code editor.

Serverless projects like Lambda / Azure Functions / Google Cloud Functions make it possible to execute un-trusted code at scale in a sandboxed way.

Note: you absolutely cannot do this out of the box. You need to have an un-trusted zone and a trusted zone. Getting this right is one of the bigger challenges.

This diagram gives the gist of it. You create an un-trusted zone with no knowledge and only allow JSON in JSON out.

https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48d4bc50-85ef-44d3-9328-9d8e0873a91e_1496x460.png
Code runs in an isolated zone, and only communicates with the trusted app’s orchestration layer etc. via JSON

Breakpoint debugging

Being the number 1 power-user of my newly minted tool, I found myself really wanting breakpoint-debugging.

I didn’t need this. But it was the major thing that felt missing. And I am a massive nerd who couldn’t stop obsessing about how freakin’ cool this would be.

Building this turned out to be very, very difficult.

The reason: serverless runtimes like Lambda etc. are abstractions. The debug port your IDE connects to does not exist here. So I decided to implement a synthetic breakpoint-like feature with a custom compiler step.

Microsoft open source doesn’t get enough credit. They really made this project possible.

Not only does Monaco provide a crazy-good front-end and make the linting, autocompletion and type-safety possible - the breakpoint feature was made possible by another Microsoft project: the Typescript compiler.

When the user adds a breakpoint, a custom compile step runs which uses the Typescript’s internal representation (AST) to dynamically determine which variables are in scope, inject a context-aware observability agent, and send that data back to the user.

https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5131870e-8a99-4522-9950-47313ce67602_3814x1982.png
Breakpoints makes it very easy to inspect the payload. This makes custom integrations trivial

(Shoutout to my incredible colleague Kara who was absolutely pivotal bw.)

Time Travel Debugging

Technically what I have is a “non breaking breakpoint”. You get to inspect the state but it doesn’t stop execution.

An interesting (and to me insanely cool) side-effect of this is it allows time-travel debugging. Where you run the code with breakpoints, and then move backwards and forwards “in time” to see what the state was on each line.

See those back and forward arrows in the breakpoint section? You click to view state at a different line.

I honestly think more dev tools should explore this pattern.

If I had “9 startup lives” I’d modify our custom compiler to bring time-travel debugging to regular NodeJS/React/etc. projects.

Do you “just want a code editor”?

The work I’ve done here would port to allow simple user-customization of almost any enterprise software. If there’s demand, this is something I feel well placed to help with. I am really interested to hear from you if:

A) You’re on the product/engineering team of software you would like to make easily user-extendable

B) You’re a power-user of some software which you wish you could simply extend in a few lines of JavaScript/TypeScript (or just submit this article to your account-manager as a feature request)

C) You know an investor who might think user-extendable software is a big market

If this happens to be you, shoot me an email - [email protected] or book a call with me.

I don’t know what I want from this! This project is super nerdy & I think quite useful. I’d like to see it spread somehow beyond just Eloqua to simplify customization of other software.

I write about how to make software that sells itself. If you like my writing go ahead and subscribe:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK