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

    Move your business logic into data

    The quickest way to simplify a complex function with lots of logic is to turn it into data. Here's what I mean.

    Take this screen for example. It shows a list of consent forms for a medical appointment.

    Consent screen
    Consent screen

    Nothing special. Checkmarks and links to PDFs. The submit button saves the list into a jsonb field in Postgres so we have an exact immutable record.

    But where does the list come from? πŸ€”

    Is it a backend or frontend concern?

    When I first built this 2 years ago, the list depended on:

    • how this appointment happens – virtual and in-person appointments have different forms
    • what kind of appointment is it – certain appointments have special forms, like acupuncture
    • the latest PDF links – the URLs will change when/if the forms are updated

    That sounded like a lot of contextual business logic to shove into the UI. Yes it knows all the data, but interpreting it felt like a step too far.

    Plus if the PDF links change and you consent to a cached version of the list (if they're hardcoded in JavaScript), that could be a problem πŸ€”

    I built the dumbest possible UI:

    function ConsentForms({ appointment }) {
    // makes an API call
    const { forms } = useConsentForms(appointment.id);
    return (
    <ul>
    {forms?.map((form) => (
    <li>
    <a href={form.url}>{form.name}</a> <Checkbox checked={form.checked} />
    </li>
    ))}
    </ul>
    );
    }

    Make an API call to get list of consent forms, iterate and render. The surrounding code took care of saving.

    We never had to touch this again. Run git blame and it says "swizec 2 years ago" except where we made style tweaks and changed links to open in a new tab.

    Business logic grows complex, always

    2 years ago the team was small and doing lots. We added a basic function on the backend with a hardcoded list of forms:

    const consentForms = {
    default: [ ... ],
    acupuncture: [ ... ],
    virtual: [ ... ]
    }
    exports.getForms = (appointment) => {
    if (isVirtual(appointment)) {
    return consentForms.virtual
    } else {
    if (isAcupuncture(appointment)) {
    return consentForms.acupuncture
    } else {
    return consentForms.default
    }
    }
    }

    Special forms for special appointments, defaults for the rest. Easy. Why didn't you do this on the frontend Swizec?

    Here's why πŸ‘‰ over the next 2 years, we:

    • added 5 more "special" appointments
    • added support for "special" appointments within virtual and in-person
    • added support for checking whether you've consented to this version of this form and pre-filling the checkmark appropriately

    That last one was a beauty of querying JSON data with SQL. Gotta love Postgres. Glad I wasn't the one figuring it out πŸ˜…

    The function grew to 70 lines of code backed by a 120 line config object. But the frontend never changed.

    Turn it into data!

    As the business grew, they wanted to make this list depend on which city you're in. Health care is funny like that.

    Our form logic would gain another dimension and explode in complexity. Too many combinations, too hard to test.

    And they warned about new even crazier ideas coming soon!

    We turned all our fancy business logic into a database table:

    • appointment type
    • location
    • is virtual
    • form id

    Now you can get the list of forms with a single query:

    select * from forms f, form_linkages fl where
    fl.appointment_type = ?
    fl.location = ?
    fl.is_virtual = ?
    fl.form_id = f.id

    Bam. Done.

    Analysts want to know which forms belong where? Query. Code needs a list of forms? Query. Business wants to update config? Query. New appointment type? Query. New location? Query. New form? Query. List of current forms in production? Query.

    And this whole time the UI didn't change. Because we kept it dumb.

    Cheers,
    ~Swizec

    PS: this puts us on the path towards a CMS so engineering never has to think about consent forms again ✌️

    Did you enjoy this article?

    Published on August 3rd, 2022 in Programming Lessons, Fullstack, Software Engineering,

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