What Teaching My Kid Lego Robots Taught Me About API Design

Tandem Tinkering·January 19, 2025·5 min read

A 7-year-old debugging motor commands revealed everything wrong with our internal APIs.

Sunday afternoon. Lego Spike Prime spread across the kitchen table.

My daughter wanted the robot to drive forward, turn right, and stop.

Three commands. Forty-five minutes of debugging.

The Problem

Spike Prime uses block-based programming. Drag, connect, run. Simple for kids.

[Move forward for 2 rotations] → [Turn right for 90 degrees] → [Stop]

She ran it. The robot lurched forward, spun wildly, and kept spinning.

"It's broken," she said.

It wasn't broken. The mental model was.

The First Bug

"Move forward for 2 rotations" moves motor A for 2 rotations.

Our robot has two motors. A and B. Moving only A makes it turn, not drive straight.

The fix:

[Move motors A+B forward for 2 rotations]

She didn't know she needed to specify both motors. The block name suggests "the robot moves forward." The implementation requires "these specific motors move."

Lesson 1: API names should describe behavior, not mechanism.

"Move forward" is a lie. "Rotate motor A" is accurate but useless to a 7-year-old.

What should API names describe?

Behavior from the user's perspective, not the internal mechanism

Click to reveal answer

The Second Bug

"Turn right for 90 degrees" turns the robot's body 90 degrees.

Except it doesn't. It turns motor A backwards for enough rotations to equal 90 degrees of wheel rotation. Whether that equals 90 degrees of robot rotation depends on:

  • Wheel diameter
  • Distance between wheels
  • Surface friction

She set 90 degrees. The robot spun 270 degrees.

Lesson 2: Parameters should mean what users expect.

"90 degrees" should mean "the robot turns 90 degrees." Requiring users to calculate wheel ratios violates the abstraction.

The Third Bug

"Stop" stops the motors.

But "Turn right for 90 degrees" is a blocking operation that waits for completion.

So "Stop" runs after the turn completes. When motors are already stopped.

She added "Stop" because the robot was spinning. It didn't help because the problem was in "Turn," not in missing stop commands.

Lesson 3: Make state visible.

Is the robot currently moving? Is it waiting? Is it stopped? The programming interface showed nothing. We diagnosed by watching the physical robot.

The Fix

We abandoned the high-level blocks. Went to Python.

from spike import Motor, MotorPair

motors = MotorPair('A', 'B')
motors.move(20, 'cm')  # Move 20 centimeters
motors.move(0, 'cm', steering=100)  # Turn in place
# Stops automatically after each command

Explicit. Clear. Works.

But she's 7. She shouldn't need Python to make a robot drive straight.

The Parallel to Work

Monday morning. Code review for our internal service API.

// Create a thing
POST /resources
Body: { "name": "foo" }

// What gets created?
// - A resource in database X
// - A record in database Y
// - A message in queue Z
// - An entry in cache W

// What does the response tell you?
// - Resource ID
// - Nothing about Y, Z, or W

Same problems:

  1. Name doesn't match behavior. "Create resource" creates four things.
  2. Parameters don't mean what users expect. "name" becomes a slug, a display name, and a search key—each transformed differently.
  3. State is invisible. Did the queue message send? Is the cache populated? Client can't tell.

The Checklist

After the Lego session, I wrote this for our API reviews:

Naming

  • Does the operation name describe what the user gets, not how we implement it?
  • Would someone unfamiliar with internals predict the behavior from the name?

Parameters

  • Do parameter names mean what users expect?
  • If "degrees" means "wheel rotation degrees" not "robot rotation degrees," rename it.

State

  • Can users determine current state from the API?
  • Are operations blocking or async? Is it obvious which?

Failure

  • When something partially fails, what state is the system in?
  • Can users recover without understanding internals?

What three things should every API review check?

Names match user expectations, parameters mean what users think, and system state is visible

Click to reveal answer

The Ending

We got the robot working. Drive straight, turn 90 degrees (actual robot degrees), stop.

She said: "Why was that so hard?"

I said: "Because the people who made it thought about motors. They didn't think about robots."

She nodded like that made sense.

It's the same reason our APIs are hard. We think about databases and queues and caches. We forget the person just wants to create a resource.


A 7-year-old found three API design flaws in a children's programming tool.

Your users are doing the same thing with your API.

They're just too polite to say "it's broken."