Why Your RPG Code Should Read Like a Recipe (Not a Novel)

Coffee of the day: Green Mountain Horizon Blend. Smooth, balanced, and quietly reliable, it’s the kind of roast you can drink all morning without getting tired of it. It doesn’t overpower—it just supports, giving you steady energy to do the work that matters. In many ways, it reminds me of RPG at its best: not flashy, not complicated for its own sake, but dependable and full of hidden depth when you need it.

I’ve been writing RPG for over 30 years, and I’ve seen every flavor of bad code you can imagine. I’ve written most of it myself.

For years, I thought that was just how RPG worked. You had to be clever. You had to pack as much logic as possible into as few lines as possible. That was the craft.

Then I became a manager.

Now I spend more time reading code than writing it. And I’ve learned something that changed how I think about programming: good code isn’t clever. Good code is kind.

It’s kind to the person who has to debug it at 2 AM. It’s kind to the junior developer trying to learn your module. It’s kind to you, six months from now, when you’ve forgotten why you wrote it that way.

Good code reads like a recipe. Not a novel.


What I Mean by a Recipe

A recipe is predictable. You know where the ingredients are. You know what each step does. You can scan it quickly and understand the flow. There’s no mystery, no subplot, no twist ending. You follow it, and you get the result you expect.

A novel is different. A novel has context you need to hold in your head. It has characters with backstories. It builds tension. It rewards close reading. That’s fine for fiction. It’s a disaster for production code.

Most RPG code I see—and most I’ve written—leans too far toward the novel:

  • Long procedures with multiple responsibilities.
  • Variables reused across different contexts.
  • Logic that requires tracing through three files and two service programs to figure out what’s happening.

You can’t scan it. You have to study it. And most of the time, you don’t have time to study.


Four Principles of Recipe-Like Code

I’ve boiled it down to four simple principles. They’re not always easy, but they’re worth it:

  1. Short procedures with clear names
    • A procedure should do one thing well.
    • CalculateDiscount() should calculate a discount. Not validate customers, log transactions, and update files.
    • If you can’t name a procedure without “and,” it’s doing too much.
  2. Meaningful variable names
    • Forget the six-character limits of old RPG.
    • Use customerNumber, not CUSTNO.
    • Use invoiceAmount, not INVAMT.
    • Extra characters aren’t wasted—they’re an investment in clarity.
  3. Single responsibility for variables
    • Don’t reuse tempValue for three different purposes.
    • Don’t let returnCode mean five different things depending on context.
    • Every variable should have one clear job.
  4. Comments that explain why, not what
    • Code already tells me what you’re doing.
    • I want to know why.
    • “Checked for blank customer ID to avoid SQL error” is gold.
    • “Multiply by 1.05 instead of constant because of regulatory fee” is gold.

A Real Example

Here’s a procedure I inherited years ago. It calculated pricing for an order:

DCL-PROC ProcessOrder;

  DCL-PI *N;

    orderNumber CHAR(10);

  END-PI;

 

  DCL-S totalAmount PACKED(9:2);

  DCL-S discountAmount PACKED(9:2);

  DCL-S taxAmount PACKED(9:2);

  DCL-S customerType CHAR(1);

  DCL-S WK1 PACKED(9:2);

  DCL-S WK2 PACKED(9:2);

 

  // Get customer info

  EXEC SQL SELECT CUST_TYPE INTO :customerType

    FROM CUSTOMERS WHERE CUST_NO = :orderNumber;

 

  // Calculate total

  EXEC SQL SELECT SUM(LINE_TOTAL) INTO :totalAmount

    FROM ORDER_LINES WHERE ORDER_NO = :orderNumber;

 

  // Apply discount

  IF customerType = 'A';

    WK1 = totalAmount * 0.10;

  ELSEIF customerType = 'B';

    WK1 = totalAmount * 0.05;

  ELSE;

    WK1 = 0;

  ENDIF;

 

  discountAmount = WK1;

  totalAmount = totalAmount - discountAmount;

 

  // Calculate tax

  WK2 = totalAmount * 0.07;

  taxAmount = WK2;

  totalAmount = totalAmount + taxAmount;

 

  // Update order

  EXEC SQL UPDATE ORDERS

    SET ORDER_TOTAL = :totalAmount,

        DISCOUNT_AMT = :discountAmount,

        TAX_AMT = :taxAmount

    WHERE ORDER_NO = :orderNumber;

 

END-PROC;

It works. But it’s a slog to follow. WK1 and WK2 could mean anything. The procedure mixes data access, calculation, and persistence all in one place.

Here’s how I’d rewrite it:

DCL-PROC ProcessOrder;

  DCL-PI *N;

    orderNumber CHAR(10);

  END-PI;

 

  DCL-S customerType CHAR(1);

  DCL-S orderTotal PACKED(9:2);

  DCL-S discountAmount PACKED(9:2);

  DCL-S taxAmount PACKED(9:2);

  DCL-S finalTotal PACKED(9:2);

 

  customerType = GetCustomerType(orderNumber);

  orderTotal = CalculateOrderTotal(orderNumber);

  discountAmount = CalculateDiscount(orderTotal: customerType);

  taxAmount = CalculateTax(orderTotal - discountAmount);

  finalTotal = orderTotal - discountAmount + taxAmount;

 

  SaveOrderTotals(orderNumber: finalTotal: discountAmount: taxAmount);

 

END-PROC;

Same logic. But now it’s a recipe: ingredients + steps = result.

You can scan it and know what’s happening. Each subprocedure has a clear purpose. If you want to change discounts, you head straight to CalculateDiscount().


Why This Matters as a Leader

When I review code now, I’m not just looking for bugs. I’m looking at how the code treats the next person who reads it.

Clear code is an act of respect. It says: I care about the person who comes after me.

That mindset scales across a team. Clever tricks might save you 10 minutes today. Clear structure saves your team 10 hours next month.

I also find that once developers learn to write “recipe-like” code, they get better at explaining designs, writing docs, and communicating in general. Clarity is a habit, and it carries over.


The One Question I Ask

I end every code review with this:

Could someone read this at 2 AM during an outage and know what to fix?

If the answer is no, it’s not done. Even if it compiles. Even if it “works.”

Your code will outlive your memory of writing it. Someone else will debug it under pressure. Don’t leave them a novel. Leave them a recipe.


Final Sips

As I sip my Green Mountain Horizon Blend, I think about how the blend is smooth, balanced, and dependable—never too strong, never too thin. It’s the quiet backbone of a productive morning.

That’s exactly what your RPG code should be: dependable, predictable, and kind to the people who use it long after you’ve moved on.

Write like a chef, not a novelist. Leave a recipe worth following.

Comments