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

    Stop SHOUTING = 'shouting'

    You've seen this pattern before – CONSTANT = 'constant' – common in dynamic languages.

    Please stop. It's a kludge.

    Why SHOUTING

    Shouting constants hail from a time when programming languages didn't have constants. You used ALL_CAPS to tell other programmers to treat this variable as a constant.

    Now it's common practice.

    Global constants like configuration variables are ALL_CAPS, local constants like const foo are camelCase or snake_case. Every language community is different. JavaScript likes camels, Python and Ruby like snakes πŸ€·β€β™€οΈ

    Why SHOUTING = 'shouting'

    Global constants like this are a poor man's type system. You see them a lot in early Redux tutorials, some XState tutorials, and other places where different areas of your codebase have to share a string value.

    The goal is to avoid typos, get IDE support for code completion, and ensure code changes together. Plus if you rename a value you totally don't have to go make changes everywhere.

    Sounds like a good idea at first

    Say you're building an appointment booking system and appointments have names for different services. You start like this:

    function doSomething(appointmentService) {
      if (appointmentService === "acupuncture") {
        // special treatment
      } else if (appointmentService === "covid") {
        // very special treatment
      }
    }
    

    Those 'acupuncture' and 'covid' strings look suspicious. You'll use them in a different function and then how do you ensure that it isn't 'acupuncture' in this method and 'acpuncture' in another?

    "A-ha!", you think, "I'll make a shared constant! That way they're gonna stay the same everywhere!"

    You make a new globals file.

    // globals.js
    const ACUPUNCTURE = "acupuncture";
    const COVID = "covid";
    
    // elsewhere
    import { ACUPUNCTURE, COVID } from "globals";
    
    function doSomething(appointmentService) {
      if (appointmentService === ACUPUNCTURE) {
        // special treatment
      } else if (appointmentService === COVID) {
        // very special treatment
      }
    }
    

    Problem solved, right? No.

    Why it doesn't work

    That looks like it solves the problem. But all you've achieved is create extra work.

    Let me explain.

    When you rename acupuncture to pokey_needle_stuff, for example, will you keep the constant name as ACUPUNCTURE? You could, but the confusion that would cause with anyone new entering the codebase ... oof

    Best keep the value and constant in sync. You now have to change 4 occurrences of "acupuncture" in even our smol example. A 4x increase in work πŸ€”

    "But Swiz, they're easier to find!"

    Are they? git grep "'acupuncture'" works the same as git grep ACUPUNCTURE.

    "Come on Swiz, at least I get undefined errors."

    Yes, if you run the code. Hope you have 100% test coverage otherwise it's a runtime error in production 🀞

    "Wait won't the compiler tell me stuff's undefined?"

    Not in a dynamic language. You need static analysis for that.

    "Okay, but at least it helps with code completion right?"

    Does it? How would your editor know that the appointmentService argument represents a specific bag of strings? It doesn't even know that's a string!

    And how do other programmers on your team know anything about appointmentService and what to expect from reading the code?

    Unless you import the constants nobody knows anything about them. Not your IDE, not you, not others.

    Yes once you import the correct constant, you get code completion for that whole file. Big whoop. πŸ™„

    Use the type system

    If you don't have a type system, use plain strings. At least they're less work.

    For TypeScript string union types fit best. Elsewhere you might use an enum of some sort.

    type AppointmentService = "acupuncture" | "covid";
    
    function doSomething(service: AppointmentService) {
      if (service === "acupuncture") {
        // special treatment
      } else if (service === "covid") {
        // very special treatment
      }
    }
    

    You get:

    • every programmer knows that service is a specific kind of string
    • your IDE knows what values to expect
    • change or drop a value and you get squiggly lines
    • build errors, no unit tests required ✌️
    • autocomplete
    • no extra work

    Look!

    Great autocomplete
    Great autocomplete
    Squiggly lines on change
    Squiggly lines on change

    😍

    You can add | string to AppointmentService, if you need an else statement that captures anything. You lose a lot of the IDE wonderfulness, but other programmers and future you know what to expect.

    Cheers,
    ~Swizec

    PS: yes a typed language gives you squiggly lines and build errors with the SHOUTING approach, but you miss out on the communicate-with-others aspect. Lean into your tools my friend

    Published on September 21st, 2021 in Opinions, TypeScript, JavaScript, Programming Lessons

    Did you enjoy this article?

    Continue reading about Stop SHOUTING = 'shouting'

    Semantically similar articles hand-picked by GPT-4

    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

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