Hey everyone, Alex here. Welcome back to another edition of Coding with Alex at sysseder.com.
If you've been scrolling through Hacker News today, you might have spotted a fascinating retrospective on Jef Raskin, the visionary who actually conceived and started the Macintosh project at Apple back in the late 1970s. While Steve Jobs gets most of the mainstream glory, Raskin was the true pioneer of cognitive-focused computing. He didn't just want to build a cool-looking computer; he wanted to build a machine that worked the way the human mind actually processes information.
Now, you might be thinking: "Alex, this is a cool history lesson, but I’m a backend engineer/web developer/DevOps specialist. Why should I care about 40-year-old human-computer interaction (HCI) theories?"
Here is why: We are currently living through a major Developer Experience (DX) crisis. We are drowning in complex cloud-native architectures, fragmented CLI tools, overly complex configuration files, and APIs that feel like they were designed by a hostile entity. When Raskin wrote his seminal book, The Humane Interface, he advocated for "monomodal" interfaces, the elimination of modal states, and reducing the cognitive load on the user.
Today, we’re going to look at how Jef Raskin's core philosophies can help us build better CLI tools, cleaner APIs, and highly intuitive developer workflows. It's time to apply cognitive engineering to our code.
The Golden Rule: Eliminating "Modes" in Developer Tools
One of Raskin’s biggest obsessions was the elimination of modal interfaces. A "mode" exists when the same user action produces different results depending on the system's current state.
The classic, albeit highly functional, example of a modal interface is the text editor vi. Pressing the "H" key might type the letter "h" (Insert Mode), or it might move your cursor to the left (Command Mode). If you forget which mode you are in, you end up corrupting your file.
While modal design works for lightweight text editors, it is a disaster for modern developer tools and APIs. Think about how many times you've run into state bugs in CLI tools. Let's look at a bad, modal CLI design vs. a clean, non-modal CLI design inspired by Raskin's philosophy.
The Anti-Pattern: The Modal CLI State
Imagine a CLI tool for managing cloud environments that requires you to "set" an active context before running commands. This is highly modal and prone to catastrophic human error (e.g., running a delete command in production because you forgot which mode you were in).
# BAD: The CLI relies on hidden global state (modes)
$ cloud-cli set-env production
Active environment set to: production
# ... three hours later, you forget you did this ...
$ cloud-cli destroy-all-nodes
Are you sure? (y/n): y
# Oops. You just wiped production because the CLI was in "production mode".
The Better Way: Explicit, Non-Modal Execution
Under a Raskin-inspired design, the state is explicit, transparent, and non-modal. The execution environment is tied directly to the command context, or explicitly demanded when destructive actions are taken, reducing cognitive dependency.
# GOOD: Explicit context, no hidden state
$ cloud-cli nodes destroy --env staging
# If you try to run a highly destructive command on production,
# the tool forces explicit verification of the target, not just a binary y/n.
$ cloud-cli nodes destroy --env production
[WARNING] You are trying to destroy nodes in PRODUCTION.
Please type the name of the environment to confirm: production
By forcing the developer to explicitly state their target, you remove the hidden "mode" of the CLI, saving countless engineering hours (and AWS budgets) from accidental command execution.
Locus of Attention and API Design
Raskin introduced the psychological concept of the Locus of Attention to computer science. The locus of attention is the single thing that a person is focusing on at any given moment. Human beings cannot actively focus on two things at once.
When developers use our APIs or libraries, their locus of attention is on solving their business problem. If your API forces them to shift their attention to the internal mechanics of your library, you have failed them from an HCI perspective.
Let's look at this through the lens of a Node.js library designed to process payments.
The High-Cognitive-Load API (Attention Fragmented)
In this example, the developer has to worry about connection pools, manual state initialization, and explicit error code parsing just to charge a card. Their locus of attention is dragged away from the business logic.
// BAD: High cognitive load, forces developer to manage library internals
import { PaymentGateway } from 'complex-pay-lib';
const gateway = new PaymentGateway();
await gateway.initializeSocketPool({ minConnections: 2, maxConnections: 10 });
const session = await gateway.createSession();
if (session.status === 'READY') {
const charge = await gateway.executeCharge(session.id, {
amount: 1000,
currency: 'usd',
source: 'tok_visa'
});
if (charge.errorCode === 0) {
console.log("Success");
} else {
// Developer has to manually map error codes
handleErrorCode(charge.errorCode);
}
}
await gateway.closeSocketPool();
The Humane API (Attention Focused)
A "humane" API design keeps the developer's locus of attention entirely on the business transaction. The library handles setup, connection pooling, teardown, and error bubbling internally.
// GOOD: Low cognitive load, keeps focus on the domain logic
import { PaymentClient } from 'humane-pay-lib';
const payments = new PaymentClient({ apiKey: process.env.PAY_API_KEY });
try {
const charge = await payments.charge({
amount: 10.00, // Using intuitive currency units instead of raw cents
currency: 'USD',
sourceToken: 'tok_visa'
});
console.log(`Charge successful: ${charge.id}`);
} catch (error) {
// Standard JS error handling, no manual code-checking required
console.error(`Charge failed: ${error.message}`);
}
By abstracting away the boilerplate infrastructure, we allow the developer to remain in a "flow state," keeping their locus of attention on the problem they are paid to solve.
Applying Raskin’s "Canon" of Interface Design to DevOps
In The Humane Interface, Jef Raskin proposed several rules that should govern any interface. Let's translate three of his core principles directly into rules for DevOps and infrastructure-as-code (IaC):
- A system should not allow you to make catastrophic errors: If a command can wipe a database, destroy an S3 bucket, or delete a cluster, it should require explicit, double-checked confirmation that cannot be automated away by a lazy flag (like
--forceor-y) unless specifically configured via environment variables. - Consistency of syntax: If
-vmeans--verbosein one of your internal CLI tools, it must not mean--versionor--volumein another. Create an internal style guide for your engineering team's custom tools. - Keep response times predictable: Raskin noted that variable response times are highly frustrating to the human brain. If an API call or CLI command takes longer than 200ms, always provide immediate visual feedback (a progress bar, spinner, or clear status stream) so the developer doesn't spam
Ctrl+Cin panic.
An Architecture for Responsive, Feedback-Driven Workflows
To implement Raskin's principle of feedback and predictable responsiveness, we should avoid "black-box" script execution in our CI/CD pipelines and internal CLI tooling. Here is a conceptual diagram of how a modern CLI tool should handle asynchronous, long-running tasks to keep the developer informed without cluttering their cognitive space:
[ Developer CLI Command ]
|
v
[ Client-Side Validator ] ---> (Instant Fail if Config Is Invalid)
|
+---> [ Spawns Background Worker ]
|
+---> [ Initiates CLI Terminal Spinner / Progress Bar ]
|
|<--- (Streams Real-Time State Events via gRPC/WebSockets)
v
[ Clean Terminal Update: "Step 3/5: Deploying Container..." ]
Instead of leaving a developer staring at a blinking cursor for three minutes (which induces anxiety and breaks focus), we build a system that respects human cognitive feedback loops.
Conclusion: The Human-Centric Developer
Jef Raskin's dream for the Macintosh was a computer that was completely intuitive—a tool that became an extension of the user's thought process. As software engineers, we often pride ourselves on our ability to navigate complex, Byzantine systems. But complexity isn't a badge of honor; it is a design failure.
Whether you are writing a custom Bash script for your deployment pipeline, designing a REST API for external developers, or writing a library for your internal team, ask yourself: Are there modes here that can confuse the user? Am I breaking their locus of attention? Is this interface humane?
By bringing Raskin's cognitive engineering principles into our development practices, we can build tools that don't just work, but are a joy to use.
What are your thoughts?
What is the worst "modal" experience you've had with a modern developer tool or API? How does your team tackle developer cognitive load? Let me know in the comments below, or drop us a line on Twitter/X at @sysseder!
Until next time, keep your interfaces clean and your code human-friendly.
— Alex