Swizec Teller - a geek with a hatswizec.com

    How defensive coding leads to bloat

    Defensive coding is an important lesson from Pragmatic Programmer, although not my favorite. It says that you should validate your inputs. Don't trust anyone!

    This is a good principle.

    Your software should validate inputs. A client may have bugs, an API could spazz out, a database or hard drive can get corrupt, a user might do something silly. Hell, sometimes clients and users are downright malicious trying to break your code.

    But on a team with lots of moving pieces and little big-picture understanding, defensively coding all the things leads to bload. Does every function in a chain really need to validate its inputs?

    How defensive coding goes wrong

    We once built an API that ran 29,000 database queries for every request. Thanks to defensive coding and what looked like clear sensible separation of concerns.

    Swizec Teller published ServerlessHandbook.dev avatarSwizec Teller published ServerlessHandbook.dev@Swizec
    The easiest way to write unreadable code is by splitting your functionality across 20 clean small functions.

    That example can't fit in a post you'll read. Too much background info and context required.

    Here's an example from a different part of that project ๐Ÿ‘‰ we built a UI that sorts the same array 5 times ๐Ÿคจ

    An innocent looking UI with a performance gotcha
    An innocent looking UI with a performance gotcha

    Designed by engineer ๐Ÿ’ช

    The UI lets you update and manage a person's schedule. You bulk upload a new list of availabilities via CSV, verify the update, and see the result in a calendar component off-screen after saving.

    Because we work as a team, each portion was built by someone else. Because we have good engineers, they all thought "Oh wait, I gotta validate my inputs!"

    You end up with a date range function that looks like this:

    function getDateRange(dates) {
    const sorted = dates.sort();
    return `Updating between ${sorted[0]} and ${sorted[sorted.length - 1]}`;
    }

    A component that lists updates like this:

    function DateList({ dates }) {
    const sorted = dates.sort();
    return (
    <ol>
    {sorted.map((date) => (
    <li>{date}</li>
    ))}
    </ol>
    );
    }

    A calendar that lists events like this:

    import groupBy from "lodash.groupby";
    function Calendar({ events }) {
    const sorted = events.sort();
    // groups preserve sort order internally
    const byDay = groupBy(sorted, (event) => event.day);
    return; // render UI
    }

    And a few others here and there.

    What's going on?

    Every engineer is following the Validate Your Inputs principle. When they need a sorted array and aren't sure if it's sorted โ€“ sort all the things!

    This makes sense when you think of each piece of code as a unit. Which they do because that's what they're currently working on and thinking about.

    Everything outside your function becomes The Untrusted Outside and you code accordingly.

    Repeat across time and engineers and you create a bloated codebase that spends half its time validating and re-validating the same data. ๐Ÿ’ฉ

    This tendency can lead to swallowed promises when functions handle their own errors instead of propagating them back up the stack.

    Solution: Validate the edges, trust the insides

    The solution is to more carefully design your units and agree on where the edges are.

    Where does new data enter your system? Validate there.

    • API request
    • user input
    • database or file read
    • URL params

    Validate inputs at those entry points and the rest of your code can assume they're valid. A type system can help you communicate that to other engineers.

    Cheers,
    ~Swizec

    PS: better unit definitions help with testing too! You can avoid the cult of TDD by testing the interfaces, not the implementation โœŒ๏ธ

    Did you enjoy this article?

    Published on November 15th, 2021 in Technical, Opinion, Mindset, Lessons

    Learned something new?
    Want to become an expert?

    Here's how it works ๐Ÿ‘‡

    Leave your email and I'll send you thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

    Join Swizec's Newsletter

    And get thoughtful letters ๐Ÿ’Œ on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.

    "Man, love your simple writing! Yours is the only newsletter I open 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 14,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ย โค๏ธ

    Created by Swizec with โค๏ธ