Skip to content
Swizec Teller - a geek with a hatswizec.com

How to think of your business logic as data

I'll never forget this lesson I learned from a friend in 6th or 7th grade.

We were building our own Windows clone. In Turbo Pascal, running in DOS, using a textual user interface because we didn't know how to do graphics.

If you're too young to know about textual user interfaces, they looked like this:

wikipedia commons c c5 Fdedit

It's got windows, buttons, a mouse cursor, and everything else you'd want in a modern user interface. Except graphics. It's all made with ASCII characters.

I used to know the ASCII table by heart by back then 🤓

Now, when I say we were building a new Windows, I don't mean working together on a single project. We didn't know how to do that. There was no Git or CVS or SVN back then. At least not that we knew of. The best we could do back then was to use diskettes to borrow each other's code.

Oh, we also didn't know about putting code in multiple files, so that was fun.

Anyway, the lesson he taught me about business logic being data came when we were both implementing our top row navigation. Like a menu, but for your whole system.

Oh yes, we built dropdown menus and everything. It's amazing what a 13 year old with infinite free time can build in a few months.

Avoid encoding business logic in the shape of your program

Let's say you have 6 items. File, Edit, Format, View, Window, and Help. That's what iA Writer has.

Now let's say you want to have a user action that goes through these items. My system used left and right arrow keys, my friend liked j and k, while MacOS relies on mouse alone.

You could build navigation like this:

onLeftKeyPress() {
if (currentMenu === "File") {
goTo("Help")
}else if (currentMenu === "Edit") {
goTo("File")
}else if (currentMenu === "Format") {
goTo("Edit")
}else if (currentMenu === "View") {
goTo("Format")
}else if (currentMenu === "Window") {
goTo("View")
}else if (currentMenu === "Help") {
goTo("Window")
}
}
onRightKeyPress() {
if (currentMenu === "File") {
goTo("Edit")
}else if (currentMenu === "Edit") {
goTo("Format")
}else if (currentMenu === "Format") {
goTo("View")
}else if (currentMenu === "View") {
goTo("Window")
}else if (currentMenu === "Window") {
goTo("Help")
}else if (currentMenu === "Help") {
goTo("File")
}
}

Nothing wrong with that. It's readable, gets the job done, everything's perfect. You congratulate yourself on an engineering problem well solved.

Then the PM comes in and says, "We've been running tests, and this sequence doesn't really work. Let's change the order.”

Uh-oh.

"Oh, and we want different apps to have different menus."

💩

Now you have to rewrite that whole logic for every app. Every time the PM decides to change the order. That's not fun at all!

So here's what you can do instead.

items = ["File", "Edit", "Format", "View", "Window", "Help"]
currentItem = 0
onLeftKeyPress() {
currentItem -= 1;
if (currentItem < 0) currentItem = items.length-1;
goTo(items[currentItem]);
}
onRightKeyPress() {
currentItem += 1;
if (currentItem >= items.length) currentItem = 0;
goTo(items[currentItem]);
}

Array of options, pointer to current selection, move pointer when user does something. Now we're talking!

With this approach, your system is flexible. You can change ordering, add elements, remove elements, even have different lists for different apps or users. It's great.

No difficult refactoring every time your PM changes their mind, just a data change.

But Swizec, nobody builds keyboard menus anymore!

That's true! People don't use keyboards as much as they used to. My whole thing above is pointless when a user can directly tap or click whatever they want.

But we still live in a world of sequental flows. More than ever, things are designed as user flows that go backwards or forwards. Onboarding flows are a good example.

Screen1: "Hai", Screen2: "Our app does X", Screen3: "Sign up", Screen4: "Gives us your phone number", Screen5: "Credit card maybe?", Screen6: "Do The Thing"

I simplify, but many apps have that flow.

You can build it as a hard-coded sequence of steps where each step must know who to call next. When your PM experiments, you're in for a world of heavy refactoring.

I had fun like that just this week. Not my fault even! Others on the team decided to build it the not-data way, and now we all suffer. I'm sure they will learn their lesson soon :)

But Swiz, my flow has branches and shit

So?

You're going to go into your super fancy logic and insert a bunch of if statements all the time?

if goNext and currentScreen is 'phone' and userSubscribed and…

Fuck.That.

Here's how you do it:

[() => userSubscribed ? <CreditCard /> : <DoTheThing />, ...]

Put functions in your previous/next logic! Core logic stays simple, end result for user is a complex tree of options.

That can get tricky too, I know. But you know what always works? Tree traversal. You can model your flow as a tree and build a simple walker that goes into different branches of the tree based on stuff. Perhaps based on functions in the tree nodes themselves.

😉

Save time. Make business logic your data. If a Turing machine can do it, so can your app.

Happy hacking.

Did you enjoy this article?

Published on August 11th, 2017 in Learning, Technical

Learned something new?
Want to become a high value JavaScript expert?

Here's how it works 👇

Leave your email and I'll send you an Interactive Modern JavaScript Cheatsheet 📖right away. After that you'll get thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over my 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

Start with an interactive cheatsheet 📖

Then get thoughtful letters 💌 on mindsets, tactics, and technical skills for your career.

"Man, love your simple writing! Yours is the only email I open from marketers and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"

~ Ashish Kumar

Join over 10,000 engineers just like you already improving their careers with my letters, workshops, courses, and talks. ✌️

Have a burning question that you think I can answer? I don't have all of the answers, but I have some! Hit me up on twitter or book a 30min ama for in-depth help.

Ready to Stop copy pasting D3 examples and create data visualizations of your own?  Learn how to build scalable dataviz components your whole team can understand with React for Data Visualization

Curious about Serverless and the modern backend? Check out Serverless Handbook, modern backend for the frontend engineer.

Ready to learn how it all fits together and build a modern webapp from scratch? Learn how to launch a webapp and make your first 💰 on the side with ServerlessReact.Dev

Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️