Skip to content
DevMeme
A Dog's Perspective on Global Variables
CodeQuality Post #101, on Feb 12, 2019 in TG

A Dog's Perspective on Global Variables

Why is this CodeQuality meme funny?

Level 1: Even the Dog Knows Better

Imagine one shared family toothbrush sitting in the hallway, and anyone — your brother, the mailman, a stranger — can use it or swap it for a different one whenever they want, without telling you. That's a global variable: one thing that everybody in the program can grab and change secretly, so when something goes wrong, nobody knows who did it. The meme is funny because it borrows a tearjerker movie where a sweet dog ponders the mysteries of human behavior, and the great unknowable mystery turns out to be... programmers doing the one thing every programmer is told not to do. The dog isn't confused because it's a dog; it's confused because there is no good explanation — and the dog's gentle, disappointed face says what every code reviewer is thinking.

Level 2: What the Dog Already Knows

A global variable is a variable declared outside any function, visible and modifiable from everywhere in the program. The opposite is a local variable, which exists only inside the function that created it — this visibility boundary is called scope.

counter = 0  # global — everyone can touch this

def handle_request():
    global counter      # Python makes you confess
    counter += 1        # who else changes this? nobody knows.

def reset_metrics():
    global counter
    counter = 0         # surprise! this just broke handle_request's count

Why your first team lead will wince at this:

  • You can't tell who changes it. Any of 200 files might write to counter. Debugging means searching the whole codebase instead of one function.
  • Tests interfere with each other. Each test inherits whatever value the previous test left behind — a classic "works alone, fails in the suite" rite of passage.
  • Name collisions. Two modules both define a global status, and one silently clobbers the other — that's scope pollution.

This is a big part of what people mean by code quality: not whether the code runs, but whether the next person can change it without stepping on a landmine. The fix is usually boring and beautiful — pass values as parameters, return results, or hand dependencies in explicitly — so every function honestly declares what it touches.

Level 3: Wormholes Between Every Bug

The format here matters: three melancholy stills from A Dog's Purpose, a car receding down a prairie road while the narrating golden retriever muses — "Humans are complicated." / "They do things dogs can't understand." — before the gut-punch subtitle lands: "like declaring global variables". The movie's wistful, reincarnation-themed dog narration gets recast as bafflement at one of software's oldest code smells, and the framing implies something deliciously cutting: a creature that eats socks has better instincts about scope than your coworker.

Why do globals earn this much contempt? Because a mutable global variable is invisible coupling made flesh. Every function that reads it has a hidden input; every function that writes it has a hidden output. Your call signatures lie. A function that claims f(x) -> y is actually f(x, entire_world_state) -> (y, possibly_mutated_world_state), and nothing in the type system, the code review diff, or the documentation forces anyone to admit it. This is the root of the classic action at a distance bug: module A misbehaves because module Q, three layers away, scribbled on shared state last Tuesday.

The senior-engineer trauma compounds from there:

  • Testing collapses. Globals are ambient state, so tests stop being independent. Test 14 passes alone, fails after test 9, and now you're bisecting test ordering instead of code. Anyone who has fought a flaky CI suite caused by a cached singleton knows this taste.
  • Concurrency turns it radioactive. A global written from two threads without synchronization is a data race — undefined behavior in C/C++, a Heisenbug generator everywhere else. The bug reproduces only under production load, never in your debugger, which is of course where bugs prefer to live.
  • Initialization order becomes a minefield. C++ even has a named disaster for this — the static initialization order fiasco — where two globals in different translation units depend on each other and the language shrugs at which one constructs first.
  • They never die. Locals are born and destroyed with scope; a global persists for the whole program's lifetime, accumulating stale state like sediment. There's a dark resonance with the source film: the dog reincarnates across lives, and a global's corrupted value likewise survives across every "life" of your request handler.

And yet globals persist, because the incentive structure favors them: passing a config or a logger through eleven layers of function parameters is tedious, and global db_connection works right now. Whole architectural movements — dependency injection, the (still side-eyed) singleton pattern, twelve-factor config — are essentially the industry's long apology tour for global. Python literally makes you type the keyword global to mutate one, a confession box built into the syntax.

Description

A three-panel meme taken from a scene with a dog. The first two panels show a long, empty rural road with subtitles. The first reads, 'Humans are complicated.' The second reads, 'They do things dogs can't understand.' The final panel is a close-up of a golden retriever looking thoughtfully into the distance, with the punchline as a subtitle: 'like declaring global variables'. The humor lies in framing a widely recognized programming anti-pattern through the simple, innocent perspective of a dog. For experienced developers, the joke is that using global variables - which can create unpredictable side effects and make code notoriously difficult to debug - is such a fundamentally bad idea that even a creature with no concept of coding would find it baffling and unnecessarily complex

Comments

8
Anonymous ★ Top Pick Global variables are the 'trust me, bro' of software architecture. They seem convenient at first, but eventually, you'll find them mutating state at 3 AM from a part of the codebase you forgot existed
  1. Anonymous ★ Top Pick

    Global variables are the 'trust me, bro' of software architecture. They seem convenient at first, but eventually, you'll find them mutating state at 3 AM from a part of the codebase you forgot existed

  2. Anonymous

    Even the dog knows to keep state on a short leash - you’ve let your globals roam every thread like they’re somehow immune to race conditions

  3. Anonymous

    The same developer who declares global variables is now architecting your microservices mesh and wondering why every service knows about UserAuthenticationStatus

  4. Anonymous

    The dog is right to be confused - a global variable is just a wormhole between every bug in your system, and unlike the dog, it never dies between reincarnations

  5. Anonymous

    Global variables are the programming equivalent of leaving your house keys under the doormat and telling everyone where they are - sure, it's convenient for you right now, but you've just created a maintenance nightmare where any part of your codebase can reach in and modify state at will, making debugging feel like detective work in a system where everyone's a suspect and the crime scene is constantly being contaminated

  6. Anonymous

    Declare a global and you’ve just speed-run the path from “pure function” to “why is this flaky only on CI?”

  7. Anonymous

    Globals are singletons without shame - great until the C++ static-init order or Node’s require cache makes your test suite Schrodinger’s flake

  8. Anonymous

    Globals: the original shared mutable state that turns single-threaded bliss into concurrency roulette

Use J and K for navigation