Best Practices & Common Pitfalls

40.1 Best practices

Put OPTION _EXPLICIT at the top of every QB64-PE program (Option Explicit in VBA, Option Strict On in VB.NET).

Declare variables with DIM ... AS instead of relying on suffixes and default SINGLE.

Use CONST for every magic number: screen size, speeds, limits, file names.

Keep the main program short: it should read like a table of contents of SUB calls.

Pass data through parameters; keep DIM SHARED globals few and clearly named.

Use LONG instead of INTEGER unless you need 16-bit storage; DOUBLE for calculations needing precision; integer cents for money.

Always CLOSE files, _FREEIMAGE images, _SNDCLOSE sounds, and _MEMFREE memory blocks.

In loops that wait or animate, use _LIMIT (or SLEEP) so the CPU isn't pegged at 100%.

Validate all user input and file data; check _FILEEXISTS before opening for input.

Use FREEFILE rather than hard-coded file numbers in reusable procedures.

Indent blocks consistently, comment *why* rather than *what*, and keep procedures under about one screen.

Keep backups or use version control (Git works perfectly with .bas files).

40.2 Common pitfalls

Why it happens Misspelled variable silently equals 0 OPTION _EXPLICIT

a% and a! treated as different variables suffix is part of the name pick one style; use DIM... AS Overflow at 32,768 INTEGER is 16-bit use LONG / _INTEGER64 Procedure changes the caller's variable copy to a local, or pass an expression (x) "Parameter type mismatch" by-reference argument of a different type match types or pass an expression

Using a keyword as a name (name$, data(), width) choose another name (userName$, values(), wd) Leading space in STR$ output sign position reserved _TRIM$(STR$(n)) or LTRIM$ INPUT splits text at commas comma is a field separator

Fixed-length strings with trailing spaces RTRIM$ before comparing or printing

IF a AND b crashes on out-of-range index no short-circuit evaluation nested IF or _ANDALSO NOT x unexpectedly true bitwise NOT on non -1/0 values compare explicitly (x = 0) Float loop misses its last value binary rounding of 0.1 integer loop counter RND gives the same numbers every run RANDOMIZE TIMER once at startup Flicker in animation drawing on the visible page _DISPLAY once per frame

Arrow keys not detected by INKEY$ = "H" extended keys are two characters check LEN(k$) = 2 and RIGHT$(k$, 1) REDIM erases the array REDIM without preserve REDIM _PRESERVE Memory grows over time images/sounds created every frame and never freed create once, reuse, free on exit

SUBs placed before main code fail to compile QB64 layout rule main code first, then SUBs/FUNCTIONs Error handler label inside a SUB

QBasic/QB64 handlers must be module-level put the handler in the main module Game runs too fast on new PCs _LIMIT or delta time