Layout is part of the program
In most languages, white space is decoration. In Befunge it is the program. The position of a cell decides what runs before it and after it, so moving a character is a change in behavior and not just in appearance. That makes layout both more important and more fragile than in a conventional language, and it means that a few disciplined habits are worth more than cleverness.
Esoteric languages are hard to read in general, and the reasons are covered in the page on code readability. Layout cannot remove the difficulty, but it can keep it from growing as the program does.
Prefer straight, short routes
The easiest paths to follow are straight lines with a small number of turns. A few rules of thumb follow from that.
- Run the main path along one row or column as long as you can, and turn only where something meaningful happens.
- Make loops rectangles. A loop that goes out along one row and returns along the next is easy to see; a loop that doubles back through the middle of other code is not.
- Avoid crossing paths. Where two routes must cross, a skip over the crossing cell is better than letting both execute whatever sits there, and the trampoline instruction guide shows how.
If a path starts to look like a spiral, step back and reconsider the order of operations. A different arrangement of the same steps often untangles it.
Align things that go together
Align turning arrows in columns. If a v sends the pointer down and a ^ brings it back, putting them in the same column or in neighboring ones makes the path visible at a glance. Similarly, keep matching pieces on the same row: a loop’s test and its return arrow, or the opening and closing of a string.
Here is the star-printing loop from the guide on Befunge loops, laid out so the rectangle is visible.
4>"*",1-:#v_@
^ <
The 4 sits at the start, the body runs east along the top row, and the return runs west along the bottom. Even without tracing it, you can see that the ^ and < bracket the loop. If the < were two columns off, the program would break and also look wrong, which is a useful warning in itself.
Separate sections with empty space
A blank row or a few empty columns between sections tells the reader that the pieces are independent. A program that reads input, processes it and prints the result can be built as three bands with a clear entry and exit for each. Empty cells cost nothing at run time, since the pointer passes over them without effect, but be sure that no path runs through a gap by accident. In Befunge-93 the grid is limited to 80 columns by 25 rows, so there is a budget for spacing, though it is easy to stay inside it for small programs. Those Befunge-93 limits are one reason larger projects sometimes move to Funge-98.
Reserve a data area
If the program uses the get and put instructions to store values, keep them in a region no execution path touches. A corner or the bottom rows work well. This prevents two kinds of bugs: a value that overwrites an instruction, and an instruction the pointer runs into that was meant to be data. The guide on grid variables describes how to choose cells. Keep a note, outside the program, of what each cell stores. A table with coordinates and meanings is enough.
Put notes where the pointer never goes
Befunge has no comment syntax, but any cell the pointer never reaches is effectively a comment. You can write labels or short explanations in a block that no path crosses. This is only safe if you are certain the area is unreachable, so be careful about wrap-around. A path that leaves the grid reappears on the opposite side, and a note placed there can start running. The same care applies to dead code, which has its own page. Do not put notes where the program also writes data.
If a note contains a character such as a double quote, a plus sign or a letter that happens to be an instruction, it is still harmless when unreachable. The risk comes only from reaching it.
Make strings stand out
Strings are among the easiest parts of a program to spot and the easiest to lose track of. Put each on its own row or segment, with a little space before and after. Since string mode pushes characters in order, the last character is on top, and printing happens in reverse. Writing the string backward, or marking the print section clearly, helps the reader notice that. The guide on string mode covers this in detail.
Keep one idea per row, where you can
When it is practical, give each row or each short stretch a single purpose, such as read, test or print. A reader can then find a feature by looking at one place. It is tempting to compress everything into fewer rows to be impressive. That is the goal of code golf, but it makes the program harder to maintain, so decide which you are after before you start.
Testing the layout
After a layout change, rerun the program, and practice tracing by hand once at the points you moved. Two checks catch most mistakes: whether the pointer enters each section where you expect, and whether the stack height at the end of each section matches your plan. If you have a visual interpreter or a trace tool, flow diagrams of the pointer’s path show layout problems quickly, because stray crossings stand out.
A tidy layout will not make Befunge easy, but it makes it learnable, which is what you are aiming for when you return to your own code after a few weeks.