Swizec Teller - a geek with a hatswizec.com

Senior Mindset Book

Get promoted, earn a bigger salary, work for top companies

Senior Engineer Mindset cover
Learn more

    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,

    Senior Mindset Book

    Get promoted, earn a bigger salary, work for top companies

    Learn more

    Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.

    Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.

    Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help πŸ‘‰ swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

    Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers πŸ‘‰ ServerlessHandbook.dev

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

    Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

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

    Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

    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 ❀️

    Created by Swizec with ❀️